TCP 长连接小尝试

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xyjincan/article/details/69357504

TCP 长连接小尝试,demo

本文学习了这两天看了不少tcp的使用细节,也看了不少有用的前辈经验,这里只是简单总结一下,有些奇怪的地方,BufferedReader,sendUrgentData。

  • 面临的问题是:写一个第三方程序信息接收服务器,协议上完全被动,等待连接接收消息。

服务端主要逻辑更新

堵塞的(BufferedReader)读取每条信息
        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader bufferedReader = null;

        try {
            // 获取一个输入流,接收服务端的信息
            inputStream = (InputStream) socket.getInputStream();
            // 包装成字符流,提高效率,如果有乱码问题
            inputStreamReader = new InputStreamReader(inputStream, "xxx");
            bufferedReader = new BufferedReader(inputStreamReader);

            char[] rcchar = new char[REVEIVEBUFFERSIZE];
            while (run) {//长连接读取远程信息,当连接断开会抛出异常
                int len = bufferedReader.read(rcchar);
                if(len==-1){//连接中断,,,           
                    throw new Exception("read socket err");
                }
                String crtstr = String.valueOf(rcchar, 0, len);
                System.out.println(new Date() + " : " + crtstr);
            }

        } catch (Exception e) {
            //与客户端连接中断
            try {
                bufferedReader.close();
                inputStreamReader.close();
                inputStream.close();
                socket.close();
            } catch (IOException e1) {
            }
        }

服务端主要逻辑

当serversocket接收到连接时,开启一个线程服务,非堵塞读取

class XXXConnect extends Thread {
    // 定义系统信息接收延迟:一秒
    private static final int receiveDelayMS = 1000;
    // 接收缓存8k,可能含多条数据,粘包等等。
    private static final int REVEIVEBUFFERSIZE = 1024 * 8;


    private Socket socket;
    private InputStream in;
    private boolean run = true;
    private byte[] receiveData = new byte[REVEIVEBUFFERSIZE];

    public XXXConnect(Socket socket) {

        this.socket = socket;
        try {
            in = socket.getInputStream();
        } catch (IOException e) {
            run = false;
            try {
                socket.close();
            } catch (IOException e1) {
            }
        }
    }

    @Override
    public void run() {
        try {
            while (run) {
                // 从远程读取数据时,远程连接断开将抛出异常
                //(Software caused connection abort: recv failed)
                int len = in.read(receiveData, 0, REVEIVEBUFFERSIZE);
                if (len != -1) {
                    System.out.println(new Date() 
                        + "receive:" + new String(receiveData, 0, len));
                }
                Thread.sleep(receiveDelayMS);
                // 测试:异常表明远程连接断开:Connection reset by peer: send
                // 发送任意数据:测试连接是否正常(心跳)
                socket.sendUrgentData(0xFF);
            }
            socket.close();
        } catch (Exception e) {

        }
    }

}

客户端发送测试

多次发送数据,然后服务端接收

            // 创建Socket对象
            Socket socket = new Socket("127.0.0.1", 11101);
            // 根据输入输出流和服务端连接
            OutputStream outputStream = (OutputStream) socket.getOutputStream();// 获取一个输出流,向服务端发送信息
            PrintWriter printWriter = new PrintWriter(outputStream);// 将输出流包装成打印流
            int ccc = 40;
            while (ccc > 0) {
                //Thread.sleep(1200);
                printWriter.print("服务端你ashfgehjsfbehjdsfbsjffj219278 27 3 好,我是Balla_兔子");
                printWriter.flush();
                ccc--;
            }

            Thread.sleep(10000);//等待那边服务器接收玩消息退出,
            System.out.println("bye server");
            printWriter.close();
            outputStream.close();
            socket.close();

这些写完后,发现了一个问题发送sendUrgentData 影响对方的报文接收。

            int ccc = 30;
            while (ccc > 0) {
                socket.sendUrgentData(0xFF);
                printWriter.print(ccc +  "服务端你ashfgehjsfbehjdsfbsjffj219278 27 3 好,我是Balla_兔子");
                printWriter.flush();
                //Thread.sleep(3000);
                ccc--;
            }
  1. windows下,如果A给B,发送一段报文,同时也发送多次socket.sendUrgentData(0xFF) ,B接收到的报文会缺失部分。
  2. 我又试了试linux下,如果A给B,发送一段报文,同时也发送多次socket.sendUrgentData(0xFF) ,A接收到的报文会混入未知字符。

    Microsoft Windows [版本 10.0.14393]
    java version “1.8.0_91”
    Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
    Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)

    Linux 4.10.6-200.fc25.x86_64 #1 SMP Mon Mar 27 14:06:23 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
    java version “1.8.0_111”
    Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
    Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)


展开阅读全文

ie8下tcp长连接带来的问题

11-10

背景: rn 公司一个产品是使用gwt的B/S架构应用,很多页面定时发送ajax请求和服务端交互数据刷新页面,交互的数据都放在body里,响应的状态信息通过http code而是通过响应的body体返回。rn 最近测试部报在ie8下,停留在有定时刷新的页面,不做任何操作有时会提示有未知错误,几率很低。开发发现前端有两个错误会连续报出,一个是提示没有需要的body,另一个是505 不支持的浏览器并发。用wireshark抓包,tcp内容如下,其中红色是请求:rn rn[color=#FF0000]POST /Console/console/alert_log HTTP/1.1rnAccept: */*rnAccept-Language: zh-cnrnReferer: http://192.168.1.151:8080/Console/Console.html#basicservice/homernContent-Type: text/xml; charset=UTF-8rnAccept-Encoding: gzip, deflaternUser-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322)rnHost: 192.168.1.151:8080rnContent-Length: 177rnConnection: Keep-AlivernCache-Control: no-cachernCookie: user_id=test; user_name=test; JSESSIONID=97D98075F4F4AACE3E2DC7882671F9D5rn[/color]rnHTTP/1.1 200 OKrnServer: Apache-Coyote/1.1rnContent-Type: application/xmlrnContent-Length: 170rnDate: Wed, 09 Nov 2011 09:28:19 GMTrnrn[color=#FF0000]POST /Console/console/alert_log HTTP/1.1rnAccept: */*rnAccept-Language: zh-cnrnReferer: http://192.168.1.151:8080/Console/Console.html#basicservice/homernContent-Type: text/xml; charset=UTF-8rnAccept-Encoding: gzip, deflaternUser-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322)rnHost: 172.16.201.151:8080rnContent-Length: 177rnConnection: Keep-AlivernCache-Control: no-cachernCookie: user_id=test; user_name=test; JSESSIONID=97D98075F4F4AACE3E2DC7882671F9D5rn[/color]rnHTTP/1.1 505 HTTP Version Not SupportedrnServer: Apache-Coyote/1.1rnDate: Wed, 09 Nov 2011 09:28:23 GMTrnConnection: closern[color=#FF0000]rnget_alert_log_list[/color]rn rn 查了一下http协议,http1.1支持建议一个长连接,也支持一个请求先发包含有expect:100-continue的header,如果响应是100再继续发body。rnrn 感觉出现问题的地方是在这个tcp连接里先只发了一个不带expect:100-continue的header,响应直接是找不到body,紧接着发了另一个header,由于使用前一个请求的tcp连接可能导致格式上有问题于是直接505并要关闭该连接。再关闭前接收到之前某个请求的body,tcp连接结束。问题似乎有2个,一个是第一个只发header的请求缺少expect:100-continue,另一个是第二个请求由于和第一个请求共用了同一个tcp连接产生了格式上的问题无法解析。rn 搜了一下,也没人说ie8有上面的问题,我也觉得ie不太可能对http1.1支持的如此不好。暂时在容器的配置文件里加了maxKeepAliveRequests="1" ,关掉tcp长连接,目前没有再复现以上的问题。rn 有没有可能是这样,ie用同一个tcp连接发送多个http请求时,先发了一个请求的header,多线程并发在发body前又用该tcp连接发了另一个请求的header,然后才发第一个请求的body,结果就混乱了?rn 论坛

没有更多推荐了,返回首页