2011-12-25 5 views
12

나는 간단한 파이썬 서버와 클라이언트를 가지고있다.클라이언트가 소켓을 닫을 때까지 소켓을 열어 두는 방법은 무엇입니까?

서버 :

import SocketServer 
import threading 


class MyTCPHandler(SocketServer.BaseRequestHandler): 
    def handle(self): 
     self.data = self.request.recv(1024).strip() 
     print str(self.client_address[0]) + " wrote: " 
     print self.data 
     self.request.send(self.data.upper()) 


if __name__ == "__main__": 
    HOST, PORT = "localhost", 3288 
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler) 
    server.serve_forever() 

클라이언트 :

여기
import socket 
import sys 
from time import sleep 

HOST, PORT = "localhost", 3288 
data = "hello" 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

try: 
    sock.connect((HOST, PORT)) 
    sock.send(data + "\n") 
    received = sock.recv(1024) 

    sleep(10) 

    sock.send(data + "\n") 
    received = sock.recv(1024) 

    sleep(10) 

    sock.send(data + "\n") 
    received = sock.recv(1024) 

finally: 
    sock.close() 

입니다 출력 내가 얻을 :

서버 :

>python server.py 
127.0.0.1 wrote: 
hello 

클라이언트 :

>python client.py 
Traceback (most recent call last): 
    File "client.py", line 18, in <module> 
    received = sock.recv(1024) 
socket.error: [Errno 10053] An established connection was aborted by the software in your host machine 

나는 리눅스 컴퓨터에서도이 도구를 사용해 보았습니다. 서버가 하나의 메시지 만 수신하면 두 번째 메시지의 recv 문에서 오류가 발생합니다. 나는 방금 파이썬에서 네트워킹을 배우기 시작했는데, 서버가 어떤 이유로 소켓을 닫고 있다고 생각한다. 이 문제를 어떻게 해결합니까?

+0

도움이 될 수 있습니다. http://stackoverflow.com/a/20421867/2290820 – user2290820

답변

20

MyTcpHandler 객체는 각 연결에 대해 생성되고, handle은 클라이언트를 처리하기 위해 호출됩니다. 연결이 종료 될 때 handle 반환, 당신은 handle 메소드 내 클라이언트에서 전체 통신을 처리 할 수 ​​있도록 :

class MyTCPHandler(SocketServer.BaseRequestHandler): 
    def handle(self): 
     while 1: 
      self.data = self.request.recv(1024) 
      if not self.data: 
       break 
      self.data = self.data.strip() 
      print str(self.client_address[0]) + " wrote: " 
      print self.data 
      self.request.send(self.data.upper()) 

참고 : recv 반환 '' 클라이언트가 연결을 닫습니다, 그래서 나는 recv.strip() 이동 따라서 클라이언트가 공백 만 보내는 것으로 인해 잘못된 경보가 발생하지 않습니다. 유사한 문제에

+0

답변 해 주셔서 감사합니다. – Bruce

1

내가 마지막으로 SocketServer을 사용한 이후로 수 년이 지난 것을인지 할 것이므로 문제를 해결하기 위해 더 많은 관용적 접근법이있을 수 있습니다.

클라이언트는 단일 연결을 열고 세 개의 데이터 집합을 보내고 세 개의 데이터 집합을받습니다. (당신이 소켓에 receive()를 호출하면 희망 TCP 스택은 버퍼링 된 데이터를 전송합니다.) 서버가 완전히 클라이언트 연결을 처리하기 위해 기대하고있다

, 처음부터 끝까지, 그것이 SocketServer 콜백 메커니즘에서 호출 될 때. 현재 수업은 약간의 입출력을 수행 한 다음 이 종료되고이 종료됩니다. 당신은 더 많은 일을하도록 서버의 콜백을 확장 할 필요가 :

class MyTCPHandler(SocketServer.BaseRequestHandler): 
    def handle(self): 
     self.data = self.request.recv(1024).strip() 
     print str(self.client_address[0]) + " wrote: " 
     print self.data 
     self.request.send(self.data.upper()) 
     foo = self.request.recv(1024).strip() 
     self.request.send(foo.lower()) 
     bar = self.request.recv(1024).strip() 
     self.request.send("goodbye " + bar) 
+0

답변 주셔서 감사합니다. – Bruce

1

여기 error: [Errno 10053]

또한 같은 일을 시도하고 같은 오류가 발생했습니다.

이 오류 보여이 같은 간단한 코드가있는 경우 : 당신이 얼마나 수신기, 있는지 확인하기 위해 소켓 객체와는 보낼 수 AMT를 작성하고 서버에서 다시 에코 경우

import socket 

host = 'localhost' 
port = 5001 
size = 102400 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect((host,port)) 
for msg in ['Hello, world','Test','anything goes here']: 
    s.send(msg) 
    data = s.recv(size) 
    print 'Received:', data 
s.close() 

는 1024 ~ 102400 (이 코드에서) 정도 다. 즉 소켓이 닫히지 않아야하지만 내 Windows OS에서 다시 서버 측은 클라이언트가 보내는 모든 데이터를 수신하고 인쇄하지만 클라이언트 측에서는이 오류가 발생합니다.

그러나 클라이언트가 한 번만 연결할 수 있고 한 번만 보내고받을 수 있다면 설계 방법입니다. 이 시도는 오류없이 작동 : 하나의 소켓 객체가 데이터를주고받을 번만 작동하는 경우

for msg in ['Hello, world','Test','anything goes here']: 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.connect((host,port)) 
    s.send(msg) 
    data = s.recv(size) 
    s.close() 
    print 'Received:', data 

나는 확실하지 않다.

업데이트 문제는 클라이언트 소켓 당 용량이 고정 된 버퍼 크기에 따라 데이터를 수신하는 것이라고 생각합니다. 위의 두 번째 코드 단편이 작동하여 서버에 새로운 클라이언트 연결 소켓이 만들어집니다. 하지만 그런 식으로 소켓이 많이 소모 될 것입니다.

대신 다음 코드는 사용중인 크기의 amt를 확인하여이 문제를 해결했습니다. 지정된 양을 초과하면 클라이언트에 새 소켓을 만들고 메시지가 전송되는지 확인합니다. 사실 문제는 서버 코드와 관련이 있지만 해결되었습니다.

크기 = 10

이 코드는 빠른 아기 시도입니다. 나는 그것을 더 잘 이해하고 최적화 할 것이라고 확신합니다!

클라이언트 코드 :

messag = ['Hello, world', 'Test', 'anything goes here'] 

def client_to_server(messag,host,port,size): 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.connect((host, port)) 
    countmsg = 0 
    restmsg = '' 
    for msg in messag: 
     strl = tmsg = msg 
     if len(restmsg): 
      tmsg = restmsg + ' ' + msg 
     countmsg = len(tmsg) 
     if countmsg <= size: 
      pass 
     else: 
      restmsg = tmsg[size:] 
      tmsg = tmsg[:size] 
      #s.close() 
      countmsg = len(tmsg) 
      #s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
      #s.connect((host, port)) 
     print 'Sending to server msg {}'.format(tmsg) 
     s.send(tmsg) 
     # s.settimeout(1) 
     try: 
      data = s.recv(size) 
      print 'Received:', data 
      if strl == data: 
       print strl,data 
       countmsg = 0 
       restmsg = '' 
     except (socket.error), e: 
      print e.args,e.message 
      s.close() 
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
      s.connect((host, port)) 
    s.close() 
    if restmsg: 
     client_to_server([restmsg],host,port,size) 
    return 


client_to_server(messag,host,port,size) 

서버 코드 :

size = 1024 #This has to be bigger than client buf size! 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind((host, port)) 
s.listen(backlog) 
while True: 
     #this is what accepts and creates a P2P dedicated client socket per socket 
     client, address = s.accept() 
     try: 
      data = client.recv(size) 
      while data or 0: 
       print "Client sent {} | Server sending data to client address {}".format(data, address) 
       client.send(data) 
       data = client.recv(size) 
      else: client.close() 
     except (socket.error), e: 
      client.close() 
      print e.args, e.message 

그것을 밖으로보십시오. 동일한 소켓을 사용합니다.

관련 문제