python - Python Socket 编码和解码客户端数据
问题描述
我正在尝试创建消息服务器类型的东西。连接到服务器客户端并尝试输入用户名后,它会给出错误:
“需要一个类似字节的对象,而不是'str'”
而且我不确定我是否对编码和解码功能处理不当。
import socket, time, sys, threading
class Server:
def __init__(self, port):
while True:
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.port = port
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(('127.0.0.1',port))
self.clients = []
self.usernames = []
print('Successfully bound socket!')
break
except:
print('Error binding, retrying....')
time.sleep(5)
def close(self):
self.socket.close()
def commands(self):
while True:
command = input()
if command.lower() in ['exit', 'end', 'quit', 'q']:
print('Closing Session.....')
server.close(), sys.exit()
def broadcast(self, message):
for client in self.clients:
client.send(message)
def handle(self, client):
while True:
try:
message = client.recv(1024)
server.broadcast(message)
except:
index = self.clients.index(client)
self.clients.remove(client)
client.close()
username = self.usernames[index]
server.broadcast(f'{username.decode("ascii")} has left!')
self.usernames.remove(username)
break
def receive(self, client, addr):
while True:
print(f'New Socket Connection: {addr}')
try:
client.send('USERNAME: '.encode('ascii'))
username = client.recv(1024).decode('ascii')
self.usernames.append(username)
self.clients.append(client)
print(f'Username is: {username}')
server.broadcast(f'{username.encode("ascii")} has connected.')
client.send('Connected to the server!'.encode('ascii'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
except Exception as e:
print(e)
print('Closed early! (Or wrong values entered!)')
socket.close()
print(f'Client {addr} closed.')
client.send()
def listen(self):
self.socket.listen(5)
print('Listening for new connections....')
while True:
client, addr = self.socket.accept()
client.settimeout(60)
server.receive(client, addr)
server = Server(4545)
try:
server.listen()
except:
server.close()
问题来自接收功能:
def receive(self, client, addr):
while True:
print(f'New Socket Connection: {addr}')
try:
client.send('USERNAME: '.encode('ascii'))
username = client.recv(1024).decode('ascii')
self.usernames.append(username)
self.clients.append(client)
print(f'Username is: {username}')
server.broadcast(f'{username.encode("ascii")} has connected.')
client.send('Connected to the server!'.encode('ascii'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
except Exception as e:
print(e)
print('Closed early! (Or wrong values entered!)')
socket.close()
print(f'Client {addr} closed.')
client.send()
解决方案
看看这部分代码:
def receive(self, client, addr):
while True:
#[...]
server.broadcast(f'{username.encode("ascii")} has connected.')
您只是在编码username
但不是完整的字符串!
所以它应该是这样的:
#[...]
server.broadcast(f'{username} has connected.'.encode("ascii"))
#[...]
这是最终的工作代码:
import socket, time, sys, threading
class Server:
def __init__(self, port):
while True:
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.port = port
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(('127.0.0.1',port))
self.clients = []
self.usernames = []
print('Successfully bound socket!')
break
except:
print('Error binding, retrying....')
time.sleep(5)
def close(self):
self.socket.close()
def commands(self):
while True:
command = input()
if command.lower() in ['exit', 'end', 'quit', 'q']:
print('Closing Session.....')
server.close(), sys.exit()
def broadcast(self, message):
for client in self.clients:
client.send(message)
def handle(self, client):
while True:
try:
message = client.recv(1024)
server.broadcast(message)
except:
index = self.clients.index(client)
self.clients.remove(client)
client.close()
username = self.usernames[index]
server.broadcast(f'{username.decode("ascii")} has left!')
self.usernames.remove(username)
break
def receive(self, client, addr):
while True:
print(f'New Socket Connection: {addr}')
try:
client.send('USERNAME: '.encode('ascii'))
username = client.recv(1024).decode('ascii')
self.usernames.append(username)
self.clients.append(client)
print(f'Username is: {username}')
server.broadcast(f'{username} has connected.'.encode("ascii"))
client.send('Connected to the server!'.encode('ascii'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
except Exception as e:
print(e)
print('Closed early! (Or wrong values entered!)')
socket.close()
print(f'Client {addr} closed.')
client.send()
def listen(self):
self.socket.listen(5)
print('Listening for new connections....')
while True:
client, addr = self.socket.accept()
client.settimeout(60)
server.receive(client, addr)
server = Server(4545)
try:
server.listen()
except:
server.close()
推荐阅读
- unit-testing - 可以在 Golang httptest 服务器中执行自重定向吗?
- asp.net-core - 如何在 ASP .NET Core 中更改 SignOutAsync ReturnUrl
- javascript - 页面不断滚动到外部 javascript
- postgresql - 如何根据 PostgreSQL 中的“where room="living" 和 garden="green" 等条件“插入或更新”
- math - 计算坐标系中盒子的封闭垂直俯仰角
- selenium - 在浏览器中使用 Selenium
- asp.net - 一种在 Episerver 中具有未提交给 git 的本地配置覆盖的方法
- sql - 如何通过关联多个其他节点来查找节点
- powershell - Azure DevOps 托管代理管道“无法找到可执行文件:‘Powershell’
- javascript - 使用导入和参数运行自定义函数