简体   繁体   中英

TCP sending/receiving missing bytes

I am using C# to create a server software for Windows and Java to create the client software. It works fine most of the time, except for those few exceptions that I don't understand.

I am generally using .ReadLine() and .WriteLine() on both ends to communicate, unless I try to send binary data. That's when I write and read the bytes directly. This is how the software is supposed work:

  1. Client requests the binary data
  2. Server responds with the length of the binary data as a string
  3. Client receives the length and converts it into an integer and starts reading (length) bytes
  4. Server starts writing (length) bytes

It works in most cases, but sometimes the client app doesn't receive the full data and blocks. The server always immediately flushes after writing data, so flushing is not the problem.

Furthermore I've noticed this usually happens with larger files, small files (up to ~1 MB) usually are not a problem.

NOTE It seems like the C# server does send the data completely, so the problem is most likely somewhere in the Java code.

EDIT - Here are some logs from the client side

Working download : pastebin.com/hFd5TvrF

Failing download : pastebin.com/Q3zFWRLB

It seems like the client is waiting for 2048 bytes at the end (as it should be, as length - processed = 2048 in this case), but for some reason the client blocks.

Any ideas what I'm doing wrong? Below are the source codes of both server and client:

C# Server:

public void Write(BinaryWriter str, byte[] data)
{
    int BUFFER = 2048;
    int PROCESSED = 0;
    // WriteString sends the String using a StreamWriter (+ flushing)
    WriteString(data.Length.ToString());
    while (PROCESSED < data.Length)
    {
        if (PROCESSED + BUFFER > data.Length)
            BUFFER = data.Length - PROCESSED;

        str.Write(data, PROCESSED, BUFFER);
        str.Flush();

        PROCESSED += BUFFER;
    }
}

Java Client:

public byte[] ReadBytes(int length){
    byte[] buffer = new byte[length];
    int PROCESSED = 0;
    int READBUF = 2048;
    TOTAL = length;
    progress.setMax(TOTAL);
    InputStream m;
    try {
        m = clientSocket.getInputStream();
        while(PROCESSED < length){
            if(PROCESSED + READBUF > length)
                READBUF = length - PROCESSED;

            try {
                PROCESSED += m.read(buffer, PROCESSED, READBUF);
            } catch (IOException e) {
            }
            XPROCESSED = PROCESSED;
        }
    } catch (IOException e1) {
        // Removed because of sensitive data
    }

    return decryptData(buffer);
}

I've found a fix. As of now, the server sends the length and right after sends the byte array. For some reason this does not work.

So what I've changed is:

  1. Send length and wait for the client to respond with "OK"
  2. Start writing bytes

Not sure why, but it works. Ran it in a while(true) loop and it's been sending data 1000 times in 4 minutes straight and no problems, so I guess it's fixed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM