繁体   English   中英

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

[英]Why are my threads hanging in this socket test on windows?

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

我的灵性告诉我os.urandom()可以在Windows上阻止熵,如果没有足够的可用熵(在Unix上永远不要阻止)。 我还无法通过MSDN确认这种方式,但是鉴于对硬件熵的依赖(与使用纯软件实现的FreeBSD不同),我并不认为阻塞是完全不可能的。 尝试用(例如) b'\\x00' * 256替换os.urandom(256)调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM