Python 套接字编程问题

3 投票
2 回答
1110 浏览
提问于 2025-04-16 11:16

好的,我花了大约三个小时在Python中研究socket编程,想做一个简单的聊天程序。我已经让客户端可以把文字发送到服务器,然后客户端又把这个消息重复给自己。不过,我希望消息能先发送到服务器,然后由服务器把它重新发送给所有连接的客户端,而不是让客户端自己重复。我在实现这个功能时遇到了一些问题。以下是我目前的代码:

服务器端代码:

import SocketServer

    def handle(self):
        data = self.request[0].strip()
        socket = self.request[1]
        print "%s wrote:" % self.client_address[0]
        print data
        socket.sendto(data.upper(), self.client_address)


if __name__ == "__main__":
    HOST, PORT = "localhost", 25555
    server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler)
    server.serve_forever()

客户端代码:

import socket
import sys
global HOST
global PORT
HOST, PORT = "localhost", 25555
while 1 > 0:
     data = raw_input(">".join(sys.argv[1:]))

# SOCK_DGRAM is the socket type to use for UDP sockets
     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# As you can see, there is no connect() call; UDP has no connections.
# Instead, data is directly sent to the recipient via sendto().
     sock.sendto(data + "\n", (HOST, PORT))
     received = sock.recv(1024)

     print "Sent:     %s" % data
 print "Received: %s" % received

2 个回答

1

你想试试一个服务器吗?这个服务器会把收到的数据包发给所有的连接,但不会发给最初发送这些数据的那个地方。

import socket, select

def main():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('', 8989))
    server.listen(5)
    sockets = [server]
    while True:
        for sender in select.select(sockets, [], [])[0]:
            if sender is server:
                sockets.append(server.accept()[0])
            else:
                try:
                    message = sender.recv(4096)
                except socket.error:
                    message = None
                if message:
                    for receiver in sockets:
                        if receiver not in (server, sender):
                            receiver.sendall(message)
                else:
                    sender.shutdown(socket.SHUT_RDWR)
                    sender.close()
                    sockets.remove(sender)

if __name__ == '__main__':
    main()
1

现在你的应用程序为每个客户端连接都创建了一个MyUDPHandler类的实例。当连接打开时,你需要把这个实例存储到一个静态数组或队列里。然后,当调用handle()时,它可以遍历所有这些套接字,并把数据的副本发送给每一个。

我建议你看看Python的文档;它基本上就是你想要的功能: http://docs.python.org/library/socketserver.html#asynchronous-mixins

还有,我会对那个例子做一些修改(不要直接把它放进去;它可能有明显的错误!):

handlerList = []

class ...

    def handle(self):
        handlerList.append(self)
        while (1):
          data = self.request.recv(1024)
          if (not data):
            break
          cur_thread = threading.currentThread()
          response = "%s: %s" % (cur_thread.getName(), data)
          for x in handlerList:
            x.request.send(response)
        psudo_code_remove_self_from_handlerList()

撰写回答