2011-12-17 22 views
4

背景
我有一个简单的套接字服务器设置,我试图允许同时连接和回显数据。客户端启动几个线程,每个线程都与服务器建立自己的连接。这对socket.send()调用很好,但随后的所有调用都会导致“通过对等方重置连接”或“断开的管道”。请注意,我没有找到切换重置和断开管道的更改。我曾经在这里看过这个解决方案,但恐怕我不知道要寻找什么。为什么此套接字连接只允许1发送和接收?

我以错误的方式讨论这个问题,还是我忽略了我的设置中的某些内容?

服务器

import SocketServer 

class MyTCPHandler(SocketServer.BaseRequestHandler): 
    def handle(self): 
     self.data = self.request.recv(1024).strip() 
     print "{} wrote: {}\n".format(self.client_address[0], self.data) 
     self.request.send(self.data.upper()) 

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

客户

import socket 
import sys 
import threading 
import time 

HOST, PORT = "localhost", 9999 
def create_client(): 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    try: 
     cur_thread = threading.current_thread() 
     sock.connect((HOST, PORT)) 
     for x in range(55): 
      msg = "{}: {}\n".format(cur_thread.name, str(x)) 
      # Connect to server and send data 
      print cur_thread.name + ": sending message\n" 
      sock.send(msg) 
      # Receive data from the server and shut down 
      received = sock.recv(2048) 
      print "RX:" + received 
    finally: 
     cur_thread = threading.current_thread() 
     response = "{}: Closing!\n".format(cur_thread.name) 
     print response 
     sock.close() 

if __name__ == "__main__": 
    print "testing single thread" 
    #create_client() 
    print "starting threads" 
    client_1 = threading.Thread(target=create_client) 
    client_1.daemon = True 
    client_1.start() 
    client_2 = threading.Thread(target=create_client) 
    client_2.daemon = True 
    client_2.start() 

    time.sleep(20) 

回答

8

当您从handle返回关闭套接字。使用一个while循环并且仅在从self.data == ''返回。当客户端关闭连接时,recv返回零字节。也不要strip()的结果,直到测试返回值或您可能得到一个错误的关闭。最后,使用ThreadingTCPServer或者服务器一次只能处理一个连接。

实施例:

import SocketServer 

class MyTCPHandler(SocketServer.BaseRequestHandler): 
    def handle(self): 
     while True: 
      self.data = self.request.recv(1024) 
      if self.data == '': 
       break 
      self.data = self.data.strip() 
      print "{} wrote: {}\n".format(self.client_address[0], self.data) 
      self.request.send(self.data.upper()) 

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

还要注意send()不能保证发送消息的所有字节,所以使用sendall()或检查返回值。 recv()也可能会很棘手。 TCP/IP是一种流媒体协议,没有消息边界的概念,所以实现一个协议来检查你是否收到完整的消息取决于你。可以发送10000个字节并且接收少于这个数字,需要多个接收才能获得整个消息。也可以在一个接收中发送和接收两个,或者甚至全部发送和接收另一个。举个例子,简单地缓存所有的接收,直到消息中有一个\n为一个简单的协议。

+0

太好了。感谢您的提示。这是我第一次使用socketserver类,并没有完全理解句柄在调用之外做了什么。我原来的测试实际上是使用ThreadingTCPServer,但我切换到单个线程以确保简单(发布)的服务器工作。再次感谢。 – 2011-12-17 20:00:30

相关问题