当server和client端同时通信时,看Server.java 的while循环里的语句,约定客户端传输的时候结束了在末尾加一个eof作为标识,推出循环。原文作者是这么描述他的作用的。
“在上述代码中首先我们从输入流中读取客户端发送过来的数据,接下来我们再往输出流里面写入数据给客户端,接下来关闭对应的资源文件。而实际上上述代码可能并不会按照我们预先设想的方式运行,因为从输入流中读取数据是一个阻塞式操作,在上述的while循环中当读到数据的时候就会执行循环体,否则就会阻塞,这样后面的写操作就永远都执行不了了。除非客户端对应的Socket关闭了阻塞才会停止,while循环也会跳出。针对这种可能永远无法执行下去的情况的解决方法是while循环需要在里面有条件的跳出来,纵观上述代码,在不断变化的也只有取到的长度len和读到的数据了,len已经是不能用的了,唯一能用的就是读到的数据了。针对这种情况,通常我们都会约定一个结束标记,当客户端发送过来的数据包含某个结束标记时就说明当前的数据已经发送完毕了,这个时候我们就可以进行循环的跳出了”
我不理解的是,从输入流中读取是一个阻塞操作,也就是输入流没发数据,他就一直在那里等,不往下执行。但是这个client.java明明write了一个hello,world字符串给他了啊。按理说,他读完了,自然会跳出while,为什么len = -1 的条件不会退出,而设一个eof,手动break???
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在描述的场景中,客户端向服务器发送数据,并且约定在数据末尾添加一个特殊的结束标记(EOF,End Of File),以指示数据传输的结束。这里有几个关键点需要理解:
阻塞式读取:当服务器端使用InputStream.read()
方法从输入流读取数据时,如果没有数据可读,这个方法会阻塞,即暂停执行并等待数据到来。这意味着如果客户端没有发送足够的数据或者没有明确表示数据传输结束(通过EOF或其他方式),服务器端的程序就会一直卡在这个读取操作上,不会继续执行后续代码,包括写入响应到输出流的操作。
len = -1的条件:在Java中,当尝试从一个已经关闭或者到达文件末尾的输入流中读取数据时,read()
方法会返回-1。这通常用于检测文件或流是否已结束。但是,在网络编程中,特别是TCP套接字,没有自然的“文件末尾”概念,除非一方显式关闭连接,否则read()
调用不会因为数据暂时停止发送而返回-1。因此,仅依赖于len = -1
来判断数据传输完成在实际网络通信中是不可行的,特别是在希望保持连接开放以进行更多交互的情况下。
EOF作为结束标记:为了在数据传输过程中明确告知对方数据何时结束,引入了一个约定俗成的做法,即在数据末尾附加一个特殊标记,比如字符串"EOF"。这样,服务器端在读取数据时,除了处理实际的数据内容,还会检查是否有这个特殊标记出现。一旦发现EOF,即使没有达到len = -1
的情况,也会主动通过break
语句跳出循环,从而能够继续执行后续的逻辑,如发送响应给客户端。
综上所述,设置EOF作为手动退出循环的条件,是为了克服单纯基于数据流自然结束(如len = -1
)在TCP通信中的局限性,确保即使在连接保持打开状态下也能准确识别单次消息的边界,从而使双方能够有效地进行多次消息交换。