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

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

在编写一个测试方法时,须要用启动一个程序监听一个端口,测试发送的数据是事正常,可是老是出现两个问题,一是Socked老是在OutputSteam.write()方法以前被关闭,可是没有使用代码调用Socket的Close方法,另外一个是在接收数据时,老是卡在InputSteam.read()方法处(通常发生在前一个Socket在写数据时异常中断后再次有新Socket链接时),得不到数据,直到发送端关闭Socket,下面是代码html

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();
                }
            }

        }
    }
}

分析缘由

  1. 在第76行代码调用的方法中 调用的 InputStream.close()方法,致使了Socket也跟着关闭了,不清楚是什么缘由引发的,可是去掉InputStream.close()确实OutputStream能够向请求端改善数据了
  2. 在OutputStream的问题解决以后,InputStream的问题也跟着没有了,由于我在测试时使用的是浏览器http发起的这个Socket,因此我猜想是在第一次Socket异常中断后浏览器再次触发了重试;;

问题更新

两天后发现新问题: InputStream在包装成BufferedReader整行读取时到http请求的最后一行还会继续向下一行读,可是发送端这时已经不发送数据了,形成服务端一直卡在这里等待java

问题缘由

BufferedReader.readLine()方法在读取文件只,由于文件最后会是一个-1 ,因此能够知道在哪里结束,但网络请求最后没有这个-1 因此在读了最后一行后不知道请求数据已经没有更多了,形成一直阻塞编程

解决思路

http 请求(只讨论get 与post 两种方法),get 请求只有请求头,在读取到第一个空行时就能够结束,post请求有请求体,能够根据请求头中ContentLength 判断是否读取完浏览器

相关文章
相关标签/搜索