(转自http://www.cnblogs.com/ggjucheng/archive/2012/01/06/2314679.html)

( http://docs.oracle.com/javase/tutorial/java/package/summary-package.html)

Java Socket的api可能很多人会用,但是Java Socket的参数可能很多人都不知道用来干嘛的,甚至都不知道有这些参数。

backlog

用于ServerSocket,配置ServerSocket的最大客户端等待队列。等待队列的意思,先看下面代码

public class Main {
public static void main(String[] args) throws Exception {
int port = 8999;
int backlog = 2;
ServerSocket serverSocket = new ServerSocket(port, backlog);
Socket clientSock = serverSocket.accept();
System.out.println("revcive from " + clientSock.getPort());
while (true) {
byte buf[] = new byte[1024];
int len = clientSock.getInputStream().read(buf);
System.out.println(new String(buf, 0, len));
}
}
}

这段测试代码在第一次处理一个客户端时,就不会处理第二个客户端,所以除了第一个客户端,其他客户端就是等待队列了。所以这个服务器最多可以同时连接3个客户端,其中2个等待队列。大家可以telnet localhost 8999测试下。

这个参数设置为-1表示无限制,默认是50个最大等待队列,如果设置无限制,那么你要小心了,如果你服务器无法处理那么多连接,那么当很多客户端连到你的服务器时,每一个TCP连接都会占用服务器的内存,最后会让服务器崩溃的。

另外,就算你设置了backlog为10,如果你的代码中是一直Socket clientSock = serverSocket.accept(),假设我们的机器最多可以同时处理100个请求,总共有100个线程在运行,然后你把在100个线程的线程池 处理clientSock,不能处理的clientSock就排队,最后clientSock越来越多,也意味着TCP连接越来越多,也意味着我们的服务 器的内存使用越来越高(客户端连接进程,肯定会发送数据过来,数据会保存到服务器端的TCP接收缓存区),最后服务器就宕机了。所以如果你不能处理那么多 请求,请不要循环无限制地调用serverSocket.accept(),否则backlog也无法生效。如果真的请求过多,只会让你的服务器宕机(相 信很多人都是这么写,要注意点)

TcpNoDelay

禁用纳格算法,将数据立即发送出去。纳格算法是以减少封包传送量来增进TCP/IP网络的效能,当我们调用下面代码,如:

Socket socket = new Socket();  
socket.connect(new InetSocketAddress(host, 8000));
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
String head = "hello ";
String body = "world\r\n";
out.write(head.getBytes());
out.write(body.getBytes());

我们发送了hello,当hello没有收到ack确认(TCP是可靠连接,发送的每一个数据都要收到对方的一个ack确认,否则就要重发)的时 候,根据纳格算法,world不会立马发送,会等待,要么等到ack确认(最多等100ms对方会发过来的),要么等到TCP缓冲区内 容>=MSS,很明显这里没有机会,我们写了world后再也没有写数据了,所以只能等到hello的ack我们才会发送world,除非我们禁用 纳格算法,数据就会立即发送了。

纳格算法参考:http://zh.wikipedia.org/wiki/%E7%B4%8D%E6%A0%BC%E7%AE%97%E6%B3%95

另外有一篇讲解纳格算法和delay ack的文章(挺不错的):http://blog.csdn.net/frankggyy/article/details/6624401

SoLinger

当我们调用socket.close()返回时,socket已经write的数据未必已经发送到对方了,例如

Socket socket = new Socket();  
socket.connect(new InetSocketAddress(host, 8000));
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
String head = "hello ";
String body = "world\r\n";
out.write(head.getBytes());
out.write(body.getBytes());
socket.close();

这里调用了socket.close()返回时,hello和world未必已经成功发送到对方了,如果我们设置了linger而不小于0,如:

bool on = true;
int linger = 100;
....
socket.setSoLinger(boolean on, int linger)
......
socket.close();

那么close会等到发送的数据已经确认了才返回。但是如果对方宕机,超时,那么会根据linger设定的时间返回。

UrgentData和OOBInline

TCP的紧急指针,一般都不建议使用,而且不同的TCP/IP实现,也不同,一般说如果你有紧急数据宁愿再建立一个新的TCP/IP连接发送数据,让对方紧急处理。

所以这两个参数,你们可以忽略吧,想知道更多的,自己查下资料。

SoTimeout

设置socket调用InputStream读数据的超时时间,以毫秒为单位,如果超过这个时候,会抛出java.net.SocketTimeoutException。

KeepAlive

keepalive不是说TCP的常连接,当我们作为服务端,一个客户端连接上来,如果设置了keeplive为true,当对方没有发送任何数据
过来,超过一个时间(看系统内核参数配置),那么我们这边会发送一个ack探测包发到对方,探测双方的TCP/IP连接是否有效(对方可能断点,断网),
在Linux好像这个时间是75秒。如果不设置,那么客户端宕机时,服务器永远也不知道客户端宕机了,仍然保存这个失效的连接。

SendBufferSize和ReceiveBufferSize

TCP发送缓存区和接收缓存区,默认是8192,一般情况下足够了,而且就算你增加了发送缓存区,对方没有增加它对应的接收缓冲,那么在TCP三握
手时,最后确定的最大发送窗口还是双方最小的那个缓冲区,就算你无视,发了更多的数据,那么多出来的数据也会被丢弃。除非双方都协商好。

以上的参数都是比较重要的Java Socket参数了,其他就不另外说明了。

最新文章

  1. 【Alpha阶段】第三次Scrum例会
  2. jQuery 学习之路(2):选择器与过滤器
  3. LayoutInflater(二)
  4. 批处理:循环解压不同文件夹下的zip压缩包
  5. 修改虚拟机linux硬盘的大小
  6. 新浪微博。。openapi 分享 图画+ 写作
  7. nginx(1)
  8. Ubuntu下安装并配置VS Code编译C++
  9. [笔记]使用Keepalived实现Nginx主从热备
  10. 洛谷P3178 [HAOI2015]树上操作
  11. 增益 Gain 分贝 dB
  12. Spring Boot 揭秘与实战(七) 实用技术篇 - FreeMarker 模板引擎
  13. linux修改文件所有者和文件所在组 【转载】
  14. WPF禁止拖拽窗口到边缘自动最大化
  15. PLSQL Developer概念学习系列之如何正确登录连接上Oracle(图文详解)
  16. centos 安装glide工具(golang)笔记
  17. 在线sass编译器
  18. Java 运行时数据区域
  19. cxf 生成客户端代码调用服务
  20. Linux 各文件系统配置

热门文章

  1. VirtualBox如何扩展虚拟机Ubuntu的硬盘容量?
  2. WAL 【转】
  3. 关于struts.xml配置文件的说明
  4. java heap space解决方法和JVM参数设置
  5. xshell分隔符
  6. mysql安装笔记-rpm
  7. linux、centos下查看系统版本、bios版本,内存信息等
  8. np.random.random()系列函数
  9. 安装Ubuntu后一些准备
  10. K组翻转链表 · Reverse Nodes in k-Group