1

I'm starting to use sockets to send a file. I learned I can send in 1024 "chunks" through the socket stream, and piece it back on the server side. I set the server to first get a string containing the size of the file it will receive, and as it reads to compare to see if the read is finished or not.

Client code is:

BUFFER_SIZE = 1024
limit = os.path.getsize("test.db") #4096 bytes
currentamt = BUFFER_SIZE
f = open("test.db", "rb")
l = f.read(BUFFER_SIZE)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(str(limit)) #first, send the limit
while(1):
  s.send(l)
  if currentamt >= limit:
    break
  l = f.read(BUFFER_SIZE)
  currentamt += BUFFER_SIZE
  print "still sending.."

s.close()
print "Done."

Server code is as such:

while True:
  conn, addr = s.accept()
  print "Connection address: ", addr
  f = open('rec.db', 'wb')
  while 1:
    limit = conn.recv(20) #this will get your limit size
    limit = limit.rstrip()
    limit = float(limit) #error in question
    print limit
    l = conn.recv(BUFFER_SIZE) #get byte bufferred back
    while (1):
      if currentamt >= limit:
        f.write(l)
        break
      f.write(l)
      l = conn.recv(BUFFER_SIZE)
      currentamt += BUFFER_SIZE
  f.close() #close your file after you're done
  conn.close()

s.close()

If I change limit in server from 20 to 10, I am able to convert to a float, but then I get an error after the print statement! Also, the print limit does work before the float(limit) statement, which confuses me.

1 Answer 1

1

TCP/IP guarantees that you get the right bytes in the right order. It doesn't guarantee anything about the sizes of the chunks you receive. IOW, if you send 1024 bytes, 1024 bytes, 1024 bytes - then there's nothing to prevent TCP from chopping that into 512 bytes, 512 bytes, 512 bytes, 512 bytes, 512 bytes, 512 bytes - or even stranger things. It also reserves the right to aggregate chunks, to form 2048 bytes, 1024 bytes.

To get around this, it's important to put a loop around your sends and recvs, or to use something that makes it easier to bufsock or twisted. Personally, I think twisted makes this easier but a lot of other things harder, but maybe that's just because I wrote bufsock.

Bufsock is at http://stromberg.dnsalias.org/~strombrg/bufsock.html

In your specific case, I see you sending a length in ASCII, but I don't see you sending any sort of termination character or padding to a field width. That'll reap havoc in the other side of the connection, where it appears to be assuming the length is always 20 characters long. To deal with this, you might:

s.send(str(limit) + '\n')

...but there's still the problem of missing loops. Bufsock does the looping for you, you just have to remember to bufsock.flush() frequently (enough).

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I appreciated the reply. I am tring bufsock now, and also found some other (rather silly) errors that I am correcting as I go. The lack of padding or ending termination character has been causing very interesting results, which is where I was getting confused (e.g. "2048SQLite" would sometimes be given)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.