我编写了这个脚本来测试Windows中的套接字行为,我不确定它为什么会在Windows中而不是在Ubuntu中挂起。该脚本使三个侦听套接字绑定到' 127.0.0.1',它产生60个线程,每个线程连接到侦听套接字10次,每个侦听套接字20个线程。
import threading
import socket
import logging
import os
ports = [60003, 60004, 60005]
class ServerTest(threading.Thread):
log_lock = threading.Lock()
def __init__(self, port):
super(ServerTest, self).__init__(name=('socktest_%d'%port))
self.port = port
self._init_logger()
def _init_logger(self):
self.logger = logging.getLogger(self.name)
handler = logging.FileHandler('socktest.log')
formatter = logging.Formatter(
'%(levelname)s -- %(asctime)s:\n%(message)s',
datefmt='%m/%d/%Y %I:%M:%S %a')
handler.setFormatter(formatter)
handler.setLevel(logging.INFO)
self.logger.addHandler(handler)
self.logger.setLevel(logging.INFO)
def log(self, junk):
self.log_lock.acquire()
if isinstance(junk, Exception):
self.logger.exception(junk)
else:
self.logger.info(str(junk))
self.log_lock.release()
def run(self):
try:
listener = socket.socket()
listener.bind(('127.0.0.1', self.port))
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listener.listen(100)
except Exeption as exc:
self.log(exc)
return
while True:
try:
c, a = listener.accept()
self.log('accepted connection from '+str(a)+' to '+self.name)
data = c.recv(4096)
if data == 'stop':
break
self.log('data:\n'+data)
c.sendall(data)
c.close()
except Exception as exc:
self.log(exc)
listener.close()
class ClientTest(threading.Thread):
def __init__(self, port):
super(ClientTest, self).__init__()
self.port = port
def run(self):
try:
for i in range(10):
c = socket.create_connection(('127.0.0.1', self.port))
data = os.urandom(256)
c.sendall(data)
c.recv(256)
c.close()
except Exception as exc:
return
def main():
print 'Starting test'
server_threads = [ServerTest(p) for p in ports]
for thread in server_threads:
thread.start()
print 'started thread', thread
client_threads = []
for p in ports:
for i in range(20):
client_threads.append(ClientTest(p))
for thread in client_threads:
thread.start()
print 'started thread', thread
for thread in client_threads:
thread.join()
print 'joined thread', thread
for p in ports:
c = socket.create_connection(('127.0.0.1', p))
c.sendall('stop')
c.close()
for thread in server_threads:
thread.join()
print 'joined thread', thread
print 'Finished'
if __name__ == '__main__':
main()
我已尝试使用和不使用行listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
并且行为相同。我也尝试了没有锁定,行为仍然相同。
修改
我忘了提到它 打印出所有的线程,它似乎停留在client_threads的thread.join()中,但我不知道为什么。
答案 0 :(得分:0)
我的通灵能力告诉我os.urandom()
如果没有足够的熵可以阻止Windows(它永远不会在Unix上阻止)。我无法确认这种方式或其他via MSDN,但鉴于对硬件熵的依赖(不像FreeBSD,它使用纯软件实现),我认为阻塞完全不是不可思议。尝试用(例如)os.urandom(256)
替换b'\x00' * 256
来电。