python - Select 在来自每个客户端的几条消息后返回空套接字列表
问题描述
我正在尝试使用 python 制作一个基本的基于终端的聊天应用程序。我使用 select() 来更新可读/可写连接。然而,在来自每个客户端的两条消息之后,服务器返回一个空的可读列表(sockets_list)。
我已经尝试从我的套接字列表中删除删除连接的代码。
这是 server.py
import socket
import select
import time
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# host, port
host = 'localhost'
port = 5555
# bind and listen for connections
sock.bind((host, port))
sock.listen(2)
print('Server started on. {} {}'.format(host, port))
# select lists
sockets_list = [sock]
outputs = []
clients = {}
def receive_message(conn):
try:
msg = conn.recv(4096)
if not len(msg):
return False
return msg
except conn.error as e:
return False
while True:
print('\n waiting for the next event')
readable, writable, exceptions = select.select(sockets_list, outputs, [], 10)
print(readable, writable)
for s in readable:
if s == sock:
connection, address = s.accept()
user = receive_message(connection)
if user is False:
continue
sockets_list.append(connection)
clients[connection] = user
print(f'Accepted new connection from {user.decode()}')
else:
arr = s.recv(4096).decode().split(':')
if len(arr) < 2:
arr = s.recv(4096).decode().split(':')
elif len(arr) >= 2:
message = arr[1]
# if message is False:
# print(f'Connection closed with {s}')
#
# sockets_list.remove(s)
# del clients[s]
#
# continue
user = clients[s]
print(f'Received message from {user.decode()}: {message}')
for client in clients:
# But don't sent it to sender
if client != s:
# Send user and message (both with their headers)
# client.send(user['header'] + user['data'] + message['header'] + message['data'])
client.send(f"{user.decode()}:{message}".encode())
print(f'Sending {message} to {clients[client].decode()}')
这是client.py:
import socket
import select
import errno
import sys
IP = "localhost"
PORT = 5555
current_user = input("Username: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((IP, PORT))
# client.setblocking(False)
username = current_user.encode()
client.send(username)
while True:
message = input(f'{current_user} > ')
if message:
# Encode message to bytes, prepare header and convert to bytes, like for username above, then send
client.send(f'{current_user}:{message}'.encode())
try:
while True:
arr = client.recv(4096).decode().split(':')
username = arr[0]
if not username:
print('Connection closed by the server')
sys.exit()
message = arr[1]
# Print message
print(f'{username} > {message}')
message = input(f'{current_user} > ')
except IOError as e:
print(e)
sys.exit()
except Exception as e:
print(e)
我希望服务器从两个客户端接收/发送消息。这意味着无论客户端 1 发送什么,客户端 2 都会看到。
解决方案
The issue was that I wasn't sending/receiving the data properly with the client. So I tweaked it a little bit and it works now!
while True:
message = input(f'{current_user} > ')
if message:
client.send(f'{current_user}:{message}'.encode())
arr = client.recv(4096).decode().split(':')
if arr:
username = arr[0]
message = arr[1]
# Print message
print(f'{username} > {message}')
Putting a forever loop in a forever loop didn't make sense so I got rid of it.
I checked if the client received data with if arr:
and printed the data. Since arr was in the forever loop, it ALWAYS checked for data.
To send data, it was pretty simple, get input, send it via socket.
推荐阅读
- reactjs - 如何在不安装表单的情况下在 React 中发起发布请求?
- angular - Angular Material 表数据源问题
- ios - 在后台执行 Apple 快捷方式
- docker - 如何让前端 Docker 容器找到后端容器 ip?
- dart - 在 Dart 中解析动态数据
- javascript - 如何使用 post 方法或在 javascript 中获取发送的数据
- .net - 如何避免在.NET中传递值类型参数时的装箱?
- javascript - PhoneGap/Cordova InAppBrowser 的定时弹出窗口?
- git - git difftool 挂起并且屏幕变得无响应
- android - 同步 FirebaseAuth.getInstance().signOut() 和异步 AuthUI.getInstance().signOut() 之间有什么区别吗