Python socket无法接收数据

1 投票
1 回答
2022 浏览
提问于 2025-04-17 08:33

我正在用Python 3.2编写进程间通信,使用本地的套接字,并在Windows上进行测试。这是一些测试代码,包括一个服务器和一个客户端,它们可以互相发送消息。奇怪的是,它在第5次或第10次连接时,随机出现RuntimeError错误,这个错误是在receive函数中抛出的。

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

不过,如果我在client_function中取消注释time.sleep(0.01),或者稍微调整一下消息的顺序,就不会出现错误。

有没有办法让它正常工作,而不需要随便加一些等待时间,也不影响协议的灵活性呢?

1 个回答

0

这是因为你在 server_function 里用了 conn.shutdown(socket.SHUT_WR)。你需要的是 socket.SHUT_RD,或者更简单的,干脆把 shutdown() 这个调用去掉。

撰写回答