尊重,
我尝试使用新的Java NIO2在客户端和服务器端创建异步SocketChannel并进行通信,但问题是我发送到服务器上的套接字的所有消息,套接字都作为一条消息读取。这是代码:
我创建了用于编写和读取数据的处理程序:
ReadHandler:
public class ReadHandler implements CompletionHandler<Integer, Msg> {
private AsynchronousSocketChannel _socket;
private SocketHandler _socketHandler;
private ByteBuffer _buffer;
public ReadHandler(SocketHandler socketHandler) {
this._socketHandler = socketHandler;
_buffer = ByteBuffer.allocate(100);
this._socket = this._socketHandler.getSocket();
this._socket.read(_buffer, null, this);
}
@Override
public void completed(Integer result, Msg attachment) {
System.out.println("readdddd " + result);
String message = new String(_buffer.array());
System.out.println("mess:" + message);
}
@Override
public void failed(Throwable exc, Msg attachment) {
System.out.println(exc.getMessage());
}
}
ClientWriteHandler
public class ClientWriteHandler implements CompletionHandler<Integer, Msg> {
private AsynchronousSocketChannel _socket;
private ClientSocket _clientHandler;
private ByteBuffer _buffer;
public ClientWriteHandler(ClientSocket clientHandler) {
this._clientHandler = clientHandler;
_buffer = ByteBuffer.allocate(2048);
this._socket = this._clientHandler.getSocket();
}
@Override
public void completed(Integer result, Msg attachment) {
System.out.println("write " + result);
_buffer.clear();
}
@Override
public void failed(Throwable exc, Msg attachment) {
System.out.println(exc.getMessage());
}
public void write(String data) {
_buffer = ByteBuffer.allocate(2048);
this._socket.write(_buffer.wrap(data.getBytes()), new Msg(), this);
}
}
然后我调用写方法2次
socket = AsynchronousSocketChannel.open();
socket.connect(new InetSocketAddress("localhost", port)).get();
writeHandler = new ClientWriteHandler(this);
writeHandler.write("hellooo server :)");
writeHandler.write("hellooo server again :)");
我尝试在ByteBuffer上使用clear()函数但没有效果。有什么建议吗?
答案 0 :(得分:2)
抛出WritePendingException不是因为缓冲区已满。抛出它是因为写入没有完成但是另一个开始写入。
答案 1 :(得分:0)
在第一次.write()调用中发送几个字节,并在第二次调用中向.write()发送几个字节。并且服务器全部接收它们。 TCP是面向字节的。如果您需要任何类似邮件的内容,则必须单独发送自己发送的邮件,例如:通过特殊的换行符或XML标签。
答案 2 :(得分:0)
我正在努力,我找到了解决方案及其工作,正如我想象的那样。
在ClientWrite处理程序内部我添加了数据列表并在try..catch中设置了write方法以检查write()是否已完成,如果写入仍在进行中,我将新字符串添加到数据列表中。写入方法完成后,我检查数据列表中的新消息并再次写入消息。
public class ClientWriteHandler implements CompletionHandler<Integer, ByteBuffer> {
private AsynchronousSocketChannel _socket;
private ClientSocket _clientHandler;
private ByteBuffer _buffer;
private List<String> datas;
private boolean finished;
public ClientWriteHandler(ClientSocket clientHandler) {
this._clientHandler = clientHandler;
_buffer = ByteBuffer.allocate(2048);
this._socket = this._clientHandler.getSocket();
finished = true;
datas = new ArrayList<>();
}
@Override
public void completed(Integer result, ByteBuffer attachment) {
System.out.println("client write complete " + result);
if(datas.size() > 0) {
this._socket.write(_buffer.wrap(datas.remove(0).getBytes()), _buffer, this);
}
else {
/////
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
System.out.println(exc.getMessage());
}
public void write(String data) {
try {
//finished = false;
this._socket.write(_buffer.wrap(data.getBytes()), _buffer, this);
}catch(WritePendingException ex) {
datas.add(data);
}
}
}
我也在附件中发送缓冲区。 阅读完成后,在ReadHandler里面我清除了ByteBuffer并再次调用了read()方法,所以接下来我读了新行,现在我不需要设置行分隔符。
public class ReadHandler implements CompletionHandler<Integer, ByteBuffer> {
private AsynchronousSocketChannel _socket;
private SocketHandler _socketHandler;
private ByteBuffer _buffer;
public ReadHandler(SocketHandler socketHandler) {
this._socketHandler = socketHandler;
_buffer = ByteBuffer.allocate(2048);
this._socket = this._socketHandler.getSocket();
this._socket.read(_buffer, _buffer, this);
}
@Override
public void completed(Integer result, ByteBuffer attachment) {
attachment.flip();
System.out.println("readdddd " + result);
String message = new String(attachment.array());
System.out.println("mess:" + message);
_buffer.clear();
this._socket.read(_buffer, _buffer, this);
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
System.out.println(exc.getMessage());
}
}
现在这个工作非常好,但是当我继续使用更复杂的东西时,我会检查这段代码的行为方式。你觉得这个解决方案怎么样呢?