`

Java ServerSocket和Socket编程的经验和教训

阅读更多

 

Java的ServerSocket和Socket是开发网络应用程序的基础。ServerSocket和Socket类是java自带的,(java.net.ServerSocket和java.net.Socket)。

 

 

我不打算再重复叙述Java文档中关于这两个类的描述,只是想把使用者两个类中的一些经验写下来。

 

ServerSocket 的队列长度

 

ServerSocket最常见的是accept方法,接受一个客户端连接请求,这样,客户端和服务器端都持有一个Socket可以互相通信。在多并发程序中,尤其是基于短连接客户端,服务器端会非常频繁的accept,那么瓶颈可能就会出现在这里。

 

在ServerSocket的accept时,如果还没有accept成功,过来了其他的连接请求,会放在ServerSocket的队列中,处理完当前的连接请求,就会处理队列中的,这样,对外的表现就是服务器端“挂住”了这个客户端连接,因为accept也很快,所以这个客户端连接也将很快得到处理。

 

这样看来,对服务器系统来讲,ServerSocket的队列长度就非常关键,而我们在编程时,可以显示的指定这个长度。

 

ServerSocket的构造方法:

 

public ServerSocket(int port,
                    int backlog)

 

其中的backlog就是指的这个队列的长度。当然,最常用的构造方法:

 

 

public ServerSocket(int port)

 

在文档中说明如下:

 

输入连接指示(对连接的请求)的最大队列长度被设置为 50。如果队列满时收到连接指示,则拒绝该连接。

 

也就是说,这种构造方法,实际上对backlog赋了默认值50。

一般情况下,也够用了。但是这里要提醒一句就是,轻易不要使用系统默认值,因为不同版本的java,默认值可能不同;而不同厂商的java,默认值更是有可能不同(例如Oracle和IBM),自己控制更稳妥。

 

Socket的TCP_NODELAY

 

 socket在创建的时候,默认都是使用Nagle算法的,这会导致交互速度严重下降,Nagle算法是为了解决这一的问题:例如在典型情况下,传送一个只拥有1个字节有效数据的数据包,却要发费40个字节长包头(即ip头20字节+tcp头20字节)的额外开销,这造成有效载荷(payload)利用率极其低下。

 

Nagle算法的改进是:Nagle算法的改进在于:如果发送端欲多次发送包含少量字符的数据包,将数据都缓存起来而不立即发送,直到满足一定的条件,例如积攒到了一定数量的数据(比如缓存的字 符数据已经达到数据包报文段的最大长度)等多种情况才将其组成一个较大的数据包发送出去。

 

可见这种算法在对延迟要求非常高的系统中,会造成等待和延迟。所以我们视系统的类型,根据需要,在创建Socket时,加上TCP_NODELAY属性。

 

public void setTcpNoDelay(boolean on) throws SocketException

 

 

 当然,对特定的系统,会增加网络的负担。

 

再有两条,一是一定要设置TCP_TIMEOUT,再有就是So_Lingle,这两条对高并发系统至关重要。TimeOut关乎稳定性和健壮性,尤其是基于长连接的系统;So_Lingle关系到“半关闭”状态的连接,因为操作系统都有“最大打开文件数”的限制,所以对系统的并发性能有很大的作用。

 

这两条,我将在下一篇文章里详细描述。

 

需要指出的是,Java的Socket都是调用的操作系统的本地实现,因此,Java Socket的参数的作用和意义,还要取决于操作系统TCP协议栈的实现。

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics