Client-Server receive/send buffers with TCP/UDP (high data rates)

Platform is windows.

I'm sending data from client to server in UDP datagrams as fast as my thread can. UDP payload is less then one IP packet, let's say 1400 Bytes.

With that amount of payload I can reach only up to 33Mbit/second in 100Mbit network (switch in between). Are threads in java virtual machine so slow that it can't send faster those packets up till 100Mbit?

Or should I increase send buffer size from 8192 to something else to achieve higher rate? If yes, what do you suggest?

Then again if I put data portion to 65 000 Bytes, and use the same thread then about 88Mbit/s is achieved. But then rest of the data is splitted to many IP packets and the UDP packets count is not increased though traffic is increased.

With TCP I have same problem with buffers. I need to create stabile traffic like 40Mbit or 80 Mbit/s but I don't know what size of buffers to use. I send from client to server the same byte [ ] and it easy to create stabile TCP-traffic till 20Mbit/s. After 20 Mbit/s traffic goes irrational and after some time cpu usage is increasing drastically toward 100%.

I use normal thread's and TimerTask in my applications.

This is from Client with TCP-traffic. And it is has been edited but the principle is there

byte[] array;

array=newbyte[2000];

publicvoid run(){

try{

for(int i=0;i<bitrate;i++){

outputstream.write(array);

//System.out.println(i);

}

catch(java.io.IOException ioe){

System.out.println("Exception "+ioe.getMessage());

}

}

If you have better ideas how to create high stable bitrates with TCP/UDP ideas please do tell.>

[2232 byte] By [zrty2a] at [2007-10-3 5:45:11]
# 1

Have you tried it with send and receive buffers of 63k?

Also you should definitely use BufferedInputStreams and BufferedOutputStreams rather than writing directly to/reading directly from the Socket, and you should use quite large buffer sizes when constructing those too. Flush the output just before you read, if you ever read, and close the output stream rather than the socket to ensure the last partial buffer gets sent.

The maximum throughput achievable with TCP is 83% of raw bandwidth, and I'd be surprised if you could do much better via UDP.

ejpa at 2007-7-14 23:53:25 > top of Java-index,Archived Forums,Socket Programming...
# 2

Thank you ejp for replying.

This is quite long post :)

I describe more of the project. I want statistics of what server has received from client . Data-packet amount ,header sizes summed up, actual data size of packets plus some information about the time delays etc...dropped packets.

I have understood that it is not possible directly with java to do that so I tried to use jpcap(not from sourceforge). It works fine for sometime but if I use high data rates like 50Mbit/s it crashes after few minutes. I use the task manager to check memory/CPU and thread usage. Memory is then reducing really fast with those data rates, maybe 60MBytes in that time and cpu usage is increasing then to 100% which collapses jvm (1.5.0_08)

This is basically how my UDP-server works.

import java.net.*;

public class UDPServer extends Thread {

DatagramSocket datagramsocket;

DatagramPacket datagrampacket;

int port;

public UDPServer(int port_){

try{

port=port_;

datagramsocket=new DatagramSocket(port_);

byte[] message = new byte[1518];

datagrampacket = new DatagramPacket(message, 1518);

}

catch(Exception e){

System.out.println("Exception:"+e.getMessage());

}

}

public void run(){

try{

while(currentThread().isInterrupted()==false){

datagramsocket.receive(datagrampacket);

}

}

catch(java.io.IOException ioe){

}

}

public void closeSocket(){

datagramsocket.close();

}

}

This is needed only for listening some port so that server doesn't send back that unreachable packet. 1518 is used because that is the max.length of normal IP-packet.

After some tests without jpcap, task manager showed that when client sends continuously UDP-packets length of 65000 Bytes, network utilization is 88-89% of 100Mbit , processor usage is ~15 % and no problems. Rest of the packet(s) are continued with IP.

So I don't know is there any use to set up those receive buffers. Now for me it seems like the jpcap is the problem and I can't affect that .

And with my TCP Client-Server I get ,according to windows task manager, 99% of network utilization of 100MBit/s. But with that jpcap only 88%.

So any ideas how to continue this project? Ok, c or c++ would be better but that is not an option here. Btw there is GUI involved in both ends here also.

How about the jpcap from sourceforge any experiences?

zrty2a at 2007-7-14 23:53:25 > top of Java-index,Archived Forums,Socket Programming...
# 3

I don't know anything practical about JPCap from any source but I can well believe that it crashes if you thrash it.

Some other observations:

I don't understand why you're sending 65000 bytes but only receiving 1518. This doesn't seem to me to be a valid test. You are asking the stack to throw away (65000-1518) bytes on every receive. So what are you measuring exactly? Surely you should be at least trying to receive 6500? Otherwise you're just measuring the performance of a degenerate application - is this really interesting?

1518 isn't the maximum size of a normal IP packet: if that was true you couldn't send 65000. More likely it is the MTU of the network segments you are using.

Increasing the receive buffer size will decrease packet loss because it will increase the ablity of the receiving IP stack to enqueue incoming datagrams. This should be one of the varying parameters of your experiment, not something you should just make assertions about without even trying it. Not very good experimental method.

Windows' report of 99% network utilization isn't inconsistent with the statement that maximum TCP throughput is 83% or whatever it is: they're measuring different things.

ejpa at 2007-7-14 23:53:25 > top of Java-index,Archived Forums,Socket Programming...
# 4

65000 is splitted to many IP packets. That is what I meant IP-continued. In client mode I can adjust the data size of UDP-datagram to about 65000(constructor allows). I did that only because I wanted to increase bandwidth utilization. It goes somehow faster then. (88% of 100Mbit what ever it measures). WIth ethreal it is shown only 1 UDP packet that way and the rest of it comes IP.

Basically I can use 1400 bytes of UDP size and it fits to 1 IP packet. But then the network util is 33%*100Mbps. There was no packet loss in my implementation it captured every packet but something else is wrong. Ok, I try with buffered inputstream if it makes any difference.

I understand that windows has it's own buffer for coming packets and I give only a hint to it what it should be. Why not then use 1MByte etc.? How about using bytebuffers?

And why 83% is maximum, and how you measure that? Is it with java only?

zrty2a at 2007-7-14 23:53:25 > top of Java-index,Archived Forums,Socket Programming...
# 5

BufferedInputStream is for TCP sockets. For UDP sockets you need to call Socket.setReceiveBufferSize(). It's a good idea for TCP sockets too. This is the 'own buffer' you are talking about.

The 83% (or whatever figure it is) applies to TCP in any language and it is due to protocol overheads (both space and time). It's been both calculated and measured but it's all so long ago I can't give you a reference off-hand. Try news:comp.protocols.tcp-ip for more information.

ejpa at 2007-7-14 23:53:25 > top of Java-index,Archived Forums,Socket Programming...
# 6

Hello.

I tried that setReceiveBufferSize in server and in client setSend... with different values, but the same result occured meaning that after few minutes jvm crashes when using jpcap. Again when the crash is about to come 60MBytes of main memory has been used and cpu usage was 100% for few seconds before crash.

Without jpcap(not from sourceforge) no problems and netlimiter pro 2 eval.version showed that bandwidth usage in UDP was maximum 90Mbit/s. Technically it doesn't matter that how many packets my UDPServer can catch, because calculations are based on jpcap.(It was only there because it needs to be listened so that server doesn't send the reply that "no one is listening " after each packet.

But it seems that my result will be that one should never use Java with this kind of experiment. It is fun while it lasts. But it seems that traffic rate is too high for jpcap thus eating the main memory fast and with pure java I can't handle those headers, dropped packet counts, etc. low level stuff. And for jpcap there is no support available.

But still any ideas or comments are welcomed :) .

zrty2a at 2007-7-14 23:53:25 > top of Java-index,Archived Forums,Socket Programming...