简体   繁体   English

Python中的多客户端服务器-如何广播?

[英]Multiclient server in Python - how to broadcast?

I found online a simple multiclient echo server in Python using threads: 我在网上使用线程在Python中找到了一个简单的多客户端回显服务器:

#!/usr/bin/env python
import socket
import sys
import threading

class Client(threading.Thread):
    def __init__(self, ip, port, connection):
        threading.Thread.__init__(self)
        self.connection = connection
        self.ip = ip
        self.port = port

    def run(self):

        data = self.connection.recv(1024)
        if data :
            self.connection.sendall(data)
        else :
            self.connection.close()

class Server:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
        self.address = (self.ip, self.port)
        self.server = None
        self.clients = []

    def open_socket(self):
        try:
            self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server.bind(self.address)
        except socket.error, e:
            if self.server:
                self.server.close()
            sys.exit(1)

    def run(self):
        self.open_socket()
        self.server.listen(5)

        while True :
            connection, (ip, port) = self.server.accept()

            c = Client(ip, port, connection)
            c.start()

            self.clients.append(c)

        self.server.close()

if __name__ == '__main__':
    s = Server('127.0.0.1', 6666)
    s.run()

And I wrote a client: 我写了一个客户:

import socket
import sys

port = 6666
size = 1024
s = None
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = socket.gethostname()
    s.connect(('127.0.0.1', port))
except socket.error, (value, message):
    if s:
        s.close()
    print "Could not open socket: " + message
    sys.exit(1)
data = raw_input('> ')
s.sendall(data)
data = s.recv(size)
print "Server sent: %s " % data
s.close()

Everything works great but I wonder how could I add to the server the functionality of broadcast to be able to echo back the message to all connected clients? 一切正常,但是我不知道如何向服务器添加广播功能,以便能够将消息回显给所有连接的客户端? Or be able to send a message to a specific client? 还是能够向特定客户端发送消息?

I have all clients in server's class, but I do not know how to (and where in the server's code, in Client class or Server class place the code to broadcast and send private messages? Thank you. 我在服务器类中拥有所有客户端,但是我不知道如何(以及在​​服务器代码中的Client类或Server类中的何处放置代码以广播和发送私人消息?谢谢。

EDIT: 编辑:

New server: 新服务器:

#!/usr/bin/env python
import socket
import sys
import threading

class Client(threading.Thread):
    def __init__(self, ip, port, connection):
        threading.Thread.__init__(self)
        self.connection = connection
        self.ip = ip
        self.port = port

    def run(self):
        while True:
            data = self.connection.recv(1024)
            if data :
                self.connection.sendall(data)
            else :
                break
        self.connection.close()


class Server:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
        self.address = (self.ip, self.port)
        self.server = None
        self.clients = []

    def send_to_all_clients(self, msg):
        for client in self.clients :
            client.connection.send(msg)

    def send_to_client(self, ip, port, msg):
        for client in self.clients :
            if client.ip == ip and client.port == port :
                client.connection.send(msg)

    def open_socket(self):
        try:
            self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server.bind(self.address)
        except socket.error, e:
            if self.server:
                self.server.close()
            sys.exit(1)

    def run(self):
        self.open_socket()
        self.server.listen(5)

        while True :
            connection, (ip, port) = self.server.accept()

            c = Client(ip, port, connection)
            c.start()

            self.clients.append(c)

        self.server.close()

if __name__ == '__main__':
    s = Server('127.0.0.1', 6666)
    s.run()

New client: 新客户:

import socket
import sys

port = 6666
size = 1024
s = None
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = socket.gethostname()
    s.connect(('127.0.0.1', port))
except socket.error, (value, message):
    if s:
        s.close()
    print "Could not open socket: " + message
    sys.exit(1)

while True:
    data = raw_input('> ')
    s.sendall(data)
    data = s.recv(size)
    print "Server sent: %s " % data
s.close()

Since you already have a list of clients in your Server , you could use it in a function like that : 由于Server已经有一个客户端列表,因此可以在类似以下功能中使用它:

def send_to_all_clients(self, msg):  
    for client in self.clients : 
        client.connection.send(msg)

Then you can make a function to select a specific client : 然后,您可以创建一个函数来选择特定的客户端:

def send_to_client(self, ip, port, msg): 
    for client in self.clients :  
        if client.ip == ip and client.port == port :  
            client.connection.send(msg)

Note 注意
It's best to add a Send() method to Client and call it to send the msg instead of using client.connection.send(msg) 最好向Client添加Send()方法并调用它以发送msg而不要使用client.connection.send(msg)

You could use those functions in the server's run method , if you modify it to handle events ( you could do that with select.select() , or with user input ( KeyboardInterrupt ) , etc , the design is up to you ) . 您可以在服务器的run方法中使用这些功能,如果您对其进行修改以处理事件(可以使用select.select()或用户输入( KeyboardInterrupt )等来完成,则设计由您决定)。
Also you should modify both client.py and Client , and make them more persistent , because now they close as soon as they sendall or recv . 另外,您应该同时修改client.py和Client ,并使它们更具持久性,因为现在它们一经sendallrecvclose
I hope this gives you some ideas 我希望这能给你一些想法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM