Question

I have a Java server class like this:

ServerSocket servsock = new ServerSocket(63456);
boolean read = false;
while (!read) {
    Socket sock = servsock.accept();
    int length = 1024;
    byte[] mybytearray = new byte[length];
    OutputStream os = sock.getOutputStream();
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
    while (true) {
    int i = bis.read(mybytearray, 0, mybytearray.length);
    if (i == 1) {
        break;
    }
    os.write(mybytearray, 0, mybytearray.length);
    os.flush();
    }
    sock.close();
    read = true;
}

` And the client is like this:

Socket sock = new Socket("127.0.0.1", 63456);
byte[] mybytearray = new byte[1024];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("C:/tmp/NEWtmp.rar");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
while(bytesRead != -1 ) {
    bos.write(mybytearray, 0, bytesRead);
    bytesRead = is.read(mybytearray, 0, mybytearray.length);
}
bos.close();
sock.close();

One question is: Why the loop does not stop at the end of the file? A second question would be, why is also so slow?

Was it helpful?

Solution

It does not stop because

if (i == 1) {

in your server source should be

if (i == -1) {

Or, if you want to be really safe:

if (i <= 0) {

Also, you risk data corruption with this line:

os.write(mybytearray, 0, mybytearray.length);

You should change this to:

os.write(mybytearray, 0, i);

On performance -- move the os.flush(); call to outside the while loop. When you flush a network stream, you are forcing it to dispatch any buffered data to the network. This is forcing the network layer to send and acknowledge 1024-byte TCP payloads (larger Ethernet payloads, of course) which is probably significantly smaller than your PMTU. You only need to flush when you are done sending data, or when you want the client to receive the buffered data now. Removing the flush call from each iteration will allow the OS-level network buffer to do its job, and segment the data into as few packets as possible.

OTHER TIPS

Second question - your client reads bytes directly from the raw socket stream. Use the BufferedInputStream/BufferedOutputStream decorators, this should increase performance:

Server Side

BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());

Client side

BufferedInputStream is = new BufferedInputStream(sock.getInputStream());

The raw streams are not buffered (AFAIK) so you have to add the buffering manually, if needed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top