java socket 的参数选项解读(转)

简介: java socket中有很多参数可以选择,这篇博客的目的是沉淀出这些参数的语义和用法,供自己以后查阅。 1、java socket参数选项总览       在JDK1.6中有如下参数选项: 1 public final static int TCP_NODELAY = 0x00...

  java socket中有很多参数可以选择,这篇博客的目的是沉淀出这些参数的语义和用法,供自己以后查阅。

1、java socket参数选项总览

      在JDK1.6中有如下参数选项:

复制代码
 1 public final static int TCP_NODELAY = 0x0001;  2  3 public final static int SO_BINDADDR = 0x000F;  4  5 public final static int SO_REUSEADDR = 0x04;  6  7 public final static int SO_BROADCAST = 0x0020;  8  9 public final static int IP_MULTICAST_IF = 0x10; 10 11 public final static int IP_MULTICAST_IF2 = 0x1f; 12 13 public final static int IP_MULTICAST_LOOP = 0x12; 14 15 public final static int IP_TOS = 0x3; 16 17 public final static int SO_LINGER = 0x0080; 18 19 public final static int SO_TIMEOUT = 0x1006; 20 21 public final static int SO_SNDBUF = 0x1001; 22 23 public final static int SO_RCVBUF = 0x1002; 24 25 public final static int SO_KEEPALIVE = 0x0008; 26 27 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.
     *
     * <p>Because this option is a hint, applications that want to
     * verify what loopback mode is set to should call 
     * {@link #getLoopbackMode()}
     * @param disable <code>true</code> 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().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable)); }
复制代码

 

9、public final static int IP_TOS = 0x3;

      这个参数是用来控制IP头中的TOS字段的,是用来控制和优化IP包的路径的,在Socket源代码里有一个设置的方法:

     

复制代码
/**
     * Sets traffic class or type-of-service octet in the IP
     * header for packets sent from this Socket.
     * As the underlying network implementation may ignore this
     * value applications should consider it a hint.
     *
     * <P> The tc <B>must</B> be in the range <code> 0 <= tc <=
     * 255</code> or an IllegalArgumentException will be thrown.
     * <p>Notes:
     * <p> For Internet Protocol v4 the value consists of an octet
     * with precedence and TOS fields as detailed in RFC 1349. The
     * TOS field is bitset created by bitwise-or'ing values such
     * the following :-
     * <p>
     * <UL>
     * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
     * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
     * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
     * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
     * </UL>
     * The last low order bit is always ignored as this
     * corresponds to the MBZ (must be zero) bit.
     * <p>
     * Setting bits in the precedence field may result in a
     * SocketException indicating that the operation is not
     * permitted.
     * <p>
     * As RFC 1122 section 4.2.4.2 indicates, a compliant TCP
     * implementation should, but is not required to, let application
     * change the TOS field during the lifetime of a connection.
     * So whether the type-of-service field can be changed after the
     * TCP connection has been established depends on the implementation
     * in the underlying platform. Applications should not assume that
     * they can change the TOS field after the connection.
     * <p>
     * For Internet Protocol v6 <code>tc</code> is the value that
     * would be placed into the sin6_flowinfo field of the IP header.
     *
     * @param tc        an <code>int</code> value for the bitset.
     * @throws SocketException if there is an error setting the * traffic class or type-of-service * @since 1.4 * @see #getTrafficClass */ public void setTrafficClass(int tc) throws SocketException { if (tc < 0 || tc > 255) throw new IllegalArgumentException("tc is not in range 0 -- 255"); if (isClosed()) throw new SocketException("Socket is closed"); getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc)); }
复制代码

从源代码的注释看,TOS设置了是否生效,和底层的操作系统的实现有关。应用程序无法保证TOS的变更会对socket连接产生影响。个人认为,TOS在一般情况下用不到。

 

10、public final static int SO_LINGER = 0x0080;

      先看Socket源代码:

    

复制代码
/**
     * Enable/disable SO_LINGER with the specified linger time in seconds. 
     * The maximum timeout value is platform specific.
     *
     * The setting only affects socket close.
     * 
     * @param on     whether or not to linger on.
     * @param linger how long to linger for, if on is true. * @exception SocketException if there is an error * in the underlying protocol, such as a TCP error. * @exception IllegalArgumentException if the linger value is negative. * @since JDK1.1 * @see #getSoLinger() */ public void setSoLinger(boolean on, int linger) throws SocketException { if (isClosed()) throw new SocketException("Socket is closed"); if (!on) { getImpl().setOption(SocketOptions.SO_LINGER, new Boolean(on)); } else { if (linger < 0) { throw new IllegalArgumentException("invalid value for SO_LINGER"); } if (linger > 65535) linger = 65535; getImpl().setOption(SocketOptions.SO_LINGER, new Integer(linger)); } }
复制代码

 

      这个字段对Socket的close方法产生影响,当这个字段设置为false时,close会立即执行并返回,如果这时仍然有未被送出的数据包,那么这些数据包将被丢弃。如果设置为True时,有一个延迟时间可以设置。这个延迟时间就是close真正执行所有等待的时间,最大为65535。

 

11、public final static int SO_TIMEOUT = 0x1006;

     

复制代码
/**
     *  Enable/disable SO_TIMEOUT with the specified timeout, in
     *  milliseconds.  With this option set to a non-zero timeout,
     *  a read() call on the InputStream associated with this Socket
     *  will block for only this amount of time.  If the timeout expires,
     *  a <B>java.net.SocketTimeoutException</B> is raised, though the
     *  Socket is still valid. The option <B>must</B> be enabled
     *  prior to entering the blocking operation to have effect. The
     *  timeout must be > 0.
     *  A timeout of zero is interpreted as an infinite timeout.
     * @param timeout the specified timeout, in milliseconds.
     * @exception SocketException if there is an error * in the underlying protocol, such as a TCP error. * @since JDK 1.1 * @see #getSoTimeout() */ public synchronized void setSoTimeout(int timeout) throws SocketException { if (isClosed()) throw new SocketException("Socket is closed"); if (timeout < 0) throw new IllegalArgumentException("timeout can't be negative"); getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); }
复制代码

 

      这个参数用来控制客户端读取socket数据的超时时间,如果timeout设置为0,那么就一直阻塞,否则阻塞直到超时后直接抛超时异常。

 

12、public final static int SO_SNDBUF = 0x1001;

       在默认情况下,输出流的发送缓冲区是8096个字节(8K)。这个值是Java所建议的输出缓冲区的大小。如果这个默认值不能满足要求,可以用setSendBufferSize方法来重新设置缓冲区的大小。

    

 

13、public final static int SO_RCVBUF = 0x1002;

     在默认情况下,输入流的接收缓冲区是8096个字节(8K)。这个值是Java所建议的输入缓冲区的大小。如果这个默认值不能满足要求,可以用setReceiveBufferSize方法来重新设置缓冲区的大小。

 

14、public final static int SO_KEEPALIVE = 0x0008;

      如果将这个参数这是为True,客户端每隔一段时间(一般不少于2小时)就像服务器发送一个试探性的数据包,服务器一般会有三种回应:

     1、服务器正常回一个ACK,这表明远程服务器一切OK,那么客户端不会关闭连接,而是再下一个2小时后再发个试探包。

     2、服务器返回一个RST,这表明远程服务器挂了,这时候客户端会关闭连接。

     3、如果服务器未响应这个数据包,在大约11分钟后,客户端Socket再发送一个数据包,如果在12分钟内,服务器还没响应,那么客户端Socket将关闭。

 

15、public final static int SO_OOBINLINE = 0x1003;

       如果这个Socket选项打开,可以通过Socket类的sendUrgentData方法向服务器发送一个单字节的数据。这个单字节数据并不经过输出缓冲区,而是立即发出。虽然在客户端并不是使用OutputStream向服务器发送数据,但在服务端程序中这个单字节的数据是和其它的普通数据混在一起的。因此,在服务端程序中并不知道由客户端发过来的数据是由OutputStream还是由sendUrgentData发过来的。

http://www.cnblogs.com/biakia/p/4321800.html

相关文章
|
25天前
|
Java
实现java执行kettle并传参数
实现java执行kettle并传参数
29 1
|
2月前
|
Java 流计算
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
45 1
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
|
2月前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
33 1
|
1月前
|
Java
在Java中定义一个不做事且没有参数的构造方法的作用
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
|
2月前
|
网络协议 安全 Java
Java Socket原理
Java Socket原理是指在Java中通过Socket实现的网络通信的基础理论与机制。Socket是网络中不同设备间通信的一种标准方式,它允许应用程序之间通过TCP/IP等协议进行数据交换。在Java中,利用Socket编程可以方便地创建客户端与服务器端应用,实现跨网络的数据传输功能,是互联网软件开发中的重要技术之一。它支持多种通信模式,如可靠的流式套接字(TCP)和数据报式套接字(UDP)。
59 10
|
2月前
|
存储 算法 Java
java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题
这篇文章是关于如何在Java中使用Graphics2D的RenderingHints方法来提高海报制作的图像质量和文字清晰度,包括抗锯齿和解决文字不清晰问题的技术详解。
69 0
java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题
|
2月前
|
Java
java构造方法时对象初始化,实例化,参数赋值
java构造方法时对象初始化,实例化,参数赋值
72 1
|
4月前
|
Java
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
|
4月前
|
C# 开发者 Windows
震撼发布:全面解析WPF中的打印功能——从基础设置到高级定制,带你一步步实现直接打印文档的完整流程,让你的WPF应用程序瞬间升级,掌握这一技能,轻松应对各种打印需求,彻底告别打印难题!
【8月更文挑战第31天】打印功能在许多WPF应用中不可或缺,尤其在需要生成纸质文档时。WPF提供了强大的打印支持,通过`PrintDialog`等类简化了打印集成。本文将详细介绍如何在WPF应用中实现直接打印文档的功能,并通过具体示例代码展示其实现过程。
399 0
|
4月前
|
缓存 前端开发 Java
【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(-Xms512m -Xmx1204m)?
【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(-Xms512m -Xmx1204m)?
下一篇
DataWorks