문제

소켓 모듈을 사용하여 Python에서 멀티 스레드 소켓 애플리케이션을 작성하고 있습니다. 서버는 연결을 듣고 연결하면 해당 소켓의 스레드가 생성됩니다.

서버 스레드는 일부 데이터를 클라이언트에 보냅니다. 그러나 고객은 아직 그것을받을 준비가되지 않았습니다. 나는 이것이 클라이언트가 recv를 시작할 때까지 서버가 기다렸다 고 생각했지만 대신 즉시 돌아옵니다.

그런 다음 클라이언트는 차단중인 RECV를 호출하며 데이터가 수신되지 않습니다.

클라이언트 소켓 생성자

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

서버 소켓 생성기

        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)

듣기 스레드를 수락합니다

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

서버 및 클라이언트 내부에서 내부에서 보내기/REC 메소드

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

self.__clientSocket.send(s)

Send ()가 곧바로 돌아 오는 이유는 무엇입니까?

도움이 되었습니까?

해결책

Send ()가 곧바로 돌아 오는 이유는 무엇입니까?

모든 send ()는 네트워크 버퍼를 채우고 전송 된 바이트의 탄약을 반환하는 것입니다.

그 블록을 보내는 것을 원한다면 클라이언트로부터 승인 메시지를 표시하십시오.

다른 팁

클라이언트는 데이터를 수신 할 준비가되어 있지 않아도됩니다. 데이터는 recv ()를 준비 할 때까지 소켓의 수신 버퍼에서 대기열을 늘립니다. 보내기 버퍼가 가득 차 있지 않기 때문에 반품을 즉시 보내십시오. 가득 차면 보내기 원하는 데이터의 공간이있을 때까지 send ()가 차단됩니다.

대부분의 경우에는 결코 그것을 채우지 않을 것입니다. 따라서 당신이 겪고있는 것. 측면에서, 당신은 아마도 1024*1024의 recv 호출을 원하지 않을 것입니다. 그것은 약간 높습니다.

이 질문을 한 직후 문제를 해결 한 지연에 대해 죄송합니다. @lee 답변 해 주셔서 감사합니다. 올바른 방향으로 나를 지적했습니다. 솔루션은 따라야 할 데이터의 크기를 지정하는 4BTE INT를 보내는 것이 었습니다. 클라이언트는 항상이 4 바이트와 데이터 크기를받습니다.

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top