Several important TCP/IP option parsing (Java sockets)

Source: Internet
Author: User
Tags jboss

The socket selection lets you specify how the socket class sends and accepts data. In JDK1.4 there are 8 socket options that can be set. All 8 of these options are defined in the Java.net.SocketOptions interface. Defined as follows:

Public final static int tcp_nodelay = 0x0001;public final static int so_reuseaddr = 0x04;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 S O_rcvbuf = 0x1002;public final static int so_keepalive = 0x0008;public final static int so_oobinline = 0x1003;

Interestingly, these 8 options are prefixed with so in addition to the first one not in the so prefix. In fact, this is the acronym for Socket option, so in Java, all constants prefixed with so are represented by the socket option; Of course, there are exceptions, such as Tcp_nodelay. A pair of get and set methods are provided for each option in the socket class. To get and set these options, respectively.

Ps:

    1. Netty of the Poor option description: http://docs.jboss.org/netty/3.2/api/org/jboss/netty/channel/socket/SocketChannelConfig.html

    2. Description of Oracle Http://docs.oracle.com/javase/6/docs/technotes/guides/net/socketOpt.html

1. Tcp_nodelay
public Boolean Gettcpnodelay () throws Socketexceptionpublic void Settcpnodelay (Boolean on) throws SocketException

By default, when a client sends data to the server, it determines whether to send it immediately, depending on the size of the packet. When the data in the packet is very small, such as only 1 bytes, and the packet header has dozens of bytes (IP header +tcp header), the system will be sent before sending the smaller package into a soft packet, together with the data sent out. When the next packet is sent, the system waits for the server to respond to the previous packet, and when it receives the response from the server, it sends the next packet, which is called the Nagle algorithm; By default, the Nagle algorithm is turned on.

Although this algorithm can effectively improve the efficiency of network transmission, but for the network speed is relatively slow, and the implementation of the high requirements of the situation (such as games, Telnet, etc.), the use of this method to transmit data will make the client has a noticeable pause phenomenon. Therefore, the best solution is to use it when the Nagle algorithm is needed and close it when it is not needed. And the use of Settcptodelay just can meet this demand. When the Nagle algorithm is closed with Settcpnodelay (true), the client sends the data every time it is sent, regardless of the packet size.

2. so_reuseaddr
public Boolean getreuseaddress () throws socketexception public void Setreuseaddress (Boolean on) throws Socketexc Eption

The wrong argument:

This option allows you to bind multiple socket objects on the same port.

The correct description is:

If the port is busy, but the TCP state is in Time_wait, the port can be reused. If the port is busy and the TCP state is in a different state, the reuse port still gets an error message, throwing "Address already in Use:jvm_bind". The SO_REUSEADDR option is useful when your service program stops and wants to restart immediately, for 60 seconds, while the new socket still uses the same port. It is important to realize that any non-expected data arrival at this time could lead to confusion in the service program, but it is only possible, in fact, impossible.

This parameter is different from the performance of the Linux platform on the Windows platform. The features of the Windows platform performance are not correct, and the performance features on the Linux platform are correct.

On the Windows platform, multiple socket new objects can be bound to the same port, and these new connections are non-time_wait state. This does not make much sense.

On the Linux platform, ports can be reused only if the TCP state is in time_wait. This is the right behavior.

Public class test {    public static void main (String[]  args)  {        try {             serversocket socket1 = new serversocket ();             serversocket socket2 = new  serversocket ();             Socket1.setreuseaddress (True);             Socket1.bind (new inetsocketaddress ("127.0.0.1",  8899));             system.out.println ("Socket1.getreuseaddress ():"                      +  Socket1.getreuseaddress ());       &NBSp;     socket2.setreuseaddress (True);             socket2.bind (new inetsocketaddress ("127.0.0.1",  8899));             system.out.println ("Socket2.getReuseAddress ():"                      + socket1.getreuseaddress ());         } catch   (exception e)  {             E.printstacktrace ();         }    }}

There are two points to note when using the SO_REUSEADDR option:

    1. You must use the Setreuseaddress method to open the option before calling the Bind method SO_REUSEADDR . Therefore, to use the SO_REUSEADDR option, you cannot bind a port by using the socket class's construction method.

    2. The SO_REUSEADDR option for all socket objects that are bound to the same port must be turned on to work. As in routine 4-12, both Socket1 and Socket2 use the Setreuseaddress method to open their respective SO_REUSEADDR options.

Running the above code on the Windows operating system results in the following: This result is incorrect.

Socket1.getreuseaddress (): Truesocket2.getreuseaddress (): True

Running the above code on the Linux operating system results in the following:

Socket1.getreuseaddress (): True java.net.BindException:Address already in use at Java.net.PlainSocketImpl.socketBind (Native Method) at Java.net.PlainSocketImpl.bind (plainsocketimpl.java:383) at Java.net.ServerSocket.bind (ServerS ocket.java:328) at Java.net.ServerSocket.bind (serversocket.java:286) at COM. Test.main (test.java:15)

This is the right result. Because the first connection is not a time_wait state, the second connection cannot use port 8899;

Only the first connection is time_wait state, the second connection will be able to use port 8899;

3. So_linger
public int Getsolinger () throws Socketexceptionpublic void Setsolinger (Boolean on, int linger) throws SocketException

This socket option can affect the behavior of the Close method. By default, when the Close method is called, it is returned immediately, and if there are still packets that are not sent, the packets are discarded. If the linger parameter is set to a positive integer n (the maximum value of n is 65,535), the Close method will be blocked for up to n seconds after it is called. In this n seconds, the system will try to send the data that is not sent out, if it exceeds n seconds, if there are packets packets, the packets will be discarded, and the Close method will return immediately. If you set linger to 0, the effect of the close SO_LINGER option is the same.

The SO_LINGER SocketException exception will be thrown if the underlying socket implementation does not support it. Setsolinger also throws an IllegalArgumentException exception when a negative value is passed to the linger parameter. The Getsolinger method can be used to get the delay time off, and if 1 is returned, the So_linger is closed. For example, the following code sets the delay-off time to 1 minutes:

if (socket.getsolinger () = =-1) Socket.setsolinger (true, 60);
4. So_timeout
public int getsotimeout () throws socketexceptionpublic void setsotimeout (int timeout) throws SocketException

This socket option has been discussed earlier. This option allows you to set the read data timeout. When the Read method of the input stream is blocked, if timeout is set (the unit of timeout is milliseconds), then the system throws a interruptedioexception exception after waiting for a timeout millisecond. After the exception is thrown, the input stream is not closed and you can continue reading the data through the Read method.

Setting Timeout to 0 means that read will wait indefinitely until the server program closes the socket. This is also the default value for timeout. The read data timeout is set to 30 seconds, as in the following statement:

Socket1.setsotimeout (30 * 1000);

These two methods will throw socketexception exceptions when the underlying socket implementation does not support the So_timeout option. You cannot set timeout to a negative number, otherwise the Setsotimeout method throws an IllegalArgumentException exception.

5. So_sndbuf
public int getsendbuffersize () throws socketexceptionpublic void setsendbuffersize (int size) throws SocketException

By default, the send buffer for the output stream is 8,096 bytes (8K). This value is the size of the output buffer recommended by Java. If this default value does not meet the requirements, you can use the Setsendbuffersize method to reset the buffer size. However, it is best not to set the output buffer too small, or it will cause the transmission of data too frequently, thereby reducing the efficiency of network transmission.

If the underlying socket implementation does not support the SO_SENDBUF option, these two methods will throw the SocketException exception. Size must be set to a positive integer, otherwise the Setsendbufferedsize method throws an IllegalArgumentException exception.

6. So_rcvbuf
public int getreceivebuffersize () throws socketexceptionpublic void setreceivebuffersize (int size) throws SocketException

By default, the receive buffer for the input stream is 8,096 bytes (8K). This value is the size of the input buffer recommended by Java. If this default value does not meet the requirements, you can use the Setreceivebuffersize method to reset the buffer size. However, it is best not to set the input buffer too small, or it will result in the transmission of data too frequently, thereby reducing the efficiency of network transmission.

If the underlying socket implementation does not support the SO_RCVBUF option, these two methods will throw the SocketException exception. Size must be set to a positive integer, otherwise the Setreceivebuffersize method throws an IllegalArgumentException exception.

7. So_keepalive
public Boolean getkeepalive () throws Socketexceptionpublic void Setkeepalive (Boolean on) throws SocketException

If this socket option is turned on, the client socket will send a packet to the server using an idle connection for a period of approximately two hours. This packet has no other effect, just to detect if the server is still active. If the server does not respond to this packet, after approximately 11 minutes, the client socket sends another packet, and if the server is not responding within 12 minutes, the client socket will be closed. If the socket option is turned off, the client socket may not shut down for a long time if the server is invalid.

The so_keepalive option is turned off by default, and you can use the following statement to turn this so_keepalive option on:

Socket1.setkeepalive (TRUE);

8. So_oobinline
public Boolean getoobinline () throws socketexception public void Setoobinline (Boolean on) throws SocketException

If this socket option is turned on, a single-byte data can be sent to the server via the Sendurgentdata method of the socket class. This single-byte data does not go through the output buffer, but is emitted immediately. Although the client does not use OutputStream to send data to the server, the single-byte data in the service-side program is mixed with other common data. As a result, it is not known in the service-side program whether the data sent by the client is OutputStream or sent over by Sendurgentdata. The following is a declaration of the Sendurgentdata method:

public void Sendurgentdata (int data) throws IOException

Although the Sendurgentdata parameter data is of type int, only the low byte of the int type is sent, and the other three bytes are ignored. The following code demonstrates how to use the So_oobinline option to send single-byte data.

package mynet;import java.net.*;import java.io.*;class server{     Public static void main (String[] args)  throws exception    {         ServerSocket serverSocket = new  ServerSocket (1234);         SYSTEM.OUT.PRINTLN ("Server has been started, port number: 1234");         while  (True)          {            Socket socket =  Serversocket.accept ();             Socket.setoobinline (true);             inputstream  in = socket.getinputstream ();             inputstreamreader inreader =&nbSp;new inputstreamreader (in);             Bufferedreader breader = new bufferedreader (Inreader);             system.out.println (Breader.readline ());             system.out.println (Breader.readline ());             socket.close ();         }    }}public class client{    public static  void main (String[] args)  throws Exception    {         socket socket = new socket ("127.0.0.1",  1234);         socket.setoobinline (True);         outputstream out =&nbSp;socket.getoutputstream ();         outputstreamwriter outwriter  = new outputstreamwriter (out);         outwriter.write ( ;              // ) Send the character "C" to the server         outwriter.write ("hello world\r\n");         socket.sendurgentdata (        //);   sends the character "A"         socket.sendurgentdata (322) to the server;         //  send the character "B" to the server          Outwriter.flush ();         socket.sendurgentdata (214);        //  send Chinese characters to the server "in"          Socket.sendurgentdata (208);     &NBsp;   socket.sendurgentdata (185);       //  sends the Chinese character "country" to the server         socket.sendurgentdata (+);         socket.close ();     }}

Since running the above code requires a server class, in addition to a server class named server, the usage of the service end socket will be discussed in detail in a later article. Only the Accept method of the ServerSocket class is used in the Class Server class to receive requests from clients. And reads two lines of string from the data from the client and displays it on the console.

Test

Because this example uses 127.0.0.1, the server and client classes must be running on the same machine.

Running the server

Java mynet. Server

Run Client

Java mynet. Client

Output from the console of the server

Server already started, port number: 1234ABChello World China

The Sendurgentdata method was used in the client class to send the characters ' A ' (65) and ' B ' (66) to the server. But sending ' B ' actually sends 322, because Sendurgentdata only sends a low byte of the integer number. Therefore, the actual send is 66. Decimal Integer 322 is in binary Form 1 as shown.

As can be seen from Figure 1, although 322 is distributed on two bytes, its low byte is still 66.

Use flush in the client class to send data from the buffer to the server. We can find a problem from the output, in the client class has been sent to the server ' C ', "Hello World" R "N", ' A ', ' B '. And on the console of the service-side program, it shows Abchello. World. This behavior indicates that the system sends the data immediately after sending it using the Sendurgentdata method, and using write to send the data, you must use the Flush method to actually send the data.

Sends a "Chinese" string to the server in the client class. Since "Zhong" is made up of 214 and 2,082 bytes, and "State" is made up of 185 and 2,502 bytes, it is possible to send these four bytes separately to transmit the "China" string.

Note: When you use the Setoobinline method to open the So_oobinline option, be aware that you must use the Setoobinline method on both the client and the server side to open this option, otherwise you cannot name sendurgentdata to send data.

Reference:
    1. http://elf8848.iteye.com/blog/1739598

    2. The KeepAlive of network programming http://blog.csdn.net/historyasamirror/article/details/5526486

    3. The Nettyk,connectiontimeoutmillis option can only be used by client, and server cannot use http://stackoverflow.com/questions/3234433/ What-is-the-meaning-of-child-connecttimeoutmillis-in-nettys-configuration

    4. Readtimeoutexception in Netty: Http://stackoverflow.com/questions/3726696/setting-socket-timeout-on-netty-channel


Several important TCP/IP option parsing (Java sockets)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.