2

我有几个问题-

1. 我有两台电脑通过socket连接。程序执行时

outputStream.writeInt(value);
outputStream.flush();

实际发生了什么?程序是否等到另一台计算机读取整数值?

2.如何清空outputStreamor inputStream?意思是,当清空outputStreamor时inputStream,写入该流的任何内容都会被删除。(请不要建议通过关闭连接来做到这一点!)我试图用inputStream这种方式清空 -

byte[] eatup=new byte[20*1024];
int available=0;
while(true)
{
    available=serverInputStream.available();
    if(available==0)
       break;
    serverInputStream.read(eatup,0,available);
}
eatup=null;

String fileName=(String)serverInputStream.readObject();

程序不应处理该行,因为outputStream. 但是我的程序无论如何都会执行它并引发java.io.OptionalDataException错误。

注意:我正在开发一个客户端-服务器文件传输项目。客户端将文件发送到服务器。第二个代码用于服务器终端。如果在服务器端按下“取消按钮”,那么它将停止从客户端读取字节并向客户端serverInputStream发送信号(我使用int -1)。当客户端收到此信号时,它会停止向服务器发送数据,但我注意到它serverInputStream不是空的。所以我需要清空它serverInputStream,以便客户端计算机能够再次发送服务器计算机文件(这就是为什么我无法从read方法管理锁定)

4

1 回答 1

2

1 - 否。在 flush() 上,数据将被写入操作系统内核,操作系统内核可能会立即将其交给网卡驱动程序,然后由网卡驱动程序将其发送到接收端。简而言之,发送就是一劳永逸。

2 - 正如 Jeffrey 评论的那样,available() 对于这种操作是不可靠的。如果做阻塞 IO,那么正如他建议的那样,你应该只是投机地使用 read() 。但是应该说,您确实需要在原始流之上定义一个协议,即使它只是使用 DataInput/DataOutputStream。使用原始写入/读取时,黄金法则是一次写入!= 一次读取。例如,如果您要在一侧写入 10 个字节,而在另一侧有一个读取循环,则无法保证一次读取将读取所有 10 个字节。它可以作为块的任何组合被“读取”。类似地,两次 10 字节的写入可能会在接收端显示为一次 20 字节的读取。换句话说,除非您在原始字节之上创建更高级别的协议来执行数据包,否则没有“数据包”的概念。

如果您确实需要做比基本应用程序更复杂的事情,我强烈建议您研究一些已经解决了网络 IO 的许多棘手问题的更高级别的库。我会推荐用于生产应用程序的Netty 。然而,从简单的 IO 流到 Netty 的更多基于事件的系统的理解是一个很大的飞跃。中间的某个地方可能还有其他库。

于 2012-09-02T18:11:03.073 回答