编写了一段网络程序,其中涉及到使用线程来进行多客户端连接,当主线程开始等待连接时,程序会卡住。另外,发送数据时客户端程序会堵塞。
- 代码示例:
obj.HOST = ""
obj.PORT = int(port.get())
obj.srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
obj.srv.bind((obj.HOST, obj.PORT))
obj.srv.listen(1)
obj.sock, obj.addr = obj.srv.accept()
class Client(threading.Thread):
def __init__(self, from_):
if from_.ip.get() == '':
obj.HOST = 'localhost'
else:
obj.HOST = from_.ip.get()
obj.PORT = int(from_.port.get())
obj.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
obj.sock.connect((obj.HOST, obj.PORT))
threading.Thread.__init__(self)
def run(self):
command = obj.sock.recv(1024)
print(command)
if command == 'confirm':
print('confirm')
elif command == 'start':
print('start')
client = Client(cl) # cl is class, where I get port. It's works 100% correct
client.start()
```
2. 解决方案
-
问题一:主线程卡顿的问题可以通过使用
threading.Event()来解决。
# Create an event to signal that a connection has been established.
connection_event = threading.Event()
def accept_connection():
"""
Wait for a connection and set the connection_event to signal that a connection has been established.
"""
obj.srv.listen(1)
obj.sock, obj.addr = obj.srv.accept()
connection_event.set()
# Create a thread to handle accepting connections.
connection_thread = threading.Thread(target=accept_connection)
connection_thread.start()
# Wait for the connection event to be set, indicating that a connection has been established.
connection_event.wait()
```
-
问题二:客户端接收数据时堵塞的问题可以通过使用
select.select()来解决。
while True:
# Wait for data to be available on the socket.
ready_to_read, _, _ = select.select([obj.sock], [], [], 0)
# If data is available, read it and process it.
if obj.sock in ready_to_read:
data = obj.sock.recv(1024)
if data:
print(data)
else:
break
```
- 最终的代码示例:
obj.HOST = ""
obj.PORT = int(port.get())
obj.srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
obj.srv.bind((obj.HOST, obj.PORT))
# Create an event to signal that a connection has been established.
connection_event = threading.Event()
def accept_connection():
"""
Wait for a connection and set the connection_event to signal that a connection has been established.
"""
obj.srv.listen(1)
obj.sock, obj.addr = obj.srv.accept()
connection_event.set()
# Create a thread to handle accepting connections.
connection_thread = threading.Thread(target=accept_connection)
connection_thread.start()
# Wait for the connection event to be set, indicating that a connection has been established.
connection_event.wait()
class Client(threading.Thread):
def __init__(self, from_):
if from_.ip.get() == '':
obj.HOST = 'localhost'
else:
obj.HOST = from_.ip.get()
obj.PORT = int(from_.port.get())
obj.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
obj.sock.connect((obj.HOST, obj.PORT))
threading.Thread.__init__(self)
def run(self):
while True:
# Wait for data to be available on the socket.
ready_to_read, _, _ = select.select([obj.sock], [], [], 0)
# If data is available, read it and process it.
if obj.sock in ready_to_read:
data = obj.sock.recv(1024)
if data:
print(data)
else:
break
client = Client(cl) # cl is class, where I get port. It's works 100% correct
client.start()
```