socket编程时的发送与接收数据时的问题解析

 更新时间:2023年06月02日 09:42:11   作者:Mzoro  
这篇文章主要为大家介绍了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实现系统认证与授权示例

    本文主要介绍了SpringBoot+SpringSecurity+JWT实现系统认证与授权示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • SpringBoot超详细讲解事务管理

    SpringBoot超详细讲解事务管理

    事务的作用就是为了保证用户的每一个操作都是可靠的,事务中的每一步操作都必须成功执行,只要有发生异常就 回退到事务开始未进行操作的状态。事务管理是Spring框架中最为常用的功能之一,我们在使用Spring Boot开发应用时,大部分情况下也都需要使用事务
    2022-08-08
  • Maven下 mybatis-generator使用

    Maven下 mybatis-generator使用

    这篇文章主要介绍了Maven下 mybatis-generator使用 ,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-09-09
  • SpringBoot启动时自动执行代码的几种实现方式

    SpringBoot启动时自动执行代码的几种实现方式

    这篇文章主要给大家介绍了关于SpringBoot启动时自动执行代码的几种实现方式,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-02-02
  • Spring中的PathVariable注释解析

    Spring中的PathVariable注释解析

    这篇文章主要介绍了Spring中的PathVariable注释用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • JAVA Integer类型自加实例详解

    JAVA Integer类型自加实例详解

    这篇文章主要介绍了JAVA Integer类型自加实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • JavaWeb学习笔记之Filter和Listener

    JavaWeb学习笔记之Filter和Listener

    这篇文章主要给大家介绍了关于JavaWeb学习笔记之Filter和Listener的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Spring Boot 项目启动自动执行方法的两种实现方式

    Spring Boot 项目启动自动执行方法的两种实现方式

    这篇文章主要介绍了Spring Boot 项目启动自动执行方法的两种实现方式,帮助大家更好的理解和学习使用Spring Boot框架,感兴趣的朋友可以了解下
    2021-05-05
  • Java之单链表问题解决案例讲解

    Java之单链表问题解决案例讲解

    这篇文章主要介绍了Java之单链表问题解决案例讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • 模仿Spring手写一个简易的IOC

    模仿Spring手写一个简易的IOC

    这篇文章主要介绍了模仿Spring手写一个简易的IOC,帮助大家更好的理解和学习spring框架,感兴趣的朋友可以了解下
    2020-11-11

最新评论