Question

Je vous écris une application de prise dans le python multithread à l'aide du module de prise. le serveur écoute les connexions et quand il fait une il génère un filetage pour que la douille.

le fil du serveur envoie des données au client. mais le client n'est pas encore prêt à le recevoir. Je pensais que cela aurait causé le serveur d'attendre jusqu'à ce que le client commence recv mais retourne immédiatement à la place

le client appelle ensuite recv qui bloque et aucune donnée n'est reçu.

constructeur de socket client

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

constructeur de socket serveur

        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)

écoute fil accepter

    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()

serveur et les clients envoient des méthodes / rec de l'intérieur ClientSocket

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

self.__clientSocket.send(s)

idées pourquoi envoyer () est de retour tout de suite?

Était-ce utile?

La solution

  

idées pourquoi envoyer () est de retour tout de suite?

tout envoi () ne fait remplir la mémoire tampon de réseau et le retour ammount d'octets envoyés.

si vous voulez un envoi qui bloque juste recv un message d'accusé de réception du client.

Autres conseils

Le client ne doit pas être prêt à recevoir des données - données file d'attente dans la mémoire tampon de réception de la prise jusqu'à ce que vous êtes prêt à recv () il. Envoyer instantanément parce que le rendement tampon d'émission est pas plein -. Si elle était pleine, envoyer () bloquerait jusqu'à ce qu'il y avait de la place pour les données que vous souhaitez envoyer

La plupart du temps vous ne remplissez - donc ce que vous vivez. D'un côté, vous ne voulez probablement pas un appel recv avec 1024 * 1024 en elle -. Qui est un peu sur le côté haut

Désolé du retard je fixe le problème peu de temps après avoir posé cette question. @Lee merci pour votre réponse, il m'a orienté dans la bonne direction. la solution était d'envoyer un 4byte int spécifiant la taille des données à suivre. le client recevrait toujours ces quatre octets et la taille des données.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top