Python 线程:threading.Thread().start() 有效,_thread.start_new_thread() 无效

发布于 2025-01-12 08:30:19 字数 2815 浏览 1 评论 0原文

我正在尝试实现一个连接多个客户端的集中式服务器。连接应保持活动状态。

到目前为止,我已经尝试过使用线程的多个客户端,但是当套接字与客户端“忙”时,另一个客户端无法在该套接字中连接。

此代码代表服务器脚本:

import socket
import threading

HOST = '127.0.0.1'
PORT = 54321


def request_handler(conn, addr):
    with conn:
        print(conn, addr)

        while True:
            data = conn.recv(1024)
            print(data.decode('utf-8'))

            if not data:
                break

            conn.sendall(data)


def main():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()

        while True:
            conn, addr = s.accept()
            print('Connected with', addr[0], ':', str(addr[1]))

            t = threading.Thread(target=request_handler(conn, addr), daemon=True)
            t.start()


if __name__ == '__main__':
    main()

此代码代表客户端部分:

import socket


host = '127.0.0.1'
port = 54321


def main():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((host, port))
        while True:
            data = input('Type data: ')

            if not data:
                break

            s.send(str.encode(data))

            res = s.recv(1024)
            print('Server Response:', res.decode('utf-8'))


if __name__ == '__main__':
    main()

客户端可以写入许多消息,并且连接保持打开状态,但如果我使用另一个客户端,则在第一个客户端关闭连接之前,它无法与服务器连接。

但我想要的是第二个客户端可以对其他客户端执行与第一个客户端相同的操作,依此类推。如何做到这一点?

除了创建多个端口之外还有其他解决方案吗?

更新

我已经使用 _thread.start_new_thread 修改了服务器脚本,现在它可以工作了。但我不明白为什么。

修改 server.py

import socket
from _thread import start_new_thread

HOST = '127.0.0.1'
PORT = 54321


def request_handler(conn, addr):
    with conn:
        print(conn, addr)

        while True:
            data = conn.recv(1024)
            print(data.decode('utf-8'))

            if not data:
                break

            conn.sendall(data)


def main():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()

        while True:
            conn, addr = s.accept()
            print('Connected with', addr[0], ':', str(addr[1]))

            start_new_thread(request_handler, (conn, addr))


if __name__ == '__main__':
    main()

总而言之,使用 start_new_thread(request_handler, (conn, addr)) 第二个客户端可以连接到服务器并发送消息;使用 threading.Thread(target=request_handler(conn, addr)).start() 它不会连接到服务器,但不会引发错误。

当我使用 threading.Thread.start() 时,主线程正在等待 #1 客户端线程停止,因此它处于休眠状态,并且不会启动 #2 客户端线程;相反,_thread.start_new_thread()工作正常。但是 threading.Thread.start() 实现了 _thread.start_new_thread,那么这里发生了什么?

I'm trying to achieve a centralized server with multiple clients connected. The connection should be kept alive.

I've experimented with multiple clients using threads until now, but when the socket is "busy" with a client, another client can't connect in that socket.

This code represents the server script:

import socket
import threading

HOST = '127.0.0.1'
PORT = 54321


def request_handler(conn, addr):
    with conn:
        print(conn, addr)

        while True:
            data = conn.recv(1024)
            print(data.decode('utf-8'))

            if not data:
                break

            conn.sendall(data)


def main():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()

        while True:
            conn, addr = s.accept()
            print('Connected with', addr[0], ':', str(addr[1]))

            t = threading.Thread(target=request_handler(conn, addr), daemon=True)
            t.start()


if __name__ == '__main__':
    main()

This code represents the client part:

import socket


host = '127.0.0.1'
port = 54321


def main():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((host, port))
        while True:
            data = input('Type data: ')

            if not data:
                break

            s.send(str.encode(data))

            res = s.recv(1024)
            print('Server Response:', res.decode('utf-8'))


if __name__ == '__main__':
    main()

A client can write many messages, and the connection stays open, but if I use another client, this can't connect with the server until the first client closes the connection.

But what I want is that the second client can do the same as the first, and so on, with other clients. How to do this?

There is a solution other than creating multiple ports?

UPDATE

I've modified the server script, using _thread.start_new_thread, and now it works. But I can't understand why.

Modified server.py

import socket
from _thread import start_new_thread

HOST = '127.0.0.1'
PORT = 54321


def request_handler(conn, addr):
    with conn:
        print(conn, addr)

        while True:
            data = conn.recv(1024)
            print(data.decode('utf-8'))

            if not data:
                break

            conn.sendall(data)


def main():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()

        while True:
            conn, addr = s.accept()
            print('Connected with', addr[0], ':', str(addr[1]))

            start_new_thread(request_handler, (conn, addr))


if __name__ == '__main__':
    main()

To summarize, with start_new_thread(request_handler, (conn, addr)) the second client can connect to the server, and send messages; with threading.Thread(target=request_handler(conn, addr)).start() it doesn't connect to the server, but no error is raised.

When I use the threading.Thread.start() the Main tread is waiting that the #1 client thread is stopped, so it's hybernated, and doesn't start the #2 client thread; instead the _thread.start_new_thread() is work fine. But the threading.Thread.start() implements the _thread.start_new_thread, so what's happening here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我们只是彼此的过ke 2025-01-19 08:30:19

解决了,我以错误的方式使用 threading.Thread 构造函数:

构造函数调用 request_handler 而不是引用它。

所以,而不是:

t = threading.Thread(target=request_handler(conn, addr))

正确的方法是:

t = threading.Thread(target=request_handler, args=(conn, addr))

以便线程可以并行运行。

Solved, I was using the threading.Thread constructor in the wrong way:

The constructor was invoking the request_handler instead of referencing it.

So, instead of:

t = threading.Thread(target=request_handler(conn, addr))

the right way is:

t = threading.Thread(target=request_handler, args=(conn, addr))

so that the threads can run in parallel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文