Domanda

Sto scrivendo un'applicazione multithread presa in Python utilizzando il modulo socket. il server in ascolto per le connessioni e quando si arriva uno che genera un thread per socket.

il filo server invia alcuni dati al client. ma il cliente non è ancora pronto a riceverlo. Ho pensato che questo avrebbe causato il server di aspettare fino a quando il cliente inizia recv ma invece restituisce immediatamente

Il client chiama recv che blocca e nessun dato è mai ricevuti.

client presa costruttore

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

Presa costruttore server

        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)

ascolto accettare filo

    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 e client inviano i metodi / REC dall'interno ClientSocket

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

self.__clientSocket.send(s)

Tutte le idee perché send () sta tornando subito?

È stato utile?

Soluzione

  

Tutte le idee perché send () sta tornando subito?

tutto send () non fa altro che riempire il buffer di rete e riportare la quantità degli byte inviati.

se si desidera un invio che blocca solo recv un messaggio di conferma da parte del cliente.

Altri suggerimenti

Il cliente non deve essere pronti a ricevere i dati - i dati saranno in coda nel buffer di ricezione del socket fino a quando si è pronti a recv () esso. Invia restituisce immediatamente perché il buffer di trasmissione non è pieno -. Se era piena, send () avrebbe bloccato finché non ci fosse spazio per i dati che si desidera inviare

La maggior parte delle volte non avrete mai riempirlo - quindi quello che stai vivendo. Su un lato, probabilmente non si vuole una chiamata recv con risoluzione 1024 * 1024 in essa -. Che è un po 'sul lato alto

Ci scusiamo per il ritardo ho risolto il problema subito dopo questa domanda. @Lee grazie per la risposta che mi ha segnalato nella giusta direzione. la soluzione era quella di inviare un 4byte int specificando la dimensione dei dati da seguire. il cliente avrebbe sempre ricevere questi quattro byte e poi la dimensione dei dati.

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top