2014-01-07 118 views
1

我有一个服务器程序,可以保持与多个客户端的连接。我希望能够关闭主服务器套接字(针对每个人),以响应客户端的CLOSE消息或其他原因。问题是服务器卡在accept()方法上,并不关心我是否在其他地方关闭套接字。如何在等待连接时关闭服务器套接字?

我可以在主服务器中使用一些标志,并在此之后关闭套接字,但这意味着在客户端请求后我必须自己连接到服务器,以便检查while状态,这听起来像是非常糟糕的节目。

代码:

import socket 
import sys 
from thread import * 

HOST = '' # Symbolic name meaning all available interfaces 
PORT = 9992 # Arbitrary non-privileged port 


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
print 'Socket created' 

#Bind socket to local host and port 
try: 
    s.bind((HOST, PORT)) 
except socket.error , msg: 
    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] 
    sys.exit() 

print 'Socket bind complete' 

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

#Function for handling connections. This will be used to create threads 
def clientthread(conn): 
    #Sending message to connected client 
    conn.send('Welcome to the server. Type something and hit enter\r\n') #send only takes string 
    data='' 
    #infinite loop so that function do not terminate and thread do not end. 
    while True: 

     #Receiving from client 
     data += conn.recv(1024) 
     print data 
     if data == 'CLOSE': 
      global s 
      conn.sendall('You have requested to destroy the connection...') 
      conn.close() 
      s.close() 
      return 
     if data.find('\n') != -1: 
      conn.sendall('OK...' + data + '\r\n') 
      data='' 






#now keep talking with the client 
while 1: 
    #wait to accept a connection - blocking call 
    try: 
     conn, addr = s.accept() 
     print 'Connected with ' + addr[0] + ':' + str(addr[1]) 

     #start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function. 
     start_new_thread(clientthread ,(conn,)) 
    except: 
     print 'socket issue sorry' 
     break 
+0

所以主线程在's.accept()'处被阻塞。如果您在套接字上调用'close()',会发生什么情况,无论是从客户端线程还是从[signal handler](http://docs.python.org/2/library/signal.html)?我认为'accept()'应该返回失败。 –

+0

@JonathonReinhart - 它在我用过的所有TCP协议栈上都有。 –

+0

你可以尝试一下,close()之后服务器仍然在等待新的连接。 –

回答

3

这是Python标准库借给你一臂之力。请查看asyncore模块或Twisted

通常没有理由不与Python进行异步,因为它非常容易。作为奖励,您的代码将更具可读性和可维护性。

你的代码asyncore

import asyncore 
import socket 
import sys 

HOST = '' # Symbolic name meaning all available interfaces 
PORT = 9992 # Arbitrary non-privileged port 

class ExampleHandler(asyncore.dispatcher_with_send): 
    data = '' 

    def handle_read(self): 
     self.data += self.recv(1024) 
     lines = self.data.split('\n') 
     if len(lines) > 1: 
      self.data = lines[-1] 
      for line in lines: 
       if not line: continue 
       if line == 'CLOSE': 
        global s 
        self.send('You have requested to destroy the connection...\r\n') 
        self.close() 
        # To exit asyncore.loop() immediately, 
        # closing all client connections 
        raise asyncore.ExitNow() 
        # If you want to finish processing the client connections, you 
        # could instead close the server, 
        server.close() 
       else: 
        self.send('OK...%s\r\n' % line) 

    def handle_write(self): 
     self.send('Welcome to the server. Type something and hit enter\r\n') 

class ExampleServer(asyncore.dispatcher): 

    def __init__(self, host, port): 
     asyncore.dispatcher.__init__(self) 
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.set_reuse_addr() 
     self.bind((host, port)) 
     self.listen(5) 

    def handle_accept(self): 
     pair = self.accept() 
     if pair is not None: 
      sock, addr = pair 
      print 'Connected with ' + addr[0] + ':' + str(addr[1]) 
      handler = ExampleHandler(sock) 
     else: 
      print 'socket issue sorry' 

server = ExampleServer(HOST, PORT) 
try: 
    asyncore.loop() 
except asyncore.ExitNow: 
    pass 

注:我也加入了线缓冲固定在原来的串码/缓冲问题。

+0

一小段片段和/或支持链接的例子将使这个体面的答案一个伟大的。 –

+0

是的,带了我几分钟重新格式化示例代码:) – Krumelur

相关问题