Python Blocking Sockets, Send Returns Immediately
Solution 1:
any ideas why send() is returning straight away?
all send() does is fill the network buffer and return the ammount of bytes sent.
if you want a send that blocks just recv an acknowledgement message from the client.
Solution 2:
The client doesn't have to be ready to receive data - data will queue up in the socket's receive buffer until you are ready to recv() it. Send returns instantly because the send buffer isn't full - if it was full, send() would block until there was room for the data you wanted to send.
Most of the time you'll never fill it - hence what you are experiencing. On a side, you probably don't want a recv call with 1024*1024 in it - that's a little on the high side.
Solution 3:
Sorry about the delay i fixed the problem shortly after asking this question. @Lee thanks for your answer it pointed me in the right direction. the solution was to send a 4byte int specifying the size of the data to follow. the client would always receive these four bytes and then the size of the data.
from commandClass import Command
from commandActionClass import CommandAction
import socket
from time import *
import struct
classClientSocket():
instance = None
__connected = False
__clientSocket = None @staticmethoddefgetInstance():
if ClientSocket.instance == None:
ClientSocket.instance = ClientSocket()
return ClientSocket.instance
def__init__(self):
self.__connected = False
self.receivedData = ''
self.bufSize = 4096
self.buffer = ''defconnect(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 = Truedefdisconnect(self):
try:
self.receivedData = ''
self.buffer = ''
self.__clientSocket.close()
except Exception, e:
print e
finally:
self.__connected = FalsedefsendString(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)
ifnot 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)
ifnot data:
raise Exception('Expected to receive buffer size')
return struct.unpack("i", data)[0]
defflush(self):
iflen(self.buffer)>0:
self.__clientSocket.sendall(self.buffer)
self.buffer = ''def__sendall(self, s):
self.buffer = self.buffer + s
defsend(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
defsendEOC(self):
self.send(Command(CommandAction.EOC, time()))#send our system time. can be used for pingdefreceive(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)
ifnot 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
defisConnected(self):
return self.__connected
defsetClientSocket(self, clientSocket):
self.__clientSocket = clientSocket
self.__connected = True#assume its connected
Post a Comment for "Python Blocking Sockets, Send Returns Immediately"