Frage

Ich bin eine Multithreading-Socket-Anwendung in Python zu schreiben das Socket-Modul. der Server wartet auf Verbindungen, und wenn es einen wird es erzeugt einen Thread für die Buchse.

der Server-Thread an den Client sendet einige Daten. aber der Kunde ist noch nicht bereit, sie zu empfangen. Ich dachte, das der Server verursacht würde warten müssen, bis die Client recv beginnt, sondern kehrt sofort zurück

der Kunde ruft dann recv, die blockiert und keine Daten jemals erhalten.

Client-Socket-Konstruktor

self.__clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__clientSocket.connect((server, port))

Server-Socket-Konstruktor

        self.servSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.servSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        #self.servSock.settimeout(None)
        self.servSock.setblocking(1)
        self.servSock.bind((self.addr,self.port))
        self.servSock.listen(5)

Thread hören akzeptieren

    try:
        (cs, address) = self.servSock.accept()
    except socket.timeout:
        return
    threadName = '\r\nClient %s:%s\r\n' % (cs, address)
    print threadName
    clientSocketHandler = ClientSocket()
    clientSocketHandler.setClientSocket(cs)
    self.clients.newThread(self.clientFunc, {clientSocketHandler : "1"}, threadName).start()

Server und Clients senden / rec Methoden von innen Clientsocket

receivedData = self.__clientSocket.recv(1024*1024)

self.__clientSocket.send(s)

irgendwelche Ideen, warum send () kehrt sofort?

War es hilfreich?

Lösung

  

irgendwelche Ideen, warum send () kehrt sofort?

alle send () tut, ist die Netzwerkpuffer füllen und die ammount der gesendeten Bytes zurück.

Wenn Sie eine Nachricht senden möchten, dass Blöcke empf nur eine Bestätigungsnachricht von dem Client.

Andere Tipps

Der Client muss nicht bereit, Daten zu empfangen - Daten werden in den Sockel der Warteschlange Empfangspuffer bis zu recv bereit sind () es. Senden kehrt sofort, weil der Sendepuffer nicht voll ist -. Wenn es voll ist, send () würde blockieren, bis es Platz für die Daten war die Sie senden wollten

Die meiste Zeit werden Sie es nie füllen - also, was Sie erleben. Auf einer Seite, wollen Sie wahrscheinlich keinen recv Anruf mit 1024 * 1024 in ihm -., Die ein wenig auf der hohen Seite ist

Es tut uns Leid über die Verzögerung festgelegt i das Problem kurz nach diese Frage stellen. @Lee Dank für Ihre Antwort darauf wies mich in der richtigen Richtung. Die Lösung war eine 4-Byte-int Angabe der Größe der Daten senden zu folgen. der Kunde würde diese vier Bytes und dann die Größe der Daten immer erhalten.

from commandClass import Command
from commandActionClass import CommandAction
import socket
from time import *
import struct

class ClientSocket():
    instance = None
    __connected = False
    __clientSocket = None

    @staticmethod
    def getInstance():
        if ClientSocket.instance == None:
            ClientSocket.instance = ClientSocket()
        return ClientSocket.instance

    def __init__(self):
        self.__connected = False
        self.receivedData = ''
        self.bufSize = 4096
        self.buffer = ''

    def connect(self, server, port):
        if self.isConnected():
            raise Exception('Already connected.')

        self.__clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.__clientSocket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
        self.__clientSocket.connect((server, port))
        self.__clientSocket.setblocking(1)
        self.__connected = True

    def disconnect(self):
        try:
            self.receivedData = ''
            self.buffer = ''
            self.__clientSocket.close()
        except Exception, e:
            print e
        finally:
            self.__connected = False

    def sendString(self,s):
        try:
            if (self.isConnected()):
                self.__clientSocket.send(s)
        except Exception, e:
            print e
            self.disconnect()

    def __pop(self, size):
        data = self.receivedData[:size]
        self.receivedData = self.receivedData[size:]
        return data

    def __recv(self,toRead):
        self.flush()
        while ((len(self.receivedData)<toRead)and(self.isConnected())):
            data = self.__clientSocket.recv(self.bufSize)
            if not data:
                self.disconnect()
            self.receivedData = self.receivedData + data

        return self.__pop(toRead)

    def __sendint(self, x):
        self.__sendall(struct.pack("i", x))

    def __recvint(self):
        data = self.__recv(4)
        if not data:
            raise Exception('Expected to receive buffer size')
        return struct.unpack("i", data)[0]

    def flush(self):
        if len(self.buffer)>0:
            self.__clientSocket.sendall(self.buffer)
        self.buffer = ''

    def __sendall(self, s):
        self.buffer = self.buffer + s

    def send(self,s):
        try:
            if (not self.isConnected()):
                raise Exception('Socket is not connected')
            data = s.pickle()
            self.__sendint(len(data))
            self.__sendall(data)
        except Exception, e:
            self.disconnect()
            raise e

    def sendEOC(self):
        self.send(Command(CommandAction.EOC, time()))#send our system time. can be used for ping

    def receive(self):
        if (not self.isConnected()):
            raise Exception('Socket Error. Not Connected')
        try:
            #first receive the size of packet
            buffsize = self.__recvint()
            #now receive the actual data
            data = self.__recv(buffsize)

            if not data:
                raise Exception('No data to receive')

            command = Command.unpickle(data)
        except Exception, e:
            self.disconnect()
            command = Command(CommandAction.Invalid, None)
            raise e
        #finally?
        return command

    def isConnected(self):
        return self.__connected

    def setClientSocket(self, clientSocket):
        self.__clientSocket = clientSocket
        self.__connected = True #assume its connected
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top