2017-04-20 3 views
0

Ich fand Online ein einfacher Multi-Client-Echo-Server in Python-Themen:Multiclient-Server in Python - wie wird gesendet?

#!/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() 

Und ich schrieb einen Client: die Funktionalität

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() 

Alles funktioniert gut, aber ich frage mich, wie konnte ich auf den Server hinzufügen von Broadcast, um die Nachricht an alle verbundenen Clients zurückzusenden? Oder können Sie eine Nachricht an einen bestimmten Kunden senden?

Ich habe alle Clients im Server-Klasse, aber ich weiß nicht, wie (und wo in dem Code des Servers, in Client Klasse oder Server Klasse Ort des Code zu übertragen und private Nachrichten senden? Danke.

EDIT:

Neuer 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() 

Neuer Kunde:

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() 

Antwort

3

Da Sie bereits eine Liste von Kunden in Ihrem Server haben, könnten Sie es in einer Funktion wie das verwenden:

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

Dann können Sie eine Funktion machen einen bestimmten Client wählen:

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
es ist am besten eine Send() Methode zu Client und nennt es hinzuzufügen, um diezu senden 10 statt client.connection.send(msg)

Verwendung Sie können diese Funktionen in der run Methode des Servers verwenden, wenn Sie es ändern Ereignisse zu behandeln (Sie tun können, dass mit select.select() oder mit Benutzereingaben (KeyboardInterrupt), usw., das Design nach oben ist für dich) .
Auch sollten Sie sowohl client.py und Client ändern, und sie persistenter machen, weil sie jetzt close, sobald sie sendall oder recv.
Ich hoffe, das gibt Ihnen einige Ideen

+0

Ja, aber ich möchte dies folgendermaßen tun: Ich möchte an alle Clients nur dann senden, wenn der Client eine Nachricht wie folgt senden: 'broadcast msgtext', und nur dann. Aber auf Server-Seite habe ich keinen Zugriff auf die Nachricht vom Client - die Daten sind in der Client-Klasse, während Clients in der Server-Klasse sind ... Ich habe meine Frage aktualisiert, finde aber immer noch keine Antwort. Kannst du bitte helfen ...? –

+0

Sie könnten dem Client ein 'message' Attribut hinzufügen (zB 'self.msg = None') und lassen den' Server' seinen Wert überprüfen. Ie: 'für den Client in self.clients: if client.msg == 'broadcast msgtext': self.send_to_all_clients (client.msg); client.msg = None' (setze es auf 'None' zurück, damit du nicht immer wieder dieselbe Nachricht sendest) –

+0

Du musst die while-Schleife in' Server.run' modifizieren, um 'client.msg' zu überprüfen. Sie können dies entweder tun, indem Sie ein Timeout in 'Server.server' setzen und versuchen - außer in der Schleife, oder mit' select.select() '. [Hier] (http://www.binarytides.com/python-socket-server-code-example/) finden Sie ein Beispiel für Letzteres. –

Verwandte Themen