2011-12-17 218 views
1

我正在使用Python 3.2中的localhost套接字編寫進程間通信並在Windows上測試它。以下是一些帶有服務器和客戶端的測試代碼,相互發送消息。奇怪的是,它隨機失敗,RuntimeError錯誤,在receive函數中提出,在第5或第10個連接的某處。Python套接字無法接收數據

#!/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),或者如果我改變的消息整理了一下。

有沒有辦法讓它工作,而不用隨意等待,並允許任意協議?

+0

有一個有用的[socketserver](http://docs.python.org/py3k/library/socketserver.html)模塊,它使你的服務器代碼更加穩定和可讀。 – Kirill 2011-12-17 18:02:18

回答

0

這是因爲你的server_function中的conn.shutdown(socket.SHUT_WR)。你需要的是socket.SHUT_RD,或者更好的是,根本不需要shutdown()調用。

+0

謝謝。根本沒有幫助,但將其更改爲SHUT_RD完成了這項工作。 – Kolmar 2011-12-17 17:57:36