JAVA实现SOCKET短连接

来源:互联网 发布:软件设计师难不难 编辑:程序博客网 时间:2024/05/21 13:50
 

先简单说概念: 1、socket就是TCP/IP实现的套接字,就是应用层调用下层服务的接口。

2、短连接指的是连接建立后,双方进行数据交互(通常是一个数据包,也可以是多个),交互完毕后立即关闭连接的TCP/IP实现方式就是常说的短连接,最常见的短连接例子就是HTTP协议。

3、长连接则指的是双方交互完毕后,不关闭连接,而让连接一直空闲着等待下一次交互,这样在一次交互前就免去了再重新建立连接的消耗,本机测试一次socket连接需要耗时23毫秒。

优点就是性能好。缺点有二,一是实现方式比较复杂,需要单独用线程收,发倒是无所谓;二是需要增加链路检测的机制,由于连接在空闲时双方都无法确认对端是否出现异常退出,因为根据TCP/IP,如果连接的一方正常退出,对端都会收到一个信号,而当一方异常退出时,对端是无法收到信号的,这时就会出现connection reset、connection reset by peer和broken pipe异常。

接下来说说JAVA如何实现短连接。一、先来看发送到方法,这个比较简单。直接获得socket的OutputStream流,然后用write方法,flush方法即可。这里要说明的就是,之前认为使用flush方法在底层就是一个TCP包,其实不然,上层何时按照上面策略封装TCP包上层根本无法知道,经过测试可知,下层封装的TCP包大小与flush无必然联系。这里有个参数可以设置,就是sock.setTcpNoDelay(true),如果设置为true,则对于缓冲区不进行拼接,立即发送。这里涉及nagle算法,用于解决小封包问题,感兴趣的朋友可以自己baidu。

二、接收时有多种方式。常用的两个类是InputStream和BufferedInputStream,下面简单说一下我看JDK的理解。这里的两个类都是阻塞的读取数据。

1、InputStream的read(byte[] b,offset,len)方法是直接从流中一个一个read()出来扔到b中的。此方法阻塞到某个事件发生,例如异常、超时、正常收到一个封包。要理解阻塞,就一定要理解好这里的事件退出,异常就不用解释了,比如对方异常关闭连接了;超时就是如果你手工设置了超时时间,当超时时间到时还没能从连接中读到任何数据,此时抛出一个Read Time Out异常;最后一个最难理解,就是从连接中读到一个数据包,此时不管数据包大小是否达到len大小,此方法都可以正常返回,当封包大于len时,只读取len长的数据,这也是它与BufferedInputStream的区别,此时方法结束。

2、BufferedInputStream的read(byte[] b);直接调用了父类InputStream的read(byte[] b,offset,len)方法,不推荐使用,因为其实并没有用到Buffer功能;

3、BufferedInputStream的read(byte[] b,offset,len);覆写了父类的方法,方法中用到了read1(byte[] b,offset,len)方法,read1方法中,如果缓冲数组中有数据则直接返回数据,如果缓冲队列中无数据则直接调用InputStream的read(byte[] b,offset,len)方法。可以得到一下推论,如果我调用了read(byte[] b,offset,len)方法,则将第一个封包所有内容全部缓冲到Buffer中,如果第一个封包大于Buffer,则先读取buffer大小的长度到buffer中,如果第一个封包小于Buffer,则全部读取到Buffer中。调用read(byte[] b,offset,len)方法时,如果len小于buffer大小则不用等待IO,直接从buffer中读取,免去IO等待。这里推荐用此方法。

4、BufferedInputStream 的available()方法返回当前不阻塞就能读到的数据。

原创粉丝点击