Hi,
the following socket I/O test code shows that under Linux there is a problem when the size of the transferred data is too small.
The problem seems to be the same with different kernel versions and with different builds of Java Hotspot Client VM 1.6.0.
For a request/response length of 20000 bytes everything is ok. But e.g. for a length of 200 bytes I get about 12 requests per second. I think I have flushed the OutputStream of the client socket at the right places.
I had the same problem with a server implemention using NIO.
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.Random;
/**
* With REQUEST_LENGTH=20000 the result is for example "6945 requests in 10 seconds".
* With REQUEST_LENGTH=200 the result is only "124 requests in 10 seconds"!
* Flushing of network buffers?
* Same effect with different Linux kernels and with different builds of Java Hotspot Client VM 1.6.0.
*/
public class SocketTest {
//private static final int REQUEST_LENGTH = 20000;
private static final int REQUEST_LENGTH = 200;
private static final int PORT = 12345;
private static final int TEST_DURATION_SECONDS = 10;
public static void main(String[] args) {
ServerThread s = new ServerThread();
s.start();
ClientThread c = new ClientThread();
c.start();
try {
Thread.sleep(TEST_DURATION_SECONDS * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println(c.getNRequests() + " requests in " + TEST_DURATION_SECONDS + " seconds");
System.exit(0);
}
private static class ServerThread extends Thread {
private ServerSocket serverSocket;
public ServerThread() {
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public void run() {
System.err.println("ServerThread started");
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
System.err.println("Connection established");
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
while (true) {
try {
// read request
InputStream is = clientSocket.getInputStream();
ByteBuffer bb = ByteBuffer.allocate(4);
byte[] lengthAsBytes = bb.array();
int offset = 0;
while (offset < 4) {
offset += is.read(lengthAsBytes, offset, 4 - offset);
}
bb.position(0);
bb.limit(4);
int length = bb.getInt();
bb.clear();
byte[] request = new byte[length];
offset = 0;
while (offset < length) {
offset += is.read(request, offset, length - offset);
}
// echo
byte[] response = request;
// write response
OutputStream os = clientSocket.getOutputStream();
bb.putInt((int) response.length);
bb.flip();
os.write(lengthAsBytes);
os.write(response);
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private static class ClientThread extends Thread {
private String testString;
private Socket socket;
private int nRequests;
public ClientThread() {
Random r = new Random();
StringBuffer buf = new StringBuffer();
for (int i = 0; i < REQUEST_LENGTH; i++) {
char c = (char) ('a' + r.nextInt(26));
buf.append(c);
}
testString = buf.toString();
}
public int getNRequests() {
return nRequests;
}
public void run() {
System.err.println("ClientThread started");
try {
socket = new Socket();
socket.connect(new InetSocketAddress("localhost", PORT), 10000);
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
ByteBuffer bb = ByteBuffer.allocate(4);
while (true) {
// write request
byte[] bytes = testString.getBytes();
bb.putInt((int) bytes.length);
bb.flip();
byte[] lengthAsBytes = bb.array();
bb.clear();
os.write(lengthAsBytes);
os.write(bytes);
os.flush();
// read response
lengthAsBytes = bb.array();
int offset = 0;
while (offset < 4) {
offset += is.read(lengthAsBytes, offset, 4 - offset);
}
bb.position(0);
bb.limit(4);
int length = bb.getInt();
bb.clear();
byte[] result = new byte[length];
offset = 0;
while (offset < length) {
offset += is.read(result, offset, length - offset);
}
nRequests++;
String resultString = new String(result);
if (!resultString.equals(testString)) {
System.err.println("RESULT STRING != TEST STRING");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Edited by: chelfrich on Jan 30, 2008 10:03 AM