Java must know socket

  java, socket

On the Internet, data is transmitted in packets of limited size. These packets are called datagrams. Each datagram contains a header and a payload. The header contains the address and port to which the packet is sent, the address and port from which the packet comes, a checksum to detect whether the data is corrupted, and various other management information to ensure reliable transmission.

The payload contains the data itself.

However, due to the limited length of datagrams, it is usually necessary to split the data into multiple packets and reassemble them at the destination. It is also possible that one or more packets are lost or destroyed in transmission and need to be retransmitted. Or packets arrive out of order and need to be reordered. All of these (decomposing data into packets, generating headers, parsing headers of inbound packets, tracking which packets have been received and which have not) are very heavy tasks and require a lot of complicated codes.

Socket helps you to cover up these underlying details, such as error detection, packet size, packet decomposition, packet retransmission, network address, etc. Socket allows programmers to think of a network connection as another stream that can read and write bytes.

Socket is a connection between two hosts, it can complete 7 basic operations:
1) Connect the remote host
2) sending data
3) receiving data
4) Close the connection
5) Binding Port
6) monitoring inbound data
7) Accept the connection from the remote machine on the binding port

Once the socket connection is established, the iostream can be used. This connection is full-duplex, and both hosts can send and receive data at the same time.

SMTP is the protocol used to transfer e-mail between servers or between mail clients and servers.

Half-closed Socket:close Close method closes both the input stream and the output stream of the Socket. If you only want to close half of the connection (input/output), call the shutdownInput or shutdownOutput method. These two methods do not close Scoket, in fact, it will adjust the stream connected to Socket to make it think it has reached the end of the stream. After closing the input, reading the input stream again will return -1, and writing Socket after closing the output stream will throw an IOException exception.
Even if the connection is partially closed or both halves of the connection are closed, the Socket needs to be closed after use. Shutdown only affects socket flow and does not release resources associated with socket, such as occupied ports, etc.

Java.net.Socket is the basic class for Java to complete client TCP operations. It uses native code to communicate with the local TCP stack of the host operating system.

public Socket(String host, int port) throws UnknownHostException, IOException
public Socket(InetAddress host, int port) throws IOException

These two constructors will establish an active network connection with the remote host before returning. Port is between 1~65535.

public Socket()
public Socket(Proxy proxy)
protected Socket(SocketImpl impl)
These three functions can create unconnected Socket.

public Socket(String host, int port, InetAddress interface, int localPort)

  throws IOException, UnknownHostException

public Socket(InetAddress host, int port, InetAddress interface, int localPort)

  throws IOException

These two constructors can be used to specify which interface and port to connect from.

SocketAddress

SocketAddress represents a connection endpoint, which can be theoretically used for TCP and non-TCP socket. In fact, only TCP/IP Socket is supported.

SocketAddress mainly provides a convenient storage for temporary Socket connection information (such as IP address and port). Even if the original socket is disconnected and garbage collected, the information can be reused to create a new socket.

boolean connected = socket.isConnected() && ! socket.isClosed();

IsConnected indicates whether a remote host has been connected, even if the socket has been closed, so it is necessary to judge whether the socket is open and whether it has been closed.

Socket option

1)TCP_NODELAY

Set to true to ensure that packets are sent as quickly as possible, regardless of packet size.
Under normal circumstances, small packets are combined into larger packets before sending. Before sending another packet, the local host waits for the remote system to confirm the previous packet. This is called Nagle algorithm.

The problem with Nagle algorithm is that if the remote system does not send acknowledgements back to the local system fast enough, applications that rely on stable transmission of small amounts of data will slow down. This problem is especially serious for computer applications such as networks or games (the server needs to track the movement of the client’s mouse in real time). In a relatively slow network, even simple typing becomes too slow due to continuous buffering. Set to true to turn off this buffering mode so that all packets will be sent as soon as they are ready.

2)SO_LINGER

Specifies how to handle unsent datagrams when Socket is closed. by default, the close method will return immediately, but the system will still try to send the remaining data. if the delay time is set to 0, all unsent packets will be discarded when Socket is closed. if SO_LINGER is opened and the delay time is set to any positive number, the close method will block the specified time, waiting for sending data and receiving confirmation. After the specified time passes, Socket is closed, and all remaining data will not be sent or acknowledged.
Returns -1 to indicate that this option is disabled and will take more time to send the remaining data as needed.

3)SO_TIMEOUT

Under normal circumstances, when trying to read data from Socket, the read () call will block as long as possible to get enough bytes. Set timeout to ensure that the time that this call will be blocked will not exceed the specified threshold. If it exceeds the specified threshold, an exception will be thrown, but the Socket is still connected. You can try to starve the Socket again, and the next call may be successful.
0 means infinite timeout.

4)SO_RCVBUF and SO_SNDBUF

TCP uses buffers to improve network performance. Larger buffers improve the performance of fast connections (such as 10M/s), while slower dial-up connections perform better with smaller buffers.

Generally speaking, when transmitting continuous large data blocks (more common in ftp and http), you can benefit from large buffers, while large buffers are not very helpful for small data volume transmission of interactive sessions (such as telnet and many games). 128K Kbytes is now a common default setting.

Maximum bandwidth achievable = buffer size/delay. For example, on xp, assuming a delay of 500ms between two hosts and a buffer size of 17520 bytes on xp, bandwidth = 17520/0.5 = 273.75 kb/s. This is the maximum speed of Socket, no matter how fast the network is. For a dial-up connection, this speed is already very fast.

Speed can be increased by reducing latency, however, latency is related to network hardware and depends on factors other than your application control.
If the buffer is increased from 17520 bytes to 128K, the maximum bandwidth will increase to 2Mb/s, and if it is increased to 256K, the maximum bandwidth will increase to 4mb/s.

Of course, the network itself has a limit on the maximum bandwidth. If the buffer is set too high, the program will try to send and receive data at too high a speed, and the network will not have time to process it, which will lead to congestion, packet loss and performance degradation. Therefore, in order to obtain the maximum bandwidth, it is necessary to match the buffer size with the connection delay, which is slightly smaller than the bandwidth of the network.

Ping can be used to detect the delay of the host.

SO_RCVBUF controls the size of the proposed receive buffer for network input. Although the size of the receive and send buffers can be set independently, in practice the buffer is usually set to the smaller of the two.

Linux systems usually specify a maximum buffer size, usually 64KB or 256KB, and do not allow any socket to have a larger buffer.

In general, if you cannot make full use of the available bandwidth for sending your application (for example, you have a 25Mb/s Internet connection, but the data transfer rate is only 1.5Mb/s), you can try to increase the size of the buffer. On the contrary, if there is packet loss and congestion, the buffer size should be reduced.

However, in most cases, the default value is appropriate unless the network is overloaded in one direction. Specifically, modern operating systems use TCP window scaling to dynamically adjust the buffer size to adapt to the network.

The general experience is that unless you detect a problem, do not make adjustments. Generally, adjusting the maximum buffer size of the operating system is more beneficial than adjusting the buffer size of a single socket in Java.

5)SO_KEEPALIVE

If this is turned on, the client will occasionally send a packet over an idle connection (usually every two hours) to ensure that the server does not crash. If the server fails to respond to this package, the client will continue to try for more than 11 minutes until a response is received. If no response is received within 12 minutes, the client closes the socket. If this is not turned on, inactive clients may exist forever without noticing whether the server has crashed.

6)OOBINLINE

TCP includes a feature that can send single byte Out Of Band (OOB) emergency data. This data will be sent immediately. In addition, the receiver will be notified when it receives emergency data. It can choose to process the emergency data (flush the current buffer if necessary) before processing other received data.

The corresponding method in Java is sendUrgentData

By default, Java ignores emergency data received from Socket, and setOOBInline is required to be true if you want to receive emergency data from normal data. Once turned on, any emergency data that arrives will be placed in Socket’s input stream in the normal way waiting to be read.

7)SO_REUSEADDR

When a Socket is closed, the local port may not be released immediately, especially if there is still an open connection when the Socket is closed, the local port will not be released, and sometimes it will wait for a short period of time to ensure that all delayed packets to be sent to this port are received. When the Socket is closed, these packets may still be transmitted on the network, and the system will not do any processing to the received delayed packets, but only wants to ensure that these data will not be accidentally passed into a new process bound to the same port.

If a random port is used, the problem is not big, but if a Socket is bound to a known port, there may be a problem because it prevents all other Sockets from using this port at the same time. If this parameter is turned on (the default is off), another Socket is allowed to bind to this port, even though there may still be data not received by the previous socket at this time.

SetReuseAddress must be called before binding a new Socket. This value is set to true only for the Socket previously connected and the new Scoket reusing the old address.

8)IP_TOS

Different types of Internet services have different requirements for performance, for example, video requires relatively high bandwidth and short delay, while email can be delivered through lower bandwidth connections.
The service type is stored in an 8-bit field named IP_TOS in the IP header. SetTrafficClass is used to set in java. In Java, it is 0-255, but TCP header requires 8 bits, so only the low byte of int can be used.

Socket exception
1)BindException, the port is occupied or does not have permission to use the port
2)ConnectException, the connection to the remote host is denied (the remote host is busy or no process listens to the port)
3)NoRouteToHostException, connection timeout
4)ProtocolException, violation of TCP/IP regulations