最近在做一个项目,要用到socket传输数据,而且考虑到跨平台,不得不使用字节传输,结果总是遇到一些问题。

关于这个问题的那块代码非常简单,就是一个发一个收。为了博客书写方便,我在这只粘贴核心代码。 服务端的代码如下

1
2
3
4
5
6
ServerSocket ss=new ServerSocket(8979);
while (true){
    Socket client=ss.accept();
    OutputStream os=client.getOutputStream();
    os.write("hello world".getBytes());
}

客户端的代码是这样的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Socket s=new Socket("127.0.0.1",8979);
InputStream in=s.getInputStream();
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
int ch;
while ((ch = in.read()) != -1) {
    System.out.println("-------------------->"+ch);
    byteStream.write(ch);
}
byte[] bytes = byteStream.toByteArray();
System.out.println(new String(bytes));

正常情况下应该是将读取到的每一个ascii都打印出来后输出字符串,结果总是有点不对。 最后卡在in.read()这了,一直没有接收到新的。证明in不知道流结束了,还在这死等着,然后就这样了。 后来查看文档,有个available方法,来测试了下。

1
byte[] recv=new byte[in.available()];

结果很无奈的发现有时候网太差了in.available()值会是0,有时候传的内容太多了会分块传输,导致创建的接受区太小。 然后在网上看到一个帖子,收到数据后稍微停一下在写入,答题是这样的代码

1
2
3
4
byte[] recv=new byte[1024];//预先分配1024个字节
while(in.available()<=0);
Thread.sleep(200);
in.read(recv);

发现相对来说接收数据不会出错了,但是万一数据量过大就不好了。 后来想了下,导致收不全的主要原因就是由于in不知道停没停止,如果确认停止了就不收了就好了。 server端这么改下。

1
os.close();

成功发送,接收端也正常。但是问题又来了,如果我想一直保持着这个连接怎么办呢? 想了想,只能通过特定字符串来停止接收了。 实际上我这次遇到的问题说复杂也并不复杂,平时socket也不太经常直接操作字节流,只是由于这次要跟硬件打交道,不得不考虑各种原因了。 如果有朋友遇到的想死的问题,希望能够有帮助。 如果你有更好的想法,欢迎提出来啊!