многопоточный сервер python - PullRequest
3 голосов
/ 02 апреля 2011

Я пытаюсь запрограммировать простой многопоточный игровой сервер на Python для развлечения.После большого разочарования я не смог выяснить, почему истекло время моего тестового клиентского соединения.Вот мой код server.py:

    import socket
import threading
import clientThread
import struct
import string

class Server:
    def __init__(self):
        self.HOST = 'localhost'
        self.PORT = 22085
        self.BUFFIZE = 1024
        self.ADDRESS = (self.HOST,self.PORT)
        self.clientList = []
        input("Press enter to start the server. . .")
        self.running = True
        self.serverSock = socket.socket()
        self.serverSock.bind(self.ADDRESS)
        self.serverSock.listen(2)
        self.clientThread = clientThread.clientThread(self)
        print("Starting client thread. . .")
        self.clientThreadObj = threading.Thread(target = self.clientThread.start, args = (self))
        print("Awaiting connections. . .")
        while self.running:
            clientInfo = self.serverSock.accept()
            print("Client connected from %s." % clientInfo[1])
            # Append to clientThread list...

        self.serverSock.close()
        print("- end -")

serv = Server()

Сервер запускает поток для существующих подключений и начинает прослушивание.Поток, созданный для существующих соединений, clientThread, просматривает список клиентских объектов, которые пока ничего не делают, они просто архитектурные.Вот clientThread.py

import socket
import threading
import struct
import string

class clientThread:
    def __init__(self, serv):
        self.server = serv
        self.clientList = []
        self.running = True
        print("Client thread created. . .")
    def start(self):
        print("Beginning client thread loop. . .")
        while self.running:
            for client in self.clientList:
                message = client.sock.recv(self.server.BUFFSIZE)
                if message != None and message != "":
                    client.update(message)

И, наконец, очень простой клиентский объект:

import string

class clientObject:
    def start(self,clientInfo):
        self.sock = clientInfo[0]
        self.address = clientInfo[1]
    def update(self,message):
        self.sock.send("Testamundo.\r\n".encode())

Теперь проблема в том, что мой клиент не может даже подключиться к моему серверу,Это просто время ожидания.Вот код для моего простого клиентского теста:

import socket
import string

address = ("192.168.1.1",22085)
mySocket = socket.socket()

mySocket.connect(address)
print("Connected successfully!")

В строке, которая подключается к адресу, возвращается «попытка подключения не удалась, потому что подключенная сторона не ответила должным образом через некоторое время, илине удалось установить соединение, так как подключенный хост не смог ответить ".

Есть предложения?Спасибо!Извините за весь этот код, я не был уверен, нужно ли мне публиковать все это или нет, поэтому я решил, что это не повредит слишком сильно.

1 Ответ

7 голосов
/ 02 апреля 2011

У вас есть две системы?Имеет ли серверная система IP-адрес 192.168.1.1?Если у вас есть только одна система, адрес localhost: 127.0.0.1.Это было первое изменение, которое мне пришлось внести в ваш код, чтобы получить соединение при запуске сервера и клиента в одной системе.

Другая проблема заключается в том, что ваш клиентский поток фактически не запускается.Поскольку вам нужен класс клиентского потока, вот как его объявить и запустить:

  1. Подкласс из threading.Thread.
  2. Переопределите __init__ для вашего поведения, но вызовите __init__сначала в базовом классе.
  3. Переопределите run для работы потока.
  4. Создайте экземпляр и вызовите его метод start.

Другая проблема заключается вrecv блокирует, если клиент не отправил никаких данных, поэтому, если вы попытаетесь подключить несколько клиентов, он будет зависать в вашем цикле над списком клиентов.Вам потребуется поток для каждого клиента или используйте select.select для запроса клиентских сокетов на готовность к чтению / записи.

Ниже приведен измененный код, который получил один клиент для ответа, но он должен работать для обработки несколькихклиентов.Также необходимо настроить протокол для обработки сообщений.TCP является потоковым протоколом (без границ сообщений), поэтому отправка 'abc' и '123' может привести к получению 'abc123' или 'ab' и 'c123' и т. Д. Он должен обрабатывать закрытиеподключений и удалите клиентские объекты из списка клиентов.

Удачи!Вы узнаете много нового, чтобы понять, как сделать все это с нуля.Посмотрите также библиотеку socketserver.py для примера кода.

srv.py

import socket
import threading
import struct
import string

class clientThread(threading.Thread):
    def __init__(self, serv):
        threading.Thread.__init__(self)
        self.server = serv
        self.clientList = []
        self.running = True
        print("Client thread created. . .")
    def run(self):
        print("Beginning client thread loop. . .")
        while self.running:
            for client in self.clientList:
                message = client.sock.recv(self.server.BUFFSIZE)
                if message != None and message != "":
                    client.update(message)

class clientObject(object):
    def __init__(self,clientInfo):
        self.sock = clientInfo[0]
        self.address = clientInfo[1]
    def update(self,message):
        self.sock.send("Testamundo.\r\n".encode())

class Server(object):
    def __init__(self):
        self.HOST = 'localhost'
        self.PORT = 22085
        self.BUFFSIZE = 1024
        self.ADDRESS = (self.HOST,self.PORT)
        self.clientList = []
        input("Press enter to start the server. . .")
        self.running = True
        self.serverSock = socket.socket()
        self.serverSock.bind(self.ADDRESS)
        self.serverSock.listen(2)
        self.clientThread = clientThread(self)
        print("Starting client thread. . .")
        self.clientThread.start()
        print("Awaiting connections. . .")
        while self.running:
            clientInfo = self.serverSock.accept()
            print("Client connected from {}.".format(clientInfo[1]))
            self.clientThread.clientList.append(clientObject(clientInfo))

        self.serverSock.close()
        print("- end -")

serv = Server()

clnt.py

import socket
import string

address = ('localhost',22085)
mySocket = socket.socket()

mySocket.connect(address)
print("Connected successfully!")
mySocket.send('blah'.encode())
print(mySocket.recv(1024))

Вывод (srv.py)

Press enter to start the server. . .
Client thread created. . .
Starting client thread. . .
Beginning client thread loop. . .
Awaiting connections. . .
Client connected from ('127.0.0.1', 52850).

Выход (clnt.py)

Connected successfully!
b'Testamundo.\r\n'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...