Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python套接字和socketserver_Python_Sockets_Client_Socketserver - Fatal编程技术网

python套接字和socketserver

python套接字和socketserver,python,sockets,client,socketserver,Python,Sockets,Client,Socketserver,我一直在尝试制作一个多客户端服务器,我终于做到了,它工作得很好,但我现在想做的是,让客户端输入他们的名字,然后程序会说“Bob:Hi guys”,而不是“127.0.0.1:Hi guys” 我使用了python文档中预先制作的服务器和客户端。 这是服务器: import socketserver class MyUDPHandler(socketserver.BaseRequestHandler): def handle(self): data = self.re

我一直在尝试制作一个多客户端服务器,我终于做到了,它工作得很好,但我现在想做的是,让客户端输入他们的名字,然后程序会说“Bob:Hi guys”,而不是“127.0.0.1:Hi guys”

我使用了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()
这是客户:

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))
一切正常,但由于某种原因,一旦客户端连接,我就会在服务器上得到这个

b'Bob'  wrote:
b'Bob'
b'hello my name is bob'  wrote:
b'hello my name is bob'
我希望它像:

Bob wrote:
b'Hello my name is bob'

我希望有人能帮助我,谢谢。

你这里有很多问题


第一个是直接打印
字节
对象:

print(name,"wrote:".format(self.client_address[0]))
这就是为什么b'Bob写了:而不是Bob写的:。在Python3中打印
bytes
对象时,会发生这种情况。如果要将其解码为字符串,则必须显式地执行此操作

你的代码到处都是这样的。使用
解码
编码
方法通常比使用
str
字节
构造函数更干净,如果您已经在使用
格式
的话,还有更好的方法来处理这个问题,但要坚持您现有的风格:

print(str(name, "utf-8"), "wrote:".format(self.client_address[0]))

接下来,我不知道为什么要在没有格式参数的字符串上调用
format
,或者为什么要将多参数
print
函数和
format
调用混合在一起。看起来您正在尝试获取
self.client\u地址[0]
,但您没有这样做。同样,您所需的输出没有显示它,因此…只要删除该
format
调用即可。如果不需要,请在格式字符串中的某个位置添加一个
{}
。(您可能还需要解码
客户端地址[0]
。)


接下来,在
名称
数据
中存储相同的值:

data = self.request[0].strip()
name = self.request[0].strip()
因此,当您稍后执行此操作时:

print(data)
…那只是一次又一次地打印
名称
,而没有对其进行解码。因此,即使您解决了解码问题,您仍然会得到以下结果:

Bob wrote:
Bob
…而不仅仅是:

Bob wrote:
要解决这个问题,只需去掉
data
变量和
print(data)
调用


接下来,您将发送两个单独的数据包,一个带有
名称
,另一个带有
数据
,但尝试从每个数据包中恢复这两个数据包。因此,即使您解决了上述所有问题,您也会在一个数据包中获得
Bob
作为名称,在下一个数据包中获得
hello my name is Bob
,结果是:

Bob wrote:
hello my name is bob wrote:
如果希望它是有状态的,则需要将状态实际存储在某个位置。在您的例子中,状态非常简单,只是一个标志,表明这是否是来自给定客户机的第一条消息,但它仍然必须到达某个地方。一种解决方案是使用字典将一个新状态与每个地址相关联,尽管在这种情况下,由于状态要么是“以前看到过”,要么根本没有,我们可以使用一个集合

总而言之:

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)

同时,您实际想要的似乎是将第一个请求中的名称存储为每个客户机状态,这样您就可以在将来的每个请求中重用它。那几乎一样容易。例如:

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)

你这里有很多问题


第一个是直接打印
字节
对象:

print(name,"wrote:".format(self.client_address[0]))
这就是为什么b'Bob写了:而不是Bob写的:。在Python3中打印
bytes
对象时,会发生这种情况。如果要将其解码为字符串,则必须显式地执行此操作

你的代码到处都是这样的。使用
解码
编码
方法通常比使用
str
字节
构造函数更干净,如果您已经在使用
格式
的话,还有更好的方法来处理这个问题,但要坚持您现有的风格:

print(str(name, "utf-8"), "wrote:".format(self.client_address[0]))

接下来,我不知道为什么要在没有格式参数的字符串上调用
format
,或者为什么要将多参数
print
函数和
format
调用混合在一起。看起来您正在尝试获取
self.client\u地址[0]
,但您没有这样做。同样,您所需的输出没有显示它,因此…只要删除该
format
调用即可。如果不需要,请在格式字符串中的某个位置添加一个
{}
。(您可能还需要解码
客户端地址[0]
。)


接下来,在
名称
数据
中存储相同的值:

data = self.request[0].strip()
name = self.request[0].strip()
因此,当您稍后执行此操作时:

print(data)
…那只是一次又一次地打印
名称
,而没有对其进行解码。因此,即使您解决了解码问题,您仍然会得到以下结果:

Bob wrote:
Bob
…而不仅仅是:

Bob wrote:
要解决这个问题,只需去掉
data
变量和
print(data)
调用


接下来,您将发送两个单独的数据包,一个带有
名称
,另一个带有
数据
,但尝试从每个数据包中恢复这两个数据包。因此,即使您解决了上述所有问题,您也会在一个数据包中获得
Bob
作为名称,在下一个数据包中获得
hello my name is Bob
,结果是:

Bob wrote:
hello my name is bob wrote:
如果希望它是有状态的,则需要将状态实际存储在某个位置。在您的例子中,状态非常简单,只是一个标志,表明这是否是来自给定客户机的第一条消息,但它仍然必须到达某个地方。一种解决方案是使用字典将一个新状态与每个地址相关联,尽管在这种情况下,由于状态要么是“以前看到过”,要么根本没有,我们可以使用一个集合

总而言之:

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)

同时,您实际想要的似乎是将第一个请求中的名称存储为每个客户机状态,这样您就可以在将来的每个请求中重用它。那几乎是一样的