你这里是有问题的。首先你设置为异步的状态,那么client.write(sendBuffer);这句话是没法保证你调用一次就完成发送了,有可能只发送了一半或者几个字节就返回了。异步状态不会阻塞到发送完再返回的。最发的方法是写一个writeable方法,专门来响应可写事件。
private void writeable(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer data = (ByteBuffer) key.attachment(); //调用马上就会返回,没法保证会发完数据,有可能一个字节都没发送。
int len = socketChannel.write(writeBuffer); //返回-1就表示,另一端强制断掉了和你的连接
if (len == EOF_FLAG) {
throw new ConnectException("close channel.");
} if (!data.hasRemaining()) {//查看一下数据都读完了吗? //如果读完了,就表示都发送到Socket的发送缓冲区了,没我什么事了..结束将可写事件取消掉.
//这里如果不取消的话,你的CPU会被涨到100%,因为可写事件只要管道不阻塞一直可用.CPU就一直空转.
synchronized (ioSelectorsSyns.get(key.selector())) {
key.selector().wakeup();
key.interestOps(SelectionKey.OP_READ);
}
} //没有写完,OK,什么都不做,等待下次的可写事件.
}
简单就是你调用了发送方法,并不保证能发送完了.至于读也要用相同的方法,而且读消息你要自己知道什么时候表示读完了.
这就要你自己来设置消息格式了,比如读到消息头后跟4个字节的消息长度,那么再读指定字节就可以了.
private void writeable(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer data = (ByteBuffer) key.attachment(); //调用马上就会返回,没法保证会发完数据,有可能一个字节都没发送。
int len = socketChannel.write(writeBuffer); //返回-1就表示,另一端强制断掉了和你的连接
if (len == EOF_FLAG) {
throw new ConnectException("close channel.");
} if (!data.hasRemaining()) {//查看一下数据都读完了吗? //如果读完了,就表示都发送到Socket的发送缓冲区了,没我什么事了..结束将可写事件取消掉.
//这里如果不取消的话,你的CPU会被涨到100%,因为可写事件只要管道不阻塞一直可用.CPU就一直空转.
synchronized (ioSelectorsSyns.get(key.selector())) {
key.selector().wakeup();
key.interestOps(SelectionKey.OP_READ);
}
} //没有写完,OK,什么都不做,等待下次的可写事件.
}
简单就是你调用了发送方法,并不保证能发送完了.至于读也要用相同的方法,而且读消息你要自己知道什么时候表示读完了.
这就要你自己来设置消息格式了,比如读到消息头后跟4个字节的消息长度,那么再读指定字节就可以了.
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货