Сокет Python не может получать данные - PullRequest
1 голос
/ 17 декабря 2011

Я пишу межпроцессное взаимодействие с использованием сокетов localhost в Python 3.2 и тестирую его в Windows. Вот некоторый тестовый код с сервером и клиентом, отправляющий сообщения друг другу. Странно, но случайно происходит ошибка с ошибкой RuntimeError, возникающей в функции receive, где-то около 5-го или 10-го соединения.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import socket
import pickle
import time
import logging
from multiprocessing import Process

def receive(conn):
    def ensure_receive(length):
        parts = []
        received = 0
        while received < length:
            chunk = conn.recv(length - received)
            if not chunk:
                raise RuntimeError("Connection broken")
            parts.append(chunk)
            received += len(chunk)
        return b''.join(parts)
    lengthString = ensure_receive(8)
    serialized = ensure_receive(int(lengthString))
    return pickle.loads(serialized)

def send(conn, message):
    def ensure_send(message):
        sent = 0
        while sent < len(message):
            sent += conn.send(message[sent:])
#            logging.warning("Now sending")
    serialized = pickle.dumps(message, 1)
    messageLength = len(serialized)
    ensure_send("{:8}".format(messageLength).encode('Latin-1'))
    ensure_send(serialized)

def client_function(clientLimit):
    for index in range(1, clientLimit + 1):
        print ("Client", index)
        try:
            conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            conn.connect(('localhost', 12333))
            send(conn, list(range(100000)))
            message = receive(conn)
            send(conn, list(range(100)))
#            time.sleep(0.01)
            conn.shutdown(socket.SHUT_WR)
            conn.close()
        except Exception:
            logging.exception("Socket error in client")

def server_function(clientLimit):
    newSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    newSocket.bind(('localhost', 12333))
    newSocket.listen(16)
    for _ in range(clientLimit):
        (conn, address) = newSocket.accept()
        time.sleep(0.01)
        message = receive(conn)
        send(conn, list(range(10)))
        message = receive(conn)
        conn.shutdown(socket.SHUT_WR)
        conn.close()

def test(clientLimit):
    server = Process(target = server_function, args = (clientLimit,))
    server.start()

    time.sleep(1)
    client = Process(target = client_function, args = (clientLimit,))
    client.start()

    client.join()
    server.join()

if __name__ == "__main__":
    test(100)

Однако ошибок нет, если я раскомментирую time.sleep(0.01) в client_function или если я немного изменю порядок сообщений.

Есть ли способ заставить его работать, не вставляя случайных ожиданий и не допуская произвольных протоколов?

1 Ответ

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

Это происходит из-за conn.shutdown (socket.SHUT_WR) в вашей функции server_function. Что вам нужно, так это socket.SHUT_RD или, что еще лучше, избавиться от вызова shutdown () вообще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...