在Java的Socket中,主要包含了以下可设置的TCP参数。

属性

说明

默认值

SO_TIMEOUT

对ServerSocket来说表示等待连接的最长空等待时间; 对Socket来说表示读数据最长空等待时间。

0

TCP_NODELAY

是否一有数据就马上发送。

false

SO_LINGER

优雅地关闭套接字,或者立刻关闭。

-1

SO_SNDBUF

发送数据的缓冲区大小。

8K

SO_RCVBUF

接收数据的缓冲区大小。

8K

SO_KEEPALIVE

是否启用心跳机制。

false

SO_REUSEADDR

是否地址重用。

false

BACKLOG

服务端处理线程全忙后,允许多少个新请求进入等待。

50

1.1 BACKLOG

BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。

ServerSocket serverSocket = new ServerSocket(8080, 100);

1.2 TCP_NODELAY

在TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认。为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。这里就涉及到一个名为Nagle的算法,该算法的目的就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。

TCP_NODELAY选项,就是用于启用或关于Nagle算法。如果要求高实时性,有数据发送时就马上发送,就将该选项设置为true关闭Nagle算法;如果要减少发送次数减少网络交互,就设置为false等累积一定大小后再发送。默认为false。

Socket中操作该属性的方法如下:

void setTcpNoDelay(boolean on)

启用/禁用 TCP_NODELAY(启用/禁用 Nagle 算法)。

boolean getTcpNoDelay()

测试是否启用 TCP_NODELAY。

关于Nagle算法介绍,请参考附录部分。

1.3 SO_TIMEOUT

对于服务端套接字ServerSocket来说,SO_TIMEOUT表示服务端accept方法空等待客户端连接的最长时间;对于客户端套接字Socket来说,SO_TIMEOUT表示输入流读取数据read方法的最长等待时间。一旦超过设置的SO_TIMEOUT,程度将抛出超时异常。

ServerSocket/Socket中操作该属性的方法如下:

int getSoTimeout()

返回 SO_TIMEOUT 的设置。

void setSoTimeout(int timeout)

启用/禁用带有指定超时值的 SO_TIMEOUT,以毫秒为单位。

使用示例:

ServerSocket serverSocket = new ServerSocket(8080);

serverSocket.setSoTimeout(30000);

Socket clientSocket = serverSocket.accept();

clientSocket.setSoTimeout(20000);

1.4 SO_LINGER

当调用closesocket关闭套接字时,SO_LINGER将决定系统如何处理残存在套接字发送队列中的数据。处理方式无非两种:丢弃或者将数据继续发送至对端,优雅关闭连接。事实上,SO_LINGER并不被推荐使用,大多数情况下我们推荐使用默认的关闭方式(即下方表格中的第一种情况)。

下方代码段显示linger结构语法,表格为不同参数情况下的套接字行为。

typedef struct linger {

u_short l_onoff;    //开关,零或者非零

u_short l_linger;   //优雅关闭最长时限

} linger;

各字段与对应行为如下表所示。

l_onoff

l_linger

closesocket行为

发送队列

底层行为

忽略

立即返回。

保持直至发送完成。

系统接管套接字并保证将数据发送至对端。

非零

立即返回。

立即放弃。

直接发送RST包,自身立即复位,不用经过2MSL状态。对端收到复位错误号。

非零

非零

阻塞直到l_linger时间超时或数据发送完成。(套接字必须设置为阻塞)

在超时时间段内保持尝试发送,若超时则立即放弃。

超时则同第二种情况,若发送完成则皆大欢喜。

Socket中操作该属性的方法如下:

void setSoLinger(boolean on, int linger)

启用/禁用具有指定逗留时间(以秒为单位)的SO_LINGER。 Linger最大取值为65535。

int getSoLinger()

返回 SO_LINGER 的设置。默认值为-1。

由于getSoLinger()方法返回的-1没有太多意思,我们查看到Java的默认实现PlainSocketImpl.c文件中,赋值操作代码片段如下所示。

/*

* Class:     java_net_PlainSocketImpl

* Method:    socketSetOption

* Signature: (IZLjava/lang/Object;)V

*/

JNIEXPORT void JNICALL

Java_java_net_PlainSocketImpl_socketSetOption(JNIEnv *env, jobject this,

jint cmd, jboolean on,

jobject value) {

switch (cmd) {

case java_net_SocketOptions_SO_SNDBUF :

case java_net_SocketOptions_SO_RCVBUF :

case java_net_SocketOptions_SO_LINGER :

case java_net_SocketOptions_IP_TOS :

{

if (cmd == java_net_SocketOptions_SO_LINGER) {

if (on) {

                        optval.ling.l_onoff = 1;

                        optval.ling.l_linger = (*env)->GetIntField(env, value, fid);

                    } else {

                        optval.ling.l_onoff = 0;

                        optval.ling.l_linger = 0;

                    }

optlen = sizeof(optval.ling);

} else {

optval.i = (*env)->GetIntField(env, value, fid);

optlen = sizeof(optval.i);

}

break;

}

/* Boolean -> int */

default :

optval.i = (on ? 1 : 0);

optlen = sizeof(optval.i);

}

}

从蓝色字体部分代码可以看出,只要赋值为false,则底层linger结构中的l_onoff和l_linger的值均为0,符合表中的第一种情况。

1.5 SO_SNDBUF

发送缓冲区的大小设置,默认为8K。

Socket中操作该属性的方法如下:

void setSendBufferSize(int size)

将此 Socket 的 SO_SNDBUF 选项设置为指定的值。

int getSendBufferSize()

获取此 Socket 的 SO_SNDBUF 选项的值,该值是平台在 Socket 上输出时使用的缓冲区大小。

1.6 SO_RCVBUF

接收缓冲区大小设置,默认为8K。该属性既可以在ServerSocket实例中设置,也可以在Socket实例中设置。

ServerSocket/Socket中操作该属性的方法如下:

void setReceiveBufferSize(int size)

将此 Socket 的 SO_RCVBUF 选项设置为指定的值。

int getReceiveBufferSize()

获取此 Socket 的 SO_RCVBUF 选项的值,该值是平台在 Socket 上输入时使用的缓冲区大小。

1.7 SO_KEEPALIVE

套接字本身是有一套心跳保活机制的,不过默认的设置并不像我们一厢情愿的那样有效。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。

很多人认为两个小时的时间设置得很不合理。为什么不设置成为10分钟,或者更短的时间?(可以通过SO_KEEPALIVE选项设置。)但是这样做其实并不被推荐。实际上这套机制只是操作系统底层使用的一个被动机制,原理上不应该被上层应用层使用。当系统关闭一个由KEEPALIVE机制检查出来的死连接时,是不会主动通知上层应用的,只有在调用相应的IO操作在返回值中检查出来。

在《UNIX网络编程第1卷》中也有详细的阐述:

SO_KEEPALIVE 保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方 发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况:对方接收一切正常:以期望的ACK响应。2小时后,TCP将发出另一个探测分节。对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接口本身则被关闭。对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟 15秒后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。

因此,忘记SO_KEEPALIVE,在应用层自己写一套保活机制比较靠谱。

Socket中操作该属性的方法如下:

boolean getKeepAlive()

测试是否启用 SO_KEEPALIVE。

void setKeepAlive(boolean on)

启用/禁用 SO_KEEPALIVE。

1.8 SO_REUSEADDR

是否重用处于TIME_WAIT状态的地址。默认为false。

Socket中操作该属性的方法如下:

boolean getReuseAddress()

测试是否启用 SO_REUSEADDR。

void setReuseAddress(boolean on)

启用/禁用 SO_REUSEADDR 套接字选项。

Java套接字Socket编程--TCP参数的更多相关文章

  1. [置顶] Java套接字Socket编程

    1)概念 网络编程基本模型就客户端到服务器的模型,也就是我们常见的C/S模型.简单的说就是两个进程间相互通信的过程.即通信双方一方作为服务器等待客户端提出请求并给以回应,另一方作为客户端向服务器提出请 ...

  2. Java套接字socket编程笔记

    相对于C和C++来说,Java中的socket编程是比较简单的,比较多的细节都已经被封装好了,每次创建socket连接只需要知道地址和端口即可. 在了解socket编程之前,我们先来了解一下读写数据的 ...

  3. Node.js开发入门—套接字(socket)编程

    Node.js的net模块提供了socket编程接口,方便我们利用较为底层的套接字接口来实现应用协议.这次我们看一个简单的回显服务器示例,包括服务端和客户端的代码. 代码 分服务器和客户端两部分来说吧 ...

  4. 网络编程 套接字socket TCP UDP

    网络编程与套接字 网络编程 网络编程是什么: ​ 网络通常指的是计算机中的互联网,是由多台计算机通过网线或其他媒介相互链接组成的 ​ 编写基于网络的应用程序的过程序称之为网络编程. 网络编程最主要的工 ...

  5. Java网络编程--套接字Socket

    一.套接字Socket IP地址标志Internet上的计算机,端口号标志正在计算机上运行的进程(程序). 端口号被规定为一个16位的0--65535之间的整数,其中,0--1023被预先定义的服务通 ...

  6. 网络编程(二)--TCP协议、基于tcp协议的套接字socket

    一.TCP协议(Transmission Control Protocol 传输控制协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会 ...

  7. 网络编程(二)——TCP协议、基于tcp协议的套接字socket

    TCP协议与基于tcp协议的套接字socket 一.TCP协议(流式协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的 ...

  8. 套接字编程,创建套接字socket

    1.套接字地址结构: struct sockaddr { sa_family_t sa_family; char sa_data[14]; }; 其中,成员sa_family表示套接字的协议族类型,对 ...

  9. day29 python 套接字socket TCP udp 形式发送信息的区别

    我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信. socket起源于UNIX,在 ...

随机推荐

  1. lua api 官方文档 函数后面的方括号 说明 [-0, +0, –]

    本博客注有“转”字样的为转载文章,其余为本人原创文章,转载请务必注明出处或保存此段.c++/lua/windows逆向交流群:69148232 每一个lua api 函数结尾都给出了这样的说明例如: ...

  2. App 开发步骤

    在 iOS 开发中,写一个 App 很容易,但是要写好一个 App,确是要下另一番功夫.首先,我们来看一个 App 的开发要求: 写一个 App,显示出 Spotify 上 Lady Gaga 相关的 ...

  3. linux下开启https

    1.在线安装mod_ssl yum -y install mod_ssl 查看openssl 是否安装成功 rpm -qa |grep openssl 2.建立服务器密钥 openssl genrsa ...

  4. 【java】浅析java组件中的布局管理器

    这篇博文笔者介绍一下java组件中,常用的布局管理器.java组件中的布局方式有好几十种,所有的这些布局管理器都实现了java.awt.LayoutManager接口.接下来笔者介绍一下常用的5种布局 ...

  5. 关于解锁美版Play市场

    关于解锁美版Play市场(本帖已经突破了G+的500评论上限,如有问题请转载留言) 我对这个问题思考的很深刻也思考了很久,作为一个深度google脑残粉怎么能用不完整的Play Store呢?那人生岂 ...

  6. C# 自定义控件入门

    原文地址:http://www.itdaan.com/blog/2008/03/29/95500785fa538b3900b34ee824376e8b.html 这几天为了什么"评估&quo ...

  7. IDEA使用笔记(二)——常用快捷键

    1:在IDEA上面找到快捷键都是有哪些?如下图所示: 2:导出快捷键的描述文件,打印一份,慢慢看,多使用,慢慢的就记住了 3:我自己在开发中经常使用的IDEA快捷键,主要是导航.查找.编辑相关的,如下 ...

  8. Photoshop做32位带Alpha通道的bmp图片

    原文链接: http://blog.sina.com.cn/s/blog_65c0cae801016e5u.html   批量制作32位带Alpha通道的bmp图片,可以制作一个动作,内容可以如下: ...

  9. [转]Tomcat中的Session小结

    阅读目录 什么是Session Session的目的 实现机制 Tomcat中的session实现 session存在的问题 什么是Session 对Tomcat而言,Session是一块在服务器开辟 ...

  10. 带你开始进入NPM的世界之NPM包的开发

    个人开发包的目录结构 ├── coverage //istanbul测试覆盖率生成的文件 ├── index.js //入口文件 ├── introduce.md //说明文件 ├── lib │   ...