TCP Connection
The foundation of TCP is Socket. In the TCP connection, we will use ServerSocket and Socket. After the client and server establish a connection, the rest is basically the control of I/O.
Let's first look at a simple TCP communication, which is divided into the client and the server.
The client code is as follows:
Copy codeThe Code is as follows: a simple TCP client
Import java.net .*;
Import java. io .*;
Public class SimpleTcpClient {
Public static void main (String [] args) throws IOException
{
Socket socket = null;
BufferedReader br = null;
PrintWriter pw = null;
BufferedReader brTemp = null;
Try
{
Socket = new Socket (InetAddress. getLocalHost (), 5678 );
Br = new BufferedReader (new InputStreamReader (socket. getInputStream ()));
Pw = new PrintWriter (socket. getOutputStream ());
BrTemp = new BufferedReader (new InputStreamReader (System. in ));
While (true)
{
String line = brTemp. readLine ();
Pw. println (line );
Pw. flush ();
If (line. equals ("end") break;
System. out. println (br. readLine ());
}
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
}
Finally
{
If (socket! = Null) socket. close ();
If (br! = Null) br. close ();
If (brTemp! = Null) brTemp. close ();
If (pw! = Null) pw. close ();
}
}
}
The server code is as follows:Copy codeThe Code is as follows:
Import java.net .*;
Import java. io .*;
Public class SimpleTcpServer {
Public static void main (String [] args) throws IOException
{
ServerSocket server = null;
Socket client = null;
BufferedReader br = null;
PrintWriter pw = null;
Try
{
Server = new serversockets (5678 );
Client = server. accept ();
Br = new BufferedReader (new InputStreamReader (client. getInputStream ()));
Pw = new PrintWriter (client. getOutputStream ());
While (true)
{
String line = br. readLine ();
Pw. println ("Response:" + line );
Pw. flush ();
If (line. equals ("end") break;
}
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
}
Finally
{
If (server! = Null) server. close ();
If (client! = Null) client. close ();
If (br! = Null) br. close ();
If (pw! = Null) pw. close ();
}
}
}
The functions of the server here are very simple. It receives messages sent from the client and then returns the messages "unblocked" to the client. When the client sends "end", the communication ends.
The above Code outlines the main framework of the client and server in the TCP communication process. We can find that in the above Code, the server is at any time, all of them can only process one request from the client. It is serialized and cannot be parallel. This is not the same as the server processing method we are impressed with. We can add multithreading to the server, when a client request enters, we create a thread to process the corresponding request.
The improved server code is as follows:
Copy codeThe Code is as follows:
Import java.net .*;
Import java. io .*;
Public class SmartTcpServer {
Public static void main (String [] args) throws IOException
{
ServerSocket server = new ServerSocket (5678 );
While (true)
{
Socket client = server. accept ();
Thread thread = new ServerThread (client );
Thread. start ();
}
}
}
Class ServerThread extends Thread
{
Private Socket socket = null;
Public ServerThread (Socket socket)
{
This. socket = socket;
}
Public void run (){
BufferedReader br = null;
PrintWriter pw = null;
Try
{
Br = new BufferedReader (new InputStreamReader (socket. getInputStream ()));
Pw = new PrintWriter (socket. getOutputStream ());
While (true)
{
String line = br. readLine ();
Pw. println ("Response:" + line );
Pw. flush ();
If (line. equals ("end") break;
}
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
}
Finally
{
If (socket! = Null)
Try {
Socket. close ();
} Catch (IOException e1 ){
E1.printStackTrace ();
}
If (br! = Null)
Try {
Br. close ();
} Catch (IOException e ){
E. printStackTrace ();
}
If (pw! = Null) pw. close ();
}
}
}
The modified server can process multiple requests from the client at the same time.
In the programming process, we have the concept of "resource". For example, database connection is a typical resource. To improve performance, we usually do not directly destroy database connections, instead, the database connection pool is used to manage multiple database connections, which has been reused. For Socket connections, it is also a resource. When our program requires a large number of Socket connections, if each connection needs to be re-established, it will be very inefficient.
Similar to the database connection pool, we can also design a TCP connection pool. The idea here is that we use an array to maintain multiple Socket connections, and another status array to describe whether each Socket connection is in use, when the program requires Socket connection, we traverse the status array and retrieve the first unused Socket connection. If all connections are in use, an exception is thrown. This is an intuitive and simple "scheduling policy". In many open-source or commercial frameworks (Apache/Tomcat), there are similar "resource pools ".
The TCP connection pool code is as follows:
Copy codeThe Code is as follows: a simple TCP Connection Pool
Import java.net .*;
Import java. io .*;
Public class TcpConnectionPool {
Private InetAddress address = null;
Private int port;
Private Socket [] arrSockets = null;
Private boolean [] arrStatus = null;
Private int count;
Public TcpConnectionPool (InetAddress address, int port, int count)
{
This. address = address;
This. port = port;
This. count = count;
ArrSockets = new Socket [count];
ArrStatus = new boolean [count];
Init ();
}
Private void init ()
{
Try
{
For (int I = 0; I <count; I ++)
{
ArrSockets [I] = new Socket (address. getHostAddress (), port );
ArrStatus [I] = false;
}
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
}
}
Public Socket getConnection ()
{
If (arrSockets = null) init ();
Int I = 0;
For (I = 0; I <count; I ++)
{
If (arrStatus [I] = false)
{
ArrStatus [I] = true;
Break;
}
}
If (I = count) throw new RuntimeException ("have no connection availiable for now .");
Return arrSockets [I];
}
Public void releaseConnection (Socket socket)
{
If (arrSockets = null) init ();
For (int I = 0; I <count; I ++)
{
If (arrSockets [I] = socket)
{
ArrStatus [I] = false;
Break;
}
}
}
Public void reBuild ()
{
Init ();
}
Public void destory ()
{
If (arrSockets = null) return;
For (int I = 0; I <count; I ++)
{
Try
{
ArrSockets [I]. close ();
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
Continue;
}
}
}
}
UDP connection
UDP is a connection method different from TCP. It is usually used in scenarios with high real-time requirements and low requirements on determination, such as online videos. UDP may cause "packet loss". In TCP, if the Server is not started, an exception is reported when the Client sends a message, but UDP does not produce any exceptions.
When two types of UDP communication are used, mongoramsocket and mongorampacket. The latter stores the communication content.
The following is a simple UDP Communication Example. Like TCP, it is also divided into two parts: Client and Server. The Client code is as follows:
Copy codeThe Code is as follows: UDP Communication Client
Import java.net .*;
Import java. io .*;
Public class UdpClient {
Public static void main (String [] args)
{
Try
{
InetAddress host = InetAddress. getLocalHost ();
Int port = 5678;
BufferedReader br = new BufferedReader (new InputStreamReader (System. in ));
While (true)
{
String line = br. readLine ();
Byte [] message = line. getBytes ();
Required rampacket packet = new DatagramPacket (message, message. length, host, port );
DatagramSocket socket = new DatagramSocket ();
Socket. send (packet );
Socket. close ();
If (line. equals ("end") break;
}
Br. close ();
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
}
}
}
The Server code is as follows:Copy codeThe Code is as follows: UDP Communication Server
Import java.net .*;
Import java. io .*;
Public class UdpServer {
Public static void main (String [] args)
{
Try
{
Int port = 5678;
DatagramSocket dsSocket = new DatagramSocket (port );
Byte [] buffer = new byte [1024];
DatagramPacket packet = new DatagramPacket (buffer, buffer. length );
While (true)
{
DsSocket. receive (packet );
String message = new String (buffer, 0, packet. getLength ());
System. out. println (packet. getAddress (). getHostName () + ":" + message );
If (message. equals ("end") break;
Packet. setLength (buffer. length );
}
DsSocket. close ();
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
}
}
}
Here, we assume that, like TCP, when the Client sends an "end" message, the communication is terminated. However, this design is not necessary and the Client can be disconnected at any time, you do not need to care about the Server status.
Multicasting)
Multicast adopts a method similar to UDP. It uses Class d ip addresses and standard UDP port numbers. Class d ip addresses refer to the addresses between 224.0.0.0 and 239.255.255.255, excluding 224.0.0.0.
The class used by multicast is MulticastSocket, which has two methods to be concerned: joinGroup and leaveGroup.
The following is an example of multicast. The Client code is as follows:
Copy codeThe Code is as follows: multicast communication Client
Import java.net .*;
Import java. io .*;
Public class MulticastClient {
Public static void main (String [] args)
{
BufferedReader br = new BufferedReader (new InputStreamReader (System. in ));
Try
{
InetAddress address = InetAddress. getByName ("230.0.0.1 ");
Int port = 5678;
While (true)
{
String line = br. readLine ();
Byte [] message = line. getBytes ();
DatagramPacket packet = new DatagramPacket (message, message. length, address, port );
MulticastSocket multicastSocket = new MulticastSocket ();
MulticastSocket. send (packet );
If (line. equals ("end") break;
}
Br. close ();
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
}
}
}
The server code is as follows:Copy codeThe Code is as follows: Multicast Communication Server
Import java.net .*;
Import java. io .*;
Public class MulticastServer {
Public static void main (String [] args)
{
Int port = 5678;
Try
{
MulticastSocket multicastSocket = new MulticastSocket (port );
InetAddress address = InetAddress. getByName ("230.0.0.1 ");
MulticastSocket. joinGroup (address );
Byte [] buffer = new byte [1024];
DatagramPacket packet = new DatagramPacket (buffer, buffer. length );
While (true)
{
MulticastSocket. receive (packet );
String message = new String (buffer, packet. getLength ());
System. out. println (packet. getAddress (). getHostName () + ":" + message );
If (message. equals ("end") break;
Packet. setLength (buffer. length );
}
MulticastSocket. close ();
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
}
}
}
NIO (New IO)
NIO is a new io api introduced by JDK1.4. It has a new design in buffer zone management, network communication, file access, and Character Set Operations. For network communication, NIO uses the concept of buffer and channel.
The following is an NIO example, which is very different from the code style we mentioned above.
Copy codeCode: NIO example
Import java. io .*;
Import java. nio .*;
Import java. nio. channels .*;
Import java. nio. charset .*;
Import java.net .*;
Public class NewIOSample {
Public static void main (String [] args)
{
String host = "127.0.0.1 ";
Int port = 5678;
SocketChannel channel = null;
Try
{
InetSocketAddress address = new InetSocketAddress (host, port );
Charset charset = Charset. forName ("UTF-8 ");
CharsetDecoder decoder = charset. newDecoder ();
CharsetEncoder encoder = charset. newEncoder ();
ByteBuffer buffer = ByteBuffer. allocate (1024 );
CharBuffer charBuffer = CharBuffer. allocate (1024 );
Channel = SocketChannel. open ();
Channel. connect (address );
String request = "GET/\ r \ n ";
Channel. write (encoder. encode (CharBuffer. wrap (request )));
While (channel. read (buffer ))! =-1)
{
Buffer. flip ();
Decoder. decode (buffer, charBuffer, false );
CharBuffer. flip ();
System. out. println (charBuffer );
Buffer. clear ();
CharBuffer. clear ();
}
}
Catch (Exception ex)
{
System. err. println (ex. getMessage ());
}
Finally
{
If (channel! = Null)
Try {
Channel. close ();
} Catch (IOException e ){
// TODO Auto-generated catch block
E. printStackTrace ();
}
}
}
}
The above code will attempt to access a local website and print out its content.