socket编程时的发送与接收数据时的问题解析
socket 编程时的发送与接收数据时的问题
在编写一个测试方法时,需要用启动一个程序监听一个端口,测试发送的数据是事正常,但是总是出现两个问题,一是 Socked 总是在 OutputSteam.write () 方法之前被关闭,但是没有使用代码调用 Socket 的 Close 方法,另一个是在接收数据时,总是卡在 InputSteam.read () 方法处 (一般发生在前一个 Socket 在写数据时异常中断后再次有新 Socket 连接时),得不到数据,直到发送端关闭 Socket, 下面是代码
package com.zoro.example.subscribe.queue; import com.zoro.util.SendUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; /** * @author zoro * @version 1.0 */ public class TestSubscribeQueue { private static final Logger LOGGER = LoggerFactory.getLogger(TestSubscribeQueue.class); public static void main(String[] args) throws IOException { new Thread(new EventListener()).start(); } private static String test(InputStream is) { BufferedReader br = null; InputStreamReader isr = null; StringBuilder sb = new StringBuilder(); isr = new InputStreamReader(is); br = new BufferedReader(isr); String line = null; while (true) { try { line = br.readLine(); if (line == null || line.length() == 0) { break; } } catch (IOException e) { e.printStackTrace(); } sb.append(line); sb.append("\n"); line = null; LOGGER.debug("当前读取的数据:{}", sb.toString()); } return sb.toString(); } static class EventListener implements Runnable { private final ServerSocket ss; public EventListener() throws IOException { ss = new ServerSocket(8087); } @Override public void run() { while (true) { /* 这里得到的InputStream 不能在OutputStream返回数据之前关闭,因为InputStream关闭之后会导致Socket关闭,你说奇怪不奇怪,这样一来就不能正常返回数据了,报错说Socket已经关闭 */ try (Socket s = ss.accept(); InputStream is = s.getInputStream(); OutputStream os = s.getOutputStream()) { LOGGER.debug("等待请求..."); LOGGER.debug("新请求进入"); if (s.isClosed() || !s.isConnected() || s.isInputShutdown()) { continue; } // String result = SendUtil.resolveInputStream(is); String result = test(is); LOGGER.debug("收到请求:{}", result); StringBuilder response = new StringBuilder(); response.append("HTTP/1.1 200 OK\r\n"); response.append("Content-Type:text/html\r\n"); response.append("\r\n"); response.append("123252321"); LOGGER.debug("即将返回数据:{}", response.toString()); if (!s.isClosed()) { LOGGER.debug("正在返回数据"); os.write(response.toString().getBytes()); os.flush(); } } catch (IOException e) { e.printStackTrace(); } } } } }
分析原因
- 在第 76 行代码调用的方法中 调用的 InputStream.close () 方法,导致了 Socket 也跟着关闭了,不清楚是什么原因引起的,但是去掉 InputStream.close () 确实 OutputStream 可以向请求端改善数据了
- 在 OutputStream 的问题解决之后,InputStream 的问题也跟着没有了,因为我在测试时使用的是浏览器 http 发起的这个 Socket,所以我猜测是在第一次 Socket 异常中断后浏览器再次触发了重试;;
问题更新
两天后发现新问题: InputStream 在包装成 BufferedReader 整行读取时到 http 请求的最后一行还会继续向下一行读,但是发送端这时已经不发送数据了,造成服务端一直卡在这里等待
问题原因
BufferedReader.readLine () 方法在读取文件只,因为文件最后会是一个 - 1 ,所以可以知道在哪里结束,但网络请求最后没有这个 - 1 所以在读了最后一行后不知道请求数据已经没有更多了,造成一直阻塞
解决思路
http 请求(只讨论 get 与 post 两种方法),get 请求只有请求头,在读取到第一个空行时就可以结束,post 请求有请求体,可以根据请求头中 ContentLength 判断是否读取完
以上就是socket编程时的发送与接收数据时的问题解析的详细内容,更多关于socket发送接收数据的资料请关注脚本之家其它相关文章!
相关文章
SpringBoot+SpringSecurity+JWT实现系统认证与授权示例
本文主要介绍了SpringBoot+SpringSecurity+JWT实现系统认证与授权示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2022-08-08
最新评论