40

所以我正在开发一个需要套接字来处理多个客户端进行在线游戏的 iPhone 应用程序。我已经尝试过 Twisted,并且付出了很多努力,我未能立即发送一堆信息,这就是为什么我现在要尝试使用 socket。

我的问题是,使用下面的代码,您将如何连接多个客户端?我已经尝试过列表,但我无法弄清楚它的格式。在一次连接多个客户端并且我能够向特定客户端发送消息的情况下,如何实现这一点?

谢谢!

#!/usr/bin/python           # This is server.py file

import socket               # Import socket module
s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 50000                # Reserve a port for your service.

print 'Server started!'
print 'Waiting for clients...'

s.bind((host, port))        # Bind to the port
s.listen(5)                 # Now wait for client connection.
c, addr = s.accept()     # Establish connection with client.
print 'Got connection from', addr
while True:
   msg = c.recv(1024)
   print addr, ' >> ', msg
   msg = raw_input('SERVER >> ')
   c.send(msg);
   #c.close()                # Close the connection
4

7 回答 7

47

根据您的问题:

我的问题是,使用下面的代码,您将如何连接多个客户端?我已经尝试过列表,但我无法弄清楚它的格式。在一次连接多个客户端并且我能够向特定客户端发送消息的情况下,如何实现这一点?

使用您提供的代码,您可以执行以下操作:

#!/usr/bin/python           # This is server.py file                                                                                                                                                                           

import socket               # Import socket module
import thread

def on_new_client(clientsocket,addr):
    while True:
        msg = clientsocket.recv(1024)
        #do some checks and if msg == someWeirdSignal: break:
        print addr, ' >> ', msg
        msg = raw_input('SERVER >> ')
        #Maybe some code to compute the last digit of PI, play game or anything else can go here and when you are done.
        clientsocket.send(msg)
    clientsocket.close()

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 50000                # Reserve a port for your service.

print 'Server started!'
print 'Waiting for clients...'

s.bind((host, port))        # Bind to the port
s.listen(5)                 # Now wait for client connection.

print 'Got connection from', addr
while True:
   c, addr = s.accept()     # Establish connection with client.
   thread.start_new_thread(on_new_client,(c,addr))
   #Note it's (addr,) not (addr) because second parameter is a tuple
   #Edit: (c,addr)
   #that's how you pass arguments to functions when creating new threads using thread module.
s.close()

正如 Eli Bendersky 提到的,您可以使用进程而不是线程,还可以检查 pythonthreading模块或其他异步套接字框架。注意:检查留给您以实现您想要的方式,这只是一个基本框架。

于 2016-10-31T21:40:26.117 回答
18

accept可以不断提供新的客户端连接。但是,请注意,它和其他套接字调用通常是阻塞的。因此,此时您有几个选择:

  • 打开新线程来处理客户端,而主线程返回接受新客户端
  • 如上所述,但使用进程而不是线程
  • 使用异步套接字框架,如 Twisted 或其他许多框架
于 2012-05-30T06:04:31.443 回答
8

这是SocketServer 文档中的示例,它是一个很好的起点

import SocketServer

class MyTCPHandler(SocketServer.BaseRequestHandler):
    """
    The RequestHandler class for our server.

    It is instantiated once per connection to the server, and must
    override the handle() method to implement communication to the
    client.
    """

    def handle(self):
        # self.request is the TCP socket connected to the client
        self.data = self.request.recv(1024).strip()
        print "{} wrote:".format(self.client_address[0])
        print self.data
        # just send back the same data, but upper-cased
        self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999

    # Create the server, binding to localhost on port 9999
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)

    # Activate the server; this will keep running until you
    # interrupt the program with Ctrl-C
    server.serve_forever()

从这样的终端尝试

$ telnet localhost 9999
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello
HELLOConnection closed by foreign host.
$ telnet localhost 9999
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Sausage
SAUSAGEConnection closed by foreign host.

您可能还需要使用 A Forking 或 Threading Mixin

于 2012-05-30T06:05:04.150 回答
2

该程序将打开 26 个套接字,您可以在其中将大量 TCP 客户端连接到它。

#!usr/bin/python
from thread import *
import socket
import sys

def clientthread(conn):
    buffer=""
    while True:
        data = conn.recv(8192)
        buffer+=data
        print buffer
    #conn.sendall(reply)
    conn.close()

def main():
    try:
        host = '192.168.1.3'
        port = 6666
        tot_socket = 26
        list_sock = []
        for i in range(tot_socket):
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
            s.bind((host, port+i))
            s.listen(10)
            list_sock.append(s)
            print "[*] Server listening on %s %d" %(host, (port+i))

        while 1:
            for j in range(len(list_sock)):
                conn, addr = list_sock[j].accept()
                print '[*] Connected with ' + addr[0] + ':' + str(addr[1])
                start_new_thread(clientthread ,(conn,))
        s.close()

    except KeyboardInterrupt as msg:
        sys.exit(0)


if __name__ == "__main__":
    main()
于 2017-04-20T17:28:02.147 回答
0

您可以使用PySock,这是一个 python 库,可以让编写多客户端服务器变得非常容易。您可以从 PyPi 下载它,适用于 windows :pip install PySock和 Linux : pip3 install PySock。他们在 PyPi 介绍页面上有很好的样板代码。您可以在此处查看或转到 GitHub存储库以获取有关版本的更多见解。它提供了一些很棒的功能,即无需任何额外工作即可进行客户端-客户端通信,您可以对这些通信进行 E2E 加密。

于 2021-08-17T15:11:19.677 回答
0
def get_clients():
    first_run = True
    startMainMenu = False

    while True:
        if first_run:
            global done
            done = False
            Thread(target=animate, args=("Waiting For Connection",)).start()

        Client, address = objSocket.accept()
        global menuIsOn
        if menuIsOn:
            menuIsOn = False  # will stop main menu
            startMainMenu = True

        done = True

        # Get Current Directory in Client Machine
        current_client_directory = Client.recv(1024).decode("utf-8", errors="ignore")

        # beep on connection
        beep()
        print(f"{bcolors.OKBLUE}\n***** Incoming Connection *****{bcolors.OKGREEN}")
        print('* Connected to: ' + address[0] + ':' + str(address[1]))
        try:
            get_client_info(Client, first_run)
        except Exception as e:
            print("Error data received is not a json!")
            print(e)
        now = datetime.now()
        current_time = now.strftime("%D %H:%M:%S")
        print("* Current Time =", current_time)

        print("* Current Folder in Client: " + current_client_directory + bcolors.WARNING)

        connections.append(Client)

        addresses.append(address)

        if first_run:
            Thread(target=threaded_main_menu, daemon=True).start()

            first_run = False
        else:
            print(f"{bcolors.OKBLUE}* Hit Enter To Continue.{bcolors.WARNING}\n#>", end="")
        if startMainMenu == True:
            Thread(target=threaded_main_menu, daemon=True).start()
            startMainMenu = False
于 2021-01-30T14:20:58.040 回答
-1
#!/usr/bin/python
import sys
import os
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)         
port = 50000

try:
    s.bind((socket.gethostname() , port))
except socket.error as msg:
    print(str(msg))
s.listen(10)
conn, addr = s.accept()  
print 'Got connection from'+addr[0]+':'+str(addr[1]))
while 1:
        msg = s.recv(1024)
        print +addr[0]+, ' >> ', msg
        msg = raw_input('SERVER >>'),host
        s.send(msg)
s.close()
于 2017-10-27T16:56:20.093 回答