2017-03-15 1 views
2

내 server.py 파일에 다음 코드가 있습니다. 클라이언트로부터 데이터를 수신하기 위해 대기 중입니다. 또한 나는 어떤 http 라이브러리도 사용할 수 없다. 만 소켓 라이브러리 :소켓 API를 사용하여 기본 HTTP 서버 작성

def handle_client(conn, addr): 
    print ('New client from', addr) 
    x = [] 
    try: 
     while True: 
      data = conn.recv(1024) 
      decoded_data = data.decode('utf-8') 
      # if "GET/" in data.decode('utf-8'): 
      # handle_client_get(conn) 
      # else: 
      if data: 
       print(data) 
       x.append(decoded_data) 
      else: 
       print(x) 
       break 
    finally: 
     print("in close now") 
     conn.close() 

오전 데 문제는 내가 수동으로 CTRL + C 클라이언트를 닫으면 나는 단지 print(x) 문에 도달 할 수 있다는 것입니다. 그렇지 않으면 인쇄되지 않습니다.

왜 그런가요?

답변

당신은 전송 데이터가 정확하게 수신 된하도록 클라이언트에 승인을 보내야합니다.

연결을 종료하고 제한 시간을 기다리지 않습니다. Expect: 100-continue 그리고 당신은 클라이언트

+0

다른 쪽이 소켓을 닫지 않았습니다. 수신 채널이 상대방에 의해 종료 된 후에 만 ​​비어있는 recv를 받게됩니다. – tdelaney

+0

하지만 데이터가 클라이언트에서 전송되지 않는 경우 어떻게 중단시킬 수 있습니까? 연결이있는 한 클라이언트에서 데이터가 전송되지 않아도 else 문을 사용할 수 없다는 말입니까? – user3450754

+0

더 나은 답변을 얻으려면 프로토콜을 정의해야합니다. 더 많은 데이터를 수신하는 데 예상되는 시간대가 있습니까? 작업이 완료되면 서버가 연결을 계속 열어 두는 이유는 무엇입니까? 일부 프로토콜 (예 : telnet 또는 ssh)은 몇 분 또는 몇 시간 동안 데이터가 없을 수 있지만 연결이 유효하며 데이터가없는 기간이 지나면 더 많은 데이터가있을 수 있습니다. – dsh

답변

0

편집 다시 승인을 보낼 필요가 :

이 클라이언트가 전송되기 때문에이는 HTTP 서버 인 만 사용하여 수행 할 것입니다 언급 이제
socket 라이브러리에서이 문제가 해결 될 때까지 while 블록을 제거하는 것과 같은 단계에서 프로그램에서 특정 복잡한 요소를 제거하는 것이 좋습니다.

server.py

def handle_client(conn, addr): 
    print ('New client from', addr) 
    x = [] 
    try: 
     data = conn.recv(1024) 
     decoded_data = data.decode('utf-8') 
     if data: 
      print(data) 
      x.append(decoded_data) 
     else: 
      print(x) 
      break 
    finally: 
     print("in close now") 
     conn.close() 

원래 답변 :

보낸 사람의 말에 추가 \n를 보내는 시도하고 버퍼 뭔가에 남아있는 데이터를 보낼 나중에 flush 기능을 사용 like :

sender.py

def send_data(data,sock_obj,addr): 
    sock_obj.send(data+"\n") 
    sock_obj.flush() 
+0

내가 보내는 클라이언트에 그런 세부 정보를 추가 할 수 없도록 cURL을 사용하고 있습니다. – user3450754

+0

클라이언트에서 보낸 모든 데이터를 얻으려면 while 루프가 필요하지 않습니까 ?? – user3450754

1

얼마나 많은 데이터를 읽을 지 알려주는 프로토콜을 구현해야합니다. HTTP의 경우, 요청은 CRLF로 구분 된 헤더로 시작하며이를 통해 원하는 정보를 얻을 수 있습니다.

w3.org에는 http request protocol에 대한 설명이 있습니다. 더 복잡하기는하지만 여기서 구현하고자하는 것보다 복잡하다. 한 번에 한 문자 씩 소켓을 읽고 비어있는 \n 터미네이션 라인을 찾음으로써 요청 헤더를 가져 오는 예제를 포함시켰다. 한 번에 한 문자 씩 읽음으로써 필자 만의 라인 버퍼를 구현할 필요가 없습니다.

첫 번째 줄은 요청 방법이고 나머지 줄은 요청에 포함 된 다른 매개 변수입니다. 예를 들어, POST의 경우 소켓에서 더 많은 데이터를 읽을 수 있습니다.

import re 

def handle_client(conn, addr): 
    print ('New client from', addr) 
    header = [] 
    line = [] 
    try: 
     # read ascii http client header. 
     while True: 
      c = conn.recv(1) 
      # check for early termination 
      if not c: 
       return None 
      # check for end of request line 
      elif c == b"\n": 
       # make line a string to add to header 
       line = ''.join(line).decode('ascii').strip() 
       # are we at the empty line signalling end-of-header? 
       if not line: 
        break 
       header.append(line) 
       line = [] 
      # filter out \r 
      elif c == b"\r": 
       continue 

     # request is first line of header 
     request_line = header.pop(0) 
     method, uri, http_version = re.split(r" +" request_line) 

     if method.upper() == "GET": 
      # this function needs more parameters... the uri to get and the protocol 
      # version to use. 
      handle_client_get(...) 
    finally: 
     print("in close now") 
     conn.close() 
+0

그러면 클라이언트가 아스키 문자가 포함 된 파일을 보내는 게시 요청을합니다. 모든 정보를 얻지 만 모든 정보를 얻 자마자 연결을 닫지 않습니다. 마치 더 많은 데이터를 기다리는 것과 같습니다. 그게 내 문제 야. – user3450754

+0

헤더에는 ascii 나 다른 것을 알려주는'Transfer-Encoding'과 읽을 바이트 수를 알려주는'Content-Length'가있을 것입니다. 그러나 모든 일 http와 마찬가지로, 거기에 합병증이있을 수 있습니다. 섹션 _4.4 메시지 길이 _ [여기] (https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3)를 읽으십시오. – tdelaney

+0

그것은'Expect : 100-continue'와 관련이 있습니다. 문제가 무엇인지 발견했습니다. – user3450754