我已经实现了一个基于NIO的SocketChannerl服务器,它将JOB委托给Socket客户端。
服务器能够将第一个作业java对象成功发送给客户端。发送第二个对象时,我在客户端看到以下异常:
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1381)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at org.cloudcoder.builder2.server.Builder2Server.safeReadObject(Builder2Server.java:370)
at org.cloudcoder.builder2.server.Builder2Server.runOnce(Builder2Server.java:294)
at org.cloudcoder.builder2.server.Builder2Server.run(Builder2Server.java:273)
at java.lang.Thread.run(Thread.java:745)
由于此原因,客户端断开连接并重新连接到服务器。即使重新连接后,第一个对象也会成功传输到客户端;第二个对象发送失败,这进入循环。
从其他各种SO问题中,我知道如果我们在服务器端使用新的OOS每次向客户端发送数据,就会发生这种异常。为了编写Java对象,我正在使用SocketChannerl.write API。
对象发送代码:
// Generate the ByteBuffer from Submission object
Job job = getNextJobToProcess();
ByteBuffer jobByteBuffer = getBuffer(job);
if (jobByteBuffer != null) {
LOGGER.info("Capacity of buffer is {}", jobByteBuffer.capacity());
while(jobByteBuffer.hasRemaining()) {
int noOfSourceCodeBuffer = socketChannel.write(sourceCodeBuffer);
LOGGER.info("{} no of bytes of job buffer written to the socket "
+ "channel {}", noOfSourceCodeBuffer, this);
}
success = true;
}
Job Java Object to ByteBuffer转换器:
/**
* Utility method generates byte buffer from a object which ISA {@link Serializable}
*
* @param obj instance of {@link Serializable}
* @return ByteBuffer
* @throws IOException
*/
private ByteBuffer getBuffer(final Serializable obj) throws IOException {
// Create ByteArrayOutputStream and ObjectOutputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
// write the Serializable object into ObjectOutputStream
objectOutputStream.writeObject(obj);
// Create a ByteBuffer with the size of byteArrayOutputStream
ByteBuffer buffer = ByteBuffer.allocate(byteArrayOutputStream.size());
// copy the ByteArrayOutputStream content to ByteBuffer
buffer.put(byteArrayOutputStream.toByteArray());
// mark it for read
buffer.flip();
return buffer;
}
根据设计,NIO服务器接受来自旧版java.net.Socket
客户端的连接。连接客户端后,NIO服务器开始将JOB委托给客户端;然后客户端处理JOB并将结果发送回服务器。一旦服务器收到结果,它就认为客户端是空闲的,并准备好发送下一个JOB。此链将继续,直到客户端明确关闭。