为什么我的线程在Windows上的套接字测试中挂起?

时间:2014-10-28 23:45:22

标签: python windows multithreading sockets

我编写了这个脚本来测试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()中,但我不知道为什么。

1 个答案:

答案 0 :(得分:0)

我的通灵能力告诉我os.urandom()如果没有足够的熵可以阻止Windows(它永远不会在Unix上阻止)。我无法确认这种方式或其他via MSDN,但鉴于对硬件熵的依赖(不像FreeBSD,它使用纯软件实现),我认为阻塞完全不是不可思议。尝试用(例如)os.urandom(256)替换b'\x00' * 256来电。