2017-12-11 4 views
0

내가 전체 스크립트 코드의 관련 부분을 인용 파이썬 소켓을 (사용하여 기본 클라이언트/서버 인터페이스 작성한받을 https://github.com/mydomo/ble-presence/blob/master/clients/DOMOTICZ/ble-presence/plugin.py를)Python3 소켓, 소켓에 임의의 부분적인 결과는

문제는 스크립트가 몇 시간 동안 실행되고 결과 목록이 커지면서 응답이 정확해야하며, 완료되지 않은 다른 시간은 잘랐습니다 ... 소켓이 아무 이유없이 종료 된 것처럼 임의적입니다. 이전 또는 응답은 완전히 읽을 수 없습니다.

당신이 날 도와 주실 수 있습니까?

SERVER :

def client_thread(conn, ip, port, MAX_BUFFER_SIZE = 32768): 
    # the input is in bytes, so decode it 
    input_from_client_bytes = conn.recv(MAX_BUFFER_SIZE) 

    # MAX_BUFFER_SIZE is how big the message can be 
    # this is test if it's too big 
    siz = sys.getsizeof(input_from_client_bytes) 
    if siz >= MAX_BUFFER_SIZE: 
     print("The length of input is probably too long: {}".format(siz)) 

    # decode input and strip the end of line 
    input_from_client = input_from_client_bytes.decode("utf8").rstrip() 

    res = socket_input_process(input_from_client) 
    #print("Result of processing {} is: {}".format(input_from_client, res)) 

    vysl = res.encode("utf8") # encode the result string 
    conn.sendall(vysl) # send it to client 
    conn.close() # close connection 
##########- END FUNCTION THAT HANDLE SOCKET'S TRANSMISSION -########## 

def start_server(): 
    global soc 
    soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    # this is for easy starting/killing the app 
    soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    #print('Socket created') 
    try: 
     soc.bind((socket_ip, socket_port)) 
    # print('Socket bind complete') 
    except socket.error as msg: 
    # print('Bind failed. Error : ' + str(sys.exc_info())) 
     sys.exit() 


    #Start listening on socket 
    soc.listen(10) 
    #print('Socket now listening') 

    # for handling task in separate jobs we need threading 
    #from threading import Thread 

    # this will make an infinite loop needed for 
    # not reseting server for every client 
    while (not killer.kill_now): 
     conn, addr = soc.accept() 
     ip, port = str(addr[0]), str(addr[1]) 
     #print('Accepting connection from ' + ip + ':' + port) 
     try: 
      Thread(target=client_thread, args=(conn, ip, port)).start() 
     except: 
      print("Terible error!") 
      import traceback 
      traceback.print_exc() 
soc.close() 

CLIENT : 당신은()를 여러 번 RECV를 호출하여 전체 메시지를 받고 시도해야하므로 보증 첫 번째 호출에 전체 메시지를 수신하지 않습니다 recv()

soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
SERV_ADDR = str(Parameters["Address"]) 
SERV_PORT = int(Parameters["Port"]) 
soc.connect((SERV_ADDR, SERV_PORT)) 

if BATTERY_REQUEST == True: 
    clients_input = str(BATTERY_DEVICE_REQUEST) 
else: 
    clients_input = "beacon_data" 

soc.send(clients_input.encode()) # we must encode the string to bytes 
result_bytes = soc.recv(32768) # the number means how the response can be in bytes 
result_string = result_bytes.decode("utf8") # the return will be in bytes, so decode 
+1

'sys.getsizeof()'메소드를 잘못 사용하고 있습니다. 'len (input_from_client_bytes)'를 사용하여'input_from_client_bytes'의 길이를 얻습니다. –

답변

0

방법.
recv()가 빈 문자열을 반환하면 클라이언트 측에서 연결이 닫힙니다.

당신이 data에 클라이언트에서 전체 스트림을 얻을 수있는이 while 루프를 사용 :

data = b'' # recv() does return bytes 
while True: 
    try: 
     chunk = conn.recv(4096) # some 2^n number 
     if not chunk: # chunk == '' 
      break 

     data += chunk 

    except socket.error: 
     conn.close() 
     break 
+0

클라이언트 측의 서버에서 recv stream과 같은 while 루프를 사용하십시오. –

0

TCP는 완전한 메시지를 구성하는 것에 대한 개념이 없습니다 의미 스트리밍 프로토콜입니다. 완전한 메시지를주고받을 수 있도록 TCP 위에 자신의 메시지 프로토콜 계층을 구현해야합니다. 완전한 메시지가있을 때까지받은 데이터를 버퍼링해야하며 완전한 메시지가 무엇인지 정의해야합니다. 일부 옵션 :

  1. 고정 길이 메시지를 보냅니다.
  2. 메시지의 길이를 나타내는 고정 된 수의 바이트를 보낸 다음 메시지를 보냅니다.
  3. 메시지를 별도의 센티널 바이트로 분리하십시오.

그런 다음 recv을 호출하고 버퍼에 전체 메시지가 나타날 때까지 결과를 누적하십시오.

+0

클라이언트 측에서 연결을 닫는 것만으로도 1, 2, 3이면 충분합니다. –

+0

@Elis 여러 메시지를 보낼 수 있으면 충분하지 않습니다. –

+0

기존의 [응용 프로그램 계층] (https://en.wikipedia.org/wiki/Application_layer)을 사용하거나 여러 메시지를주고받을 수있는 간단한 응용 프로그램을 직접 구현해야합니다. 이 경우 1, 2, 3은 시작하기 좋은 지점입니다. –