Почему это сокет-соединение разрешает только 1 отправку и получение? - PullRequest
4 голосов
/ 17 декабря 2011

Справочная информация
У меня есть простая настройка сокет-сервера, в которой я пытаюсь разрешить одновременные подключения и вывести данные обратно.Клиентская сторона запускает несколько потоков, каждый из которых устанавливает свое собственное соединение с сервером.Это прекрасно работает для вызова socket.send (), но все последующие вызовы вызывают либо «Сброс соединения по пиру», либо «Сломанный канал».Обратите внимание, что я не нашел изменения, которое переключает сброс и разрыв трубы.Я искал здесь на SO решение, но боюсь, я не знаю, что искать.

Я поступаю неправильно, или я что-то пропускаю в настройках?1006 *

Сервер

import SocketServer

class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        self.data = self.request.recv(1024).strip()
        print "{} wrote: {}\n".format(self.client_address[0], self.data)
        self.request.send(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()

Клиент

import socket
import sys
import threading
import time

HOST, PORT = "localhost", 9999
def create_client():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        cur_thread = threading.current_thread()
        sock.connect((HOST, PORT))
        for x in range(55):
            msg = "{}: {}\n".format(cur_thread.name, str(x))
            # Connect to server and send data
            print cur_thread.name + ": sending message\n"
            sock.send(msg)
            # Receive data from the server and shut down
            received = sock.recv(2048)
            print "RX:" + received
    finally:
        cur_thread = threading.current_thread()
        response = "{}: Closing!\n".format(cur_thread.name)
        print response
        sock.close()

if __name__ == "__main__":
    print "testing single thread"
    #create_client()
    print "starting threads"
    client_1 = threading.Thread(target=create_client)
    client_1.daemon = True
    client_1.start()
    client_2 = threading.Thread(target=create_client)
    client_2.daemon = True
    client_2.start()

    time.sleep(20)

1 Ответ

8 голосов
/ 17 декабря 2011

При возврате из handle сокет закрывается.Используйте цикл while и возвращайтесь из handle только тогда, когда self.data == ''.recv возвращает ноль байтов, когда клиент закрывает соединение.Также не strip() результат, пока после тестирования возвращаемого значения или вы не можете получить ложное закрытие.Наконец, используйте ThreadingTCPServer или сервер может обрабатывать только одно соединение за раз.

Пример:

import SocketServer

class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        while True:
            self.data = self.request.recv(1024)
            if self.data == '':
                break
            self.data = self.data.strip()
            print "{} wrote: {}\n".format(self.client_address[0], self.data)
            self.request.send(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999
    server = SocketServer.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()

Также обратите внимание, что send() не гарантирует отправку всех байтов сообщения, поэтому используйте sendall() или проверьте возвращаемое значение.recv() также может быть хитрым.TCP / IP является потоковым протоколом и не имеет понятия границ сообщений, поэтому вам нужно внедрить протокол, чтобы проверить, что вы получили полное сообщение.Можно отправить 10000 байтов и получить меньше этого, требуя многократных приемов для получения всего сообщения.Также возможно сделать две посылки и получить одновременно одну посылку или даже всю одну посылку и часть другой.Для вашего примера просто буферизация всех полученных до тех пор, пока в сообщении не будет \n, для простого протокола.

...