1

在下面显示的代码中,我使用阻塞调用从套接字接收 50 个字节的数据并将其回显。但是发生的情况是代码在收到一个字节后卡住了。在另一个命令提示符上运行的 telnet 中,连接仍然显示作为连接。这可能缺少什么?

import socket
import sys

host = ''
port = 8888

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

s.bind((host,port))
print 'Socket Bind Complete'

s.listen(10)
print 'Now Listening'

while 1:
   conn, adr = s.accept()
   print 'connected with' + adr[0] + ':' + str(adr[1])
   data = conn.recv(50)
   print data
   if not data:
    break
   conn.sendall(data)

conn.close()
s.close() 
4

1 回答 1

1

问题是您accept每次通过循环都会建立一个新连接,并且只能从该连接接收一次。下次通过循环时,您会忘记该连接和accept一个新连接,该连接会阻塞直到其他人连接。


如果您只想处理单个连接并退出,只需移动accept循环外:

conn, adr = s.accept()
print 'connected with' + adr[0] + ':' + str(adr[1])
while True:
    data = conn.recv(50)
    print data
    if not data:
        break
    conn.sendall(data)
conn.close()
s.close()

如果您想一次处理一个连接,但在完成第一个连接后等待新连接,请添加一个外部循环。

while True:
    conn, adr = s.accept()
    print 'connected with' + adr[0] + ':' + str(adr[1])
    while True:
        data = conn.recv(50)
        print data
        if not data:
            break
        conn.sendall(data)
    conn.close()
s.close()

如果您想一次处理多个连接,就像大多数服务器一样,您需要某种异步机制——<code>选择和非阻塞套接字gevent、线程等等。例如:

def handle_client(conn, addr):
    print 'connected with' + adr[0] + ':' + str(adr[1])
    while True:
        data = conn.recv(50)
        print data
        if not data:
            break
        conn.sendall(data)
    conn.close()

client_threads = []
try:
    while True:
        conn, adr = s.accept()
        client_thread = threading.Thread(target=handle_client, args=[conn, addr])
        client_thread.start()
        client_threads.append(client_thread)
finally:
    s.close()
    for client_thread in client_threads:
        client_thread.join()

在任何这些设计中,您最好使用with语句而不是显式close调用和/或try/ finally

于 2013-05-28T08:15:05.163 回答