Java Socket中有很多参数可以选择,这篇文章的目的是沉淀出这些参数的语义和用法,供自己以后查阅。
1、java socket参数选项总览
在JDK1.6中有如下参数选项:
public final static int TCP_NODELAY = 0x0001;
public final static int SO_BINDADDR = 0x000F;
public final static int SO_REUSEADDR = 0x04;
public final static int SO_BROADCAST = 0x0020;
public final static int IP_MULTICAST_IF = 0x10;
public final static int IP_MULTICAST_IF2 = 0x1f;
public final static int IP_MULTICAST_LOOP = 0x12;
public final static int IP_TOS = 0x3;
public final static int SO_LINGER = 0x0080;
public final static int SO_TIMEOUT = 0x1006;
public final static int SO_SNDBUF = 0x1001;
public final static int SO_RCVBUF = 0x1002;
public final static int SO_KEEPALIVE = 0x0008;
public final static int SO_OOBINLINE = 0x1003;
?2、public final static int TCP_NODELAY = 0x0001;
要理解这个参数,首先要理解Nagle算法,下面先说说这个Nagle算法
2.1 Nagle算法产生的背景
? ? 当网络传输中存在大量小包传输时,会严重影响传输效率。比如一个包,包头40字节,而真正的内容只有一个字节或者几个字节(典型的有Telnet),这样的传输效率是十分低下的。Nagle算法要解决的就是这种低效率的传输问题。
2.2 Nagle算法的原理
? ? 用通俗的话来说就是,把小包要发送的字节先缓存,当到达一定的阀值的时候再一次性传输。具体算法(伪代码)如下:
if there is new data to send
? if the window size >= MSS and available data is >= MSS
? ? send complete MSS segment now
? else
? ? if there is unconfirmed data still in the pipe
? ? ? enqueue data in the buffer until an acknowledge is received
? ? else
? ? ? send data immediately
? ? end if
? end if
end if
其中MSS为maximum segment size的缩写,是TCP头部的一个字段,表示一个TCP段最大的数据承载量。
2.3 Nagle算法的问题
? 在传输大文件的时候,如果使用这个算法,那么会出现明显的延迟现象,因此,在这种情况下,最好是关闭这个算法。
知道了Nagle算法,就知道了TCP_NODELAY这个参数的意义了,如果这个参数被设置为True,那么就是关闭Nagle算法,实现无延迟传输,如果设置为false,则是打开这个算法,会对发送的数据进行缓存。
3、public final static int SO_BINDADDR = 0x000F;
? 获取绑定套接字的本地地址(不能仅将此选项“设置”为“得到”,因为套接字是在创建时绑定的,所以本地绑定的地址不可更改)。
4、public final static int SO_REUSEADDR = 0x04;
?
? 这个参数表示套接字对端口是否可重用。
? 这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,指明"地址已经使用中"。如果你的服务程序停止后想立即重启,而新套接字依旧使用同一端口,此时 SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能。
? ? ? 一个套接字由相关五元组构成,协议、本地地址、本地端口、远程地址、远程端口。SO_REUSEADDR 仅仅表示可以重用本地本地地址、本地端口,整个相关五元组还是唯一确定的。所以,重启后的服务程序有可能收到非期望数据。必须慎重使用 SO_REUSEADDR 选项。
?
5、public final static int SO_BROADCAST = 0x0020;
? ? ? 这个参数选项用来控制广播,目前只有在DatagramSocket里支持。
?
6、public final static int IP_MULTICAST_IF = 0x10;
? ? ? 用来控制多播的参数选项,目前只有在MulticastSocket里支持
? ? ? 在MulticastSocket的源代码里有设置多播的方法:
?
?public void setInterface(InetAddress inf) throws SocketException {
? ? if (isClosed()) {
? ? ? ? throw new SocketException("Socket is closed");
? ? }
? ? checkAddress(inf, "setInterface");
? ? synchronized (infLock) {
? ? ? ? getImpl().setOption(SocketOptions.IP_MULTICAST_IF, inf);
? ? ? ? infAddress = inf;
? ? }
? ? }
?
?
7、public final static int IP_MULTICAST_IF2 = 0x1f;
? ? ? ? 这个字段的效果和上面的是一样的,只是扩展支持IPV6
?
8、public final static int IP_MULTICAST_LOOP = 0x12;
? ? ? ? 用来设置本地回环接口的多播特性,在MulticastSocket源代码中有相关方法:
?
/**
? ? * Disable/Enable local loopback of multicast datagrams
? ? * The option is used by the platform's networking code as a hint
? ? * for setting whether multicast data will be looped back to
? ? * the local socket.
? ? *
? ? *
Because this option is a hint, applications that want to
? ? * verify what loopback mode is set to should call
? ? * {@link #getLoopbackMode()}
? ? * @param disable true to disable the LoopbackMode
? ? * @throws SocketException if an error occurs while setting the value
? ? * @since 1.4
? ? * @see #getLoopbackMode
? ? */
? ? public void setLoopbackMode(boolean disable) throws SocketException {
? ? getImpl()