Python 多线程同时使用一台服务器 运行 无限期地处理两个客户端

Python multithreading two clients to run indefinitely at the same time with one server

我正在尝试解决两个客户端 运行 的多线程问题,永远同时向服务器发送 ping,而服务器不断回显消息。

在发现一个 client/server 如何永远来回回显后,我研究了多线程。

当我添加第二个客户端时,它会收到第一个客户端的最后输出。然后,第二个客户端将与服务器重复回显,而第一个客户端从未收到消息,将其冻结。

我被困在这个问题上好几天了,所以帮助会很好。

无论如何,这是我用来测试的代码:

ClientA.py

import socket
import time

host = '127.0.0.1' 
port = 2004
BUFFER_SIZE = 2000 

tcpClientA = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
tcpClientA.connect((host, port))

while True:
    data = 'this is client A'
    tcpClientA.send(data)
    data2 = tcpClientA.recv(BUFFER_SIZE)
    print " Client A received data:", data2

Clientb.py 与客户端 A 相同,但带有 b

Server.py

import socket
import time
import thread

from threading import Thread 
from SocketServer import ThreadingMixIn 


BUFFER_SIZE = 1024

TCP_IP = '127.0.0.1' 
TCP_PORT = 2004
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

threads = []

def client(ip,port):
    while True:
        data = conn.recv(2048)
        conn.send(data)
    conn.close()

print "Server waiting"
tcpServer.bind((TCP_IP, TCP_PORT))
tcpServer.listen(4)
while True:
    conn,addr=tcpServer.accept()
    thread.start_new_thread(client,(conn,addr))
tcpServer.close()

您的客户端处理程序线程使用在主线程中分配的变量 conn 中的套接字从中接收数据并向其发送数据。基本上,您总是只使用创建的最后一个连接。
这通常在第二个客户端的输出中可见,就在启动它之后:

Client B received data: this is client A

从现在开始,两个客户端处理程序线程都只为客户端 B 服务,因为您的 client 函数的这一部分 ...

    data = conn.recv(2048)
    conn.send(data)

... 从主线程使用这个 conn (套接字),每次新客户端连接到服务器时都会覆盖它:

conn, addr = tcpServer.accept()

客户端A此时等待服务器数据:

data2 = tcpClientA.recv(BUFFER_SIZE)

但是由于您服务器中的两个客户端处理程序线程只监听和写入客户端 B 连接时创建的套接字,客户端 A 进程不再接收数据并无限期地阻塞等待一些。

您已经将相应的连接传递给您的客户端处理程序线程...

thread.start_new_thread(client, (conn, addr))

...你只需要使用它:

def client(ip,port):
    while True:
        data = ip.recv(2048)  # receive from ip
        ip.send(data)         # send to ip
    conn.close()

您原来的 client 函数没有使用传入的连接,而是在每个连接上覆盖的全局变量 connip 是传递给 client 的连接。

由于您的服务器代码导入了SocketServer,因此请使用它并简化代码。此代码将为每个客户端连接创建一个线程。 self.request 是套接字连接:

#!python2
import SocketServer

class Handler(SocketServer.StreamRequestHandler):
    def handle(self):
        while True:
            data = self.request.recv(2048)
            if not data: break
            self.request.sendall(data)

server = SocketServer.ThreadingTCPServer(('',2004),Handler)
server.serve_forever()