BufferedInputStream隐藏的含义

最近RDP协议数据转发程序,有一个错误百思不得其解。通过多方尝试,才发现是BufferedInputStream搞得鬼。

转发程序从一个socket接收数据, 然后处理,通过另外一个socket发送出去。

为了提高效率,转发后面部分是采用nio的select来完成。但是转发前面部分,为了协商协议方便采用的blocking模式。在同步转异步的过程中,偶尔会出现协议错误的问题。

错误体现在一个packet解密出来是乱码。通过抓包,前后对比,才发现中间掉了一个packet。最后分析定位,是BufferedInputStream将socket接收的数据会缓存下来,在同步转异步的过程中,丢失BufferedInputStream中缓存的数据。

具体的模拟代码如下:

server:

public class Server {
public static void main(String[] args) throws IOException {
Server s = new Server();
s.test();
}


private ServerSocket serverSocket;
static int port = 8000;
private Selector selector;
private SocketChannel channel;


public void test() throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverSocket = serverChannel.socket();
serverSocket.bind(new InetSocketAddress(port));
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
for (;;) {
selector.select();
Iterator<SelectionKey> it = selector.selectedKeys()
.iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if (key.isValid())
handle0(key);
it.remove();
}
}
}


private void handle0(SelectionKey key) throws IOException {
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel channel = server.accept();
this.channel = channel;
DataInputStream dis = new DataInputStream(new BufferedInputStream(
channel.socket().getInputStream()));
// ByteBuffer dsts = ByteBuffer.allocate(2);
// int o = channel.read(dsts);
int length = 4;
byte[] packet = new byte[length];
dis.readFully(packet, 0, length);
System.out.println("received data:" +packet[length-1]);

channel.configureBlocking(false);
// ByteBuffer dsts1 = ByteBuffer.allocate(2);
// o = channel.read(dsts1);
// logger.info("received data:" + o + dsts1);
channel.register(selector, SelectionKey.OP_READ);
}
else if (key.isReadable()){
ByteBuffer dsts1 = ByteBuffer.allocate(2);
int o = channel.read(dsts1);
System.out.println("received data:" + o + dsts1.get());

}
}
}

client代码:

public class Client {
/**
* @param args
* @throws IOException 
* @throws InterruptedException 
*/
public static void main(String[] args) throws IOException, InterruptedException {
Socket s = new Socket();
SocketAddress endpoint = new InetSocketAddress("localhost",Server.port);
s.connect(endpoint);
byte[] ba = new byte[]{1,2,3,4,5,6,8,9,10,11,12};
s.getOutputStream().write(ba );
Thread.sleep(1000);
byte[] ba1 = new byte[]{13,14,15};
s.getOutputStream().write(ba1);
}
}


服务端就只能收到1,2,13,14,15,中间的其他数据就丢失了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值