user622505
user622505

Reputation: 773

Python to C# TCP transfer corrupts data beyond 1523rd byte

I'm trying to send a long string from a python server to a C# client. The string is 230400 bytes long. I'm both sending and receiving in chunks of 64 bytes. Server code:

import socket

def initialize():
  global s
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  s.bind(('', 1719))
  s.listen()

initialize()

while(1):
  sock, addr = s.accept()

  msgstr = generate_msg_string() # irrelevant

  msglen = len(msgstr)

  totalsent = 0
  while totalsent < msglen:
    sent = sock.send(msgstr[totalsent:totalsent+64])
    totalsent = totasent + sent

  sock.close()

Client code:

TcpClient tcpClient = new TcpClient();
tcpClient.Connect(ip, 1719);
byte[] ba = new byte[230400];
byte[] buffer = new byte[64];
tcpClient.ReceiveBufferSize = 64
int i=0;
while(i != 230400)
{
    stream.Read(buffer, 0, 64);
    buffer.CopyTo(ba, i);
    i += 64;
}
tcpClient.Close();

I've checked a few connections in a row - the first 1523 bytes are correct and all the rest are gibberish - at least seemingly random.

Any idea what might be the cause?

Upvotes: 1

Views: 170

Answers (2)

Marc Gravell
Marc Gravell

Reputation: 1062855

while(i != 230400)
{
    stream.Read(buffer, 0, 64);
    buffer.CopyTo(ba, i);
    i += 64;
}

The fundamental error here is assuming that Read read 64 bytes. It can read any of:

  • 0 if the socket gets closed for any reason
  • 64 bytes if that happens to be available and it chooses to
  • 1-63 bytes, just for fun

You are not guaranteed anything other than "non-positive if the stream is closed, else at least 1 byte and no more than 64 bytes"

You must must must read the return value of Read and only process that much of the buffer. This remains the case if you switch to Socket.Receive, by the way.

Also - why don't you just fill ba in the first place, increment in the offset and decrementing the count each time?

int count = 230400, offset = 0, read;
byte[] ba = new byte[count];
while(count > 0 && (read=stream.Read(ba, offset, count)) > 0)
{
    offset += read;
    count -= read;
}
if(read!=0) throw new EndOfStreamException();

Upvotes: 3

user622505
user622505

Reputation: 773

It seems that I hurried with the question.

Changing TcpClient to Socket fixed the problem. The approach remained the same.

Upvotes: 0

Related Questions