TCP-Verbindung
Die Basis von TCP ist Socket. Bei einer TCP-Verbindung verwenden wir ServerSocket und Socket. Nachdem der Client und der Server eine Verbindung hergestellt haben, ist der Rest im Grunde die Steuerung der E/A.
Schauen wir uns zunächst eine einfache TCP-Kommunikation an, die in Client und Server unterteilt ist.
Der Client-Code lautet wie folgt:
public static void main(String[] args) löst eine IOException aus
{
Socket socket = null;
BufferedReader br = null;
PrintWriter pw = null;
BufferedReader brTemp = null;
versuchen
{
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 (Ausnahme ex)
{
System.err.println(ex.getMessage());
}
Endlich
{
if (socket != null) socket.close();
if (br != null) br.close();
if (brTemp != null) brTemp.close();
if (pw != null) pw.close();
}
}
}
public static void main(String[] args) löst eine IOException aus
{
ServerSocket server = null;
Socket-Client = null;
BufferedReader br = null;
PrintWriter pw = null;
versuchen
{
server = neuer 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("Antwort:" + Zeile);
pw.flush();
if (line.equals("end")) break;
}
}
Catch (Ausnahme ex)
{
System.err.println(ex.getMessage());
}
Endlich
{
if (server != null) server.close();
if (client != null) client.close();
if (br != null) br.close();
if (pw != null) pw.close();
}
}
}
Der obige Code beschreibt im Wesentlichen das Hauptgerüst des Clients und des Servers während des TCP-Kommunikationsprozesses. Wir können feststellen, dass der Server jeweils nur eine Anfrage vom Client verarbeiten kann Dies ist nicht dasselbe wie die Serververarbeitungsmethode in unserem Eindruck. Wenn eine Clientanfrage eingeht, erstellen wir einen Thread, um die entsprechende Anfrage zu verarbeiten.
Der verbesserte serverseitige Code lautet wie folgt:
Die Klasse ServerThread erweitert Thread
{
privater Socket socket = null;
öffentlicher ServerThread(Socket-Socket)
{
this.socket = socket;
}
public void run() {
BufferedReader br = null;
PrintWriter pw = null;
versuchen
{
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream());
while(true)
{
String line = br.readLine();
pw.println("Antwort:" + Zeile);
pw.flush();
if (line.equals("end")) break;
}
}
Catch (Ausnahme ex)
{
System.err.println(ex.getMessage());
}
Endlich
{
if (Socket != null)
versuchen {
socket.close();
} Catch (IOException e1) {
e1.printStackTrace();
}
if (br != null)
versuchen {
br.close();
} Catch (IOException e) {
e.printStackTrace();
}
if (pw != null) pw.close();
}
}
}
Beim Programmieren verwenden wir das Konzept der „Ressource“. Um die Leistung zu verbessern, zerstören wir normalerweise nicht direkt die Datenbankverbindung, sondern verwenden den Datenbankverbindungspool, um mehrere zu verwalten Datenbanken werden verwaltet und wiederverwendet. 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 Statusarray, um zu beschreiben, ob jede Socket-Verbindung verwendet wird Socket-Verbindung: Wir durchlaufen 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 für den TCP-Verbindungspool lautet wie folgt:
private InetAddress-Adresse = null;
privater int-Port;
private Socket[] arrSockets = null;
private boolean[] arrStatus = null;
private int count;
public TcpConnectionPool(InetAddress-Adresse, int-Port, int-Anzahl)
{
this.address = Adresse;
this.port = port;
this .count = count;
arrSockets = neuer Socket[count];
arrStatus = new boolean[count];
init();
}
private void init()
{
versuchen
{
for (int i = 0; i < count; i++)
{
arrSockets[i] = new Socket(address.getHostAddress(), port);
arrStatus[i] = false;
}
}
Catch (Ausnahme ex)
{
System.err.println(ex.getMessage());
}
}
öffentlicher Socket getConnection()
{
if (arrSockets == null) init();
int i = 0;
for(i = 0; i < count; i++)
{
if (arrStatus[i] == false)
{
arrStatus[i] = true;
brechen;
}
}
if (i == count) throw new RuntimeException("Im Moment ist keine Verbindung verfügbar.");
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;
brechen;
}
}
}
public void reBuild()
{
init();
}
öffentliche Leere zerstören()
{
if (arrSockets == null) return;
for(int i = 0; i < count; i++)
{
versuchen
{
arrSockets[i].close();
}
Catch (Ausnahme ex)
{
System.err.println(ex.getMessage());
weitermachen;
}
}
}
}
UDP ist eine andere Verbindungsmethode als TCP. Sie wird normalerweise in Situationen verwendet, die eine hohe Echtzeitleistung und geringe Anforderungen an die Genauigkeit erfordern, wie z. B. Online-Video. 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 für die UDP-Kommunikation verwendeten Klassen sind DatagramSocket und DatagramPacket. Letztere speichert den Inhalt der Kommunikation.
Das Folgende ist ein einfaches UDP-Kommunikationsbeispiel, das ebenfalls in zwei Teile unterteilt ist: Client und Server.
public static void main(String[] args)
{
versuchen
{
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(paket);
socket.close();
if (line.equals("end")) break;
}
br.close();
}
Catch (Ausnahme ex)
{
System.err.println(ex.getMessage());
}
}
}
public static void main(String[] args)
{
versuchen
{
int port = 5678;
DatagramSocket dsSocket = new DatagramSocket(port);
byte[] buffer = neues 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 (Ausnahme ex)
{
System.err.println(ex.getMessage());
}
}
}
Multicast verwendet eine ähnliche Methode wie UDP. Es werden IP-Adressen der Klasse D verwendet, und Standard-IP-Adressen der Klasse D beziehen sich auf Adressen zwischen 224.0.0.0 und 239.255.255.255, mit Ausnahme von 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:
public static void main(String[] args)
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
versuchen
{
InetAddress-Adresse = 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 (Ausnahme ex)
{
System.err.println(ex.getMessage());
}
}
}
public static void main(String[] args)
{
int port = 5678;
versuchen
{
MulticastSocket multicastSocket = new MulticastSocket(port);
InetAddress-Adresse = InetAddress.getByName("230.0.0.1");
multicastSocket.joinGroup(address);
byte[] buffer = neues 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 (Ausnahme ex)
{
System.err.println(ex.getMessage());
}
}
}
NIO ist ein neuer Satz von IO-APIs, der in JDK1.4 eingeführt wurde. Er verfügt über neue Designs 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.
public static void main(String[] args)
{
String host="127.0.0.1";
int port = 5678;
SocketChannel-Kanal = null;
versuchen
{
InetSocketAddress-Adresse = neue 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);
Kanal = SocketChannel.open();
Channel.connect(Adresse);
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 (Ausnahme ex)
{
System.err.println(ex.getMessage());
}
Endlich
{
if (Kanal != null)
versuchen {
Kanal.close();
} Catch (IOException e) {
// TODO Automatisch generierter Catch-Block
e.printStackTrace();
}
}
}
}