Heim  >  Artikel  >  Java  >  Anwendungsanalyse der Netzwerkkommunikation basierend auf der Java-Überprüfung

Anwendungsanalyse der Netzwerkkommunikation basierend auf der Java-Überprüfung

黄舟
黄舟Original
2016-12-19 14:55:221185Durchsuche

TCP-Verbindung

Die Basis von TCP ist die Verwendung von ServerSocket und Socket, nachdem der Client und der Server eine Verbindung hergestellt haben.

Schauen wir uns zunächst eine einfache TCP-Kommunikation an, die in Client und Server unterteilt ist.

Der Client-Code lautet wie folgt:

简单的TCP客户端 
 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();
         }
     }
 }

Der Server-Code lautet wie folgt:

简单版本TCP服务器端
 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 ServerSocket(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();
         }
     }
 }

Die Funktion des Servers hier ist sehr einfach, er empfängt Nachrichten vom Client und geben Sie dann die Nachricht „intakt“ an den Client zurück. Die Kommunikation endet, wenn der Client „end“ sendet.


Der obige Code beschreibt im Wesentlichen das Hauptgerüst des Clients und des Servers während des TCP-Kommunikationsprozesses. Wir können das im obigen Code jederzeit auf der Serverseite finden. Beide können nur eine Anfrage vom Client verarbeiten. Dies ist nicht dasselbe wie die Serververarbeitungsmethode in unserem Eindruck. Wir können dem Server mehrere Threads hinzufügen. Wir erstellen einfach einen Thread, um die entsprechende Anfrage zu bearbeiten.

Der verbesserte serverseitige Code lautet wie folgt:

多线程版本的TCP服务器端
 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();
         }
     }
 }

Die geänderte Serverseite kann mehrere Anfragen vom Client gleichzeitig verarbeiten.


Im Prozess der Programmierung verwenden wir normalerweise das Konzept der „Ressourcen“. Zerstören Sie die Datenbank nicht direkt, anstatt einen Datenbankverbindungspool zum Verwalten mehrerer Datenbankverbindungen zu verwenden. Der Zweck der Wiederverwendung wurde erreicht. Für Socket-Verbindungen ist es auch eine Ressource. Wenn unser Programm eine große Anzahl von Socket-Verbindungen benötigt, ist es ein sehr ineffizienter Ansatz, wenn jede Verbindung neu hergestellt werden muss.

Ähnlich wie beim Datenbankverbindungspool können wir auch einen TCP-Verbindungspool entwerfen. Die Idee hier ist, dass wir ein Array verwenden, um mehrere Socket-Verbindungen zu verwalten, und ein weiteres Status-Array, um zu beschreiben, ob jede Socket-Verbindung verwendet wird Wenn das Programm eine Socket-Verbindung benötigt, durchlaufen wir das Status-Array und entfernen die erste nicht verwendete Socket-Verbindung. Wenn alle Verbindungen verwendet werden, wird eine Ausnahme ausgelöst. Dies ist eine sehr intuitive und einfache „Planungsstrategie“. In vielen Open-Source- oder kommerziellen Frameworks (Apache/Tomcat) wird es ähnliche „Ressourcenpools“ geben.

Der Code des TCP-Verbindungspools lautet wie folgt:

一个简单的TCP连接池
 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-Verbindung


UDP ist eine andere Verbindungsmethode als TCP Es wird normalerweise in Situationen verwendet, in denen eine hohe Echtzeitleistung, aber geringe Anforderungen an die Ausrichtungsbestimmung erforderlich sind, z. B. bei Online-Videos. Bei UDP kommt es zu „Paketverlust“. Wenn der Server nicht gestartet wird, wird eine Ausnahme gemeldet, wenn der Client eine Nachricht sendet. Bei UDP wird jedoch keine Ausnahme generiert.

Die beiden in der UDP-Kommunikation verwendeten Klassen sind DatagramSocket und DatagramPacket. Letztere speichert den Kommunikationsinhalt.

Das Folgende ist ein einfaches UDP-Kommunikationsbeispiel, das ebenfalls in zwei Teile unterteilt ist: Client und Server:

UDP通信客户端
 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();
                 DatagramPacket 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());
         }
     }
 }

Der Servercode ist wie folgt:

UDP通信服务器端
 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());
         }
     }
 }

Hier gehen wir auch davon aus, dass die Kommunikation wie bei TCP als beendet gilt, wenn der Client die „Ende“-Nachricht sendet. Tatsächlich ist ein solches Design jedoch nicht erforderlich . Der Client kann die Verbindung jederzeit trennen und muss sich nicht um den Serverstatus kümmern.
Multicast


Multicast verwendet eine Methode ähnlich wie UDP. Es werden IP-Adressen der Klasse D und Standard-IP-Adressen der Klasse D verwendet. Es bezieht sich auf die Adressen dazwischen 224.0.0.0 und 239.255.255.255, ausgenommen 224.0.0.0.

Die im Multicast verwendete Klasse ist MulticastSocket, die zwei Methoden hat, auf die man achten muss: joinGroup und LeaveGroup.

Das Folgende ist ein Beispiel für Multicast. Der Client-Code lautet wie folgt:

多播通信客户端
 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());
         }
     }
 }

Der Servercode lautet wie folgt:

多播通信服务器端
 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 (Neues IO )


NIO ist ein neuer Satz von IO-APIs, der in JDK1.4 eingeführt wurde. Es verfügt über ein neues Design in den Bereichen Pufferverwaltung, Netzwerkkommunikation, Dateizugriff und Zeichensatzoperationen. Für die Netzwerkkommunikation verwendet NIO die Konzepte von Puffern und Kanälen.

Das Folgende ist ein Beispiel für NIO, das sich stark von dem oben erwähnten Codierungsstil unterscheidet.

NIO例子
 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\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();
                 }
         }
     }
 }

Der obige Code versucht, auf eine lokale URL zuzugreifen und dann deren Inhalt auszudrucken.

Das Obige ist die Anwendungsanalyse der Netzwerkkommunikation basierend auf der Java-Überprüfung. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn).


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Java-GenerikaNächster Artikel:Java-Generika