use*_*537 1 python sockets client socketserver
我一直在尝试制作一个多客户端服务器,并且最终可以正常运行,但是我现在要做的是代替获取客户端地址,让客户端输入名称,然后程序会说“鲍勃:嗨,大家好”,而不是“ 127.0.0.1:嗨,大家好”。
我使用了python文档中的预制服务器和客户端。这是服务器:
import socketserver
class MyUDPHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request[0].strip()
name = self.request[0].strip()
socket = self.request[1]
print(name,"wrote:".format(self.client_address[0]))
print(data)
socket.sendto(data.upper(), self.client_address)
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = socketserver.UDPServer((HOST, PORT), MyUDPHandler)
server.serve_forever()
Run Code Online (Sandbox Code Playgroud)
这是客户:
import socket
import sys
HOST, PORT = "localhost", 9999
data = "".join(sys.argv[1:])
name = "".join(sys.argv[1:])
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(bytes(name + "Bob", 'utf-8'), (HOST, PORT))
sock.sendto(bytes(data + "hello my name is Bob", "utf-8"), (HOST, PORT))
received = str(sock.recv(1024), "utf-8")
print("Sent: {}".format(data))
print("Received: {}".format(received))
Run Code Online (Sandbox Code Playgroud)
一切正常,但由于某种原因,一旦客户端连接,我就会在服务器中得到此信息。
b'Bob' wrote:
b'Bob'
b'hello my name is bob' wrote:
b'hello my name is bob'
Run Code Online (Sandbox Code Playgroud)
我希望它像:
Bob wrote:
b'Hello my name is bob'
Run Code Online (Sandbox Code Playgroud)
希望有人能帮助我,谢谢。
您在这里遇到了多个问题。
首先是bytes直接打印对象:
print(name,"wrote:".format(self.client_address[0]))
Run Code Online (Sandbox Code Playgroud)
这就是为什么您得到b'Bob' wrote:而不是的原因Bob wrote:。当您bytes在Python 3中打印对象时,就会发生这种情况。如果要将其解码为字符串,则必须明确地执行此操作。
您有可以在整个地方执行此操作的代码。使用decodeand encode方法通常比strand bytes构造函数更干净,并且如果您已经在使用format,则可以使用更好的方法来处理此问题,但要坚持使用现有样式:
print(str(name, "utf-8"), "wrote:".format(self.client_address[0]))
Run Code Online (Sandbox Code Playgroud)
接下来,我不确定为什么要调用format没有格式参数的字符串,或者为什么要混合使用多参数print函数和format调用。看来您正在尝试获取self.client_address[0],但您并未这样做。再一次,您想要的输出没有显示出来,所以…… format如果您不想要它,只需删除该调用,然后{}在格式字符串中添加一个位置即可。(您也可能也想解码client_address[0]。)
接下来,将相同的值存储在name和中data:
data = self.request[0].strip()
name = self.request[0].strip()
Run Code Online (Sandbox Code Playgroud)
因此,当您稍后执行此操作时:
print(data)
Run Code Online (Sandbox Code Playgroud)
……这只是name再次打印-并且再次进行解码。因此,即使解决了解码问题,您仍然会得到以下信息:
Bob wrote:
Bob
Run Code Online (Sandbox Code Playgroud)
……而不仅仅是:
Bob wrote:
Run Code Online (Sandbox Code Playgroud)
要解决此问题,只需删除data变量和print(data)调用即可。
接下来,您要发送两个独立的包,一个与name和其他与data,但要恢复既出每个数据包的。因此,即使您修复了上述所有问题,您也将获得Bob一个数据包作为名称,而hello my name is bob在下一个数据包中得到:
Bob wrote:
hello my name is bob wrote:
Run Code Online (Sandbox Code Playgroud)
如果希望此状态是有状态的,则需要将状态实际存储在某处。在您的情况下,状态非常简单-只是一个标志,表明这是否是来自给定客户端的第一条消息-但它仍然必须传递到某个地方。一种解决方案是使用字典将新状态与每个地址相关联,尽管在这种情况下,由于状态是“先见过”或什么都没有,因此我们可以只使用一个集合。
放在一起:
class MyUDPHandler(socketserver.BaseRequestHandler):
def __init__(self, *args, **kw):
self.seen = set()
super().__init__(*args, **kw)
def handle(self):
data = self.request[0].strip()
addr = self.client_address[0]
if not addr in self.seen:
print(str(data, "utf-8"), "wrote:")
self.seen.add(addr)
else:
print(str(data, "utf-8"))
socket.sendto(data.upper(), self.client_address)
Run Code Online (Sandbox Code Playgroud)
同时,似乎您真正想要的是将第一个请求中的名称存储为每个客户端状态,因此您可以在以后的每个请求中重用它。那几乎一样容易。例如:
class MyUDPHandler(socketserver.BaseRequestHandler):
def __init__(self, *args, **kw):
self.clients = {}
super().__init__(*args, **kw)
def handle(self):
data = str(self.request[0].strip(), 'utf-8')
addr = self.client_address[0]
if not addr in self.clients:
print(data, "joined!")
self.clients[addr] = data
else:
print(self.clients[addr], 'wrote:', data)
socket.sendto(data.upper(), self.client_address)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3636 次 |
| 最近记录: |