Suche…


Syntax

  • neuer Socket ("localhost", 1234); // Stellt eine Verbindung zu einem Server unter der Adresse "localhost" und Port 1234 her
  • neuer SocketServer ("localhost", 1234); // Erstellt einen Socket-Server, der an der Adresse localhost und Port 1234 auf neue Sockets warten kann
  • socketServer.accept (); // Akzeptiert ein neues Socket-Objekt, das zur Kommunikation mit dem Client verwendet werden kann

Grundlegende Client- und Server-Kommunikation über einen Socket

Server: Starten Sie und warten Sie auf eingehende Verbindungen

//Open a listening "ServerSocket" on port 1234.
ServerSocket serverSocket = new ServerSocket(1234); 

while (true) {
    // Wait for a client connection.
    // Once a client connected, we get a "Socket" object
    // that can be used to send and receive messages to/from the newly 
    // connected client
    Socket clientSocket = serverSocket.accept();            
    
    // Here we'll add the code to handle one specific client.
}

Server: Umgang mit Clients

Wir behandeln jeden Client in einem separaten Thread, sodass mehrere Clients gleichzeitig mit dem Server interagieren können. Diese Technik funktioniert gut, solange die Anzahl der Clients gering ist (<< 1000 Clients, abhängig von der Betriebssystemarchitektur und der erwarteten Last jedes Threads).

new Thread(() -> {
    // Get the socket's InputStream, to read bytes from the socket
    InputStream in = clientSocket.getInputStream();
    // wrap the InputStream in a reader so you can read a String instead of bytes
    BufferedReader reader = new BufferedReader(
            new InputStreamReader(in, StandardCharsets.UTF_8));
    // Read text from the socket and print line by line
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
    }).start();

Client: Verbinden Sie sich mit dem Server und senden Sie eine Nachricht

// 127.0.0.1 is the address of the server (this is the localhost address; i.e.
// the address of our own machine)
// 1234 is the port that the server will be listening on
Socket socket = new Socket("127.0.0.1", 1234);

// Write a string into the socket, and flush the buffer
OutputStream outStream = socket.getOutputStream();
PrintWriter writer = new PrintWriter(
        new OutputStreamWriter(outStream, StandardCharsets.UTF_8));
writer.println("Hello world!");
writer.flush();

Schließen von Sockets und Behandeln von Ausnahmen

Die obigen Beispiele ließen einige Dinge aus, um sie leichter lesbar zu machen.

  1. Genau wie Dateien und andere externe Ressourcen ist es wichtig, dass wir dem Betriebssystem mitteilen, wenn wir damit fertig sind. Wenn wir mit einem Socket fertig sind, rufen Sie socket.close() auf, um ihn richtig zu schließen.

  2. Sockets behandeln E / A-Vorgänge (Eingabe / Ausgabe), die von verschiedenen externen Faktoren abhängen. Was passiert zum Beispiel, wenn die andere Seite plötzlich getrennt wird? Was ist, wenn ein Netzwerkfehler vorliegt? Diese Dinge liegen außerhalb unserer Kontrolle. Aus diesem Grund können viele IOException Ausnahmen IOException , insbesondere IOException .

Ein vollständigerer Code für den Client wäre daher etwa so:

 // "try-with-resources" will close the socket once we leave its scope
 try (Socket socket = new Socket("127.0.0.1", 1234)) {
     OutputStream outStream = socket.getOutputStream();
     PrintWriter writer = new PrintWriter(
             new OutputStreamWriter(outStream, StandardCharsets.UTF_8));
     writer.println("Hello world!");
     writer.flush();
 } catch (IOException e) {
     //Handle the error
 }

Basic Server und Client - vollständige Beispiele

Server:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class Server {
    public static void main(String args[]) {
        try (ServerSocket serverSocket = new ServerSocket(1234)) {
            while (true) {
                // Wait for a client connection.
                Socket clientSocket = serverSocket.accept();
                
                // Create and start a thread to handle the new client
                new Thread(() -> {
                    try {
                        // Get the socket's InputStream, to read bytes 
                        // from the socket
                        InputStream in = clientSocket.getInputStream();
                        // wrap the InputStream in a reader so you can 
                        // read a String instead of bytes
                        BufferedReader reader = new BufferedReader(
                             new InputStreamReader(in, StandardCharsets.UTF_8));
                        // Read from the socket and print line by line
                        String line;
                        while ((line = reader.readLine()) != null) {
                            System.out.println(line);
                        }
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        // This finally block ensures the socket is closed.
                        // A try-with-resources block cannot be used because
                        // the socket is passed into a thread, so it isn't 
                        // created and closed in the same block
                        try {
                            clientSocket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }

    }
}

Klient:

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class Client {
    public static void main(String args[]) {
        try (Socket socket = new Socket("127.0.0.1", 1234)) {
            // We'll reach this code once we've connected to the server
            
            // Write a string into the socket, and flush the buffer
            OutputStream outStream = socket.getOutputStream();
            PrintWriter writer = new PrintWriter(
                    new OutputStreamWriter(outStream, StandardCharsets.UTF_8));
            writer.println("Hello world!");
            writer.flush();
        } catch (IOException e) {
            // Exception should be handled.
            e.printStackTrace();
        }
    }
}

TrustStore und KeyStore werden aus InputStream geladen

public class TrustLoader {
    
    public static void main(String args[]) {
        try {
                //Gets the inputstream of a a trust store file under ssl/rpgrenadesClient.jks
                //This path refers to the ssl folder in the jar file, in a jar file in the same directory
                //as this jar file, or a different directory in the same directory as the jar file
                InputStream stream = TrustLoader.class.getResourceAsStream("/ssl/rpgrenadesClient.jks");
                //Both trustStores and keyStores are represented by the KeyStore object
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                //The password for the trustStore
                char[] trustStorePassword = "password".toCharArray();
                //This loads the trust store into the object
                trustStore.load(stream, trustStorePassword);
                
                //This is defining the SSLContext so the trust store will be used
                //Getting default SSLContext to edit.
                SSLContext context = SSLContext.getInstance("SSL");
                //TrustMangers hold trust stores, more than one can be added
                TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                //Adds the truststore to the factory
                factory.init(trustStore);
                //This is passed to the SSLContext init method
                TrustManager[] managers = factory.getTrustManagers();
                context.init(null, managers, null);
                //Sets our new SSLContext to be used.
                SSLContext.setDefault(context);
            } catch (KeyStoreException | IOException | NoSuchAlgorithmException 
                    | CertificateException | KeyManagementException ex) {
                //Handle error
                ex.printStackTrace();
            }
        
    }
}

Die Initialisierung eines KeyStores funktioniert genauso, mit der Ausnahme, dass ein beliebiges Wort Trust in einem Objektnamen durch Key . Darüber hinaus muss das KeyManager[] Array an das erste Argument von SSLContext.init . Das ist SSLContext.init(keyMangers, trustMangers, null)

Socket-Beispiel - Lesen einer Webseite mit einem einfachen Socket

import java.io.*;
import java.net.Socket;

public class Main {

    public static void main(String[] args) throws IOException {//We don't handle Exceptions in this example 
        //Open a socket to stackoverflow.com, port 80
        Socket socket = new Socket("stackoverflow.com",80);

        //Prepare input, output stream before sending request
        OutputStream outStream = socket.getOutputStream();
        InputStream inStream = socket.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
        PrintWriter writer = new PrintWriter(new BufferedOutputStream(outStream));

        //Send a basic HTTP header
        writer.print("GET / HTTP/1.1\nHost:stackoverflow.com\n\n");
        writer.flush();

        //Read the response
        System.out.println(readFully(reader));

        //Close the socket
        socket.close();
    }
    
    private static String readFully(Reader in) {
        StringBuilder sb = new StringBuilder();
        int BUFFER_SIZE=1024;
        char[] buffer = new char[BUFFER_SIZE]; // or some other size, 
        int charsRead = 0;
        while ( (charsRead  = rd.read(buffer, 0, BUFFER_SIZE)) != -1) {
          sb.append(buffer, 0, charsRead);
        }
    }
}

Sie sollten eine Antwort erhalten, die mit HTTP/1.1 200 OK beginnt HTTP/1.1 200 OK ist eine normale HTTP-Antwort, gefolgt vom restlichen HTTP-Header, gefolgt von der rohen Webseite im HTML-Format.

Beachten Sie, dass die readFully() -Methode wichtig ist, um eine vorzeitige EOF-Ausnahme zu verhindern. Möglicherweise fehlt in der letzten Zeile der Webseite ein Return, um das Zeilenende zu signalisieren. Anschließend wird sich readLine() beschweren. readLine() muss man es readLine() lesen oder Dienstprogramme von Apache commons-io IOUtils verwenden

Dieses Beispiel dient als einfache Demonstration der Verbindung mit einer vorhandenen Ressource über einen Socket. Es ist keine praktische Möglichkeit, auf Webseiten zuzugreifen. Wenn Sie mit Java auf eine Webseite zugreifen müssen, verwenden Sie am besten eine vorhandene HTTP-Client-Bibliothek wie den HTTP-Client von Apache oder den HTTP-Client von Google

Grundlegende Client / Server-Kommunikation über UDP (Datagramm)

Client.java

import java.io.*;
import java.net.*;
    
public class Client{
    public static void main(String [] args) throws IOException{
        DatagramSocket clientSocket = new DatagramSocket(); 
        InetAddress address = InetAddress.getByName(args[0]);

        String ex = "Hello, World!";
        byte[] buf = ex.getBytes();

        DatagramPacket packet = new DatagramPacket(buf,buf.length, address, 4160); 
        clientSocket.send(packet);
    }
}

In diesem Fall übergeben wir die Adresse des Servers über ein Argument ( args[0] ). Der verwendete Port ist 4160.

Server.java

import java.io.*;
import java.net.*;

public class Server{
    public static void main(String [] args) throws IOException{
        DatagramSocket serverSocket = new DatagramSocket(4160);

        byte[] rbuf = new byte[256];
        DatagramPacket packet = new DatagramPacket(rbuf, rbuf.length);        
        serverSocket.receive(packet);
        String response = new String(packet.getData());
        System.out.println("Response: " + response);
    }
}

Deklarieren Sie serverseitig ein DatagramSocket an demselben Port, an den wir unsere Nachricht gesendet haben (4160), und warten Sie auf eine Antwort.

Multicasting

Multicasting ist eine Art Datagram-Socket. Im Gegensatz zu regulären Datagrammen behandelt Multicasting nicht jeden Client einzeln, sondern sendet ihn an eine IP-Adresse und alle abonnierten Clients erhalten die Nachricht.

Geben Sie hier die Bildbeschreibung ein

Beispielcode für eine Serverseite:

public class Server {
    
    private DatagramSocket serverSocket;
    
    private String ip;
    
    private int port;
    
    public Server(String ip, int port) throws SocketException, IOException{
        this.ip = ip;
        this.port = port;
        // socket used to send
        serverSocket = new DatagramSocket();
    }
    
    public void send() throws IOException{
        // make datagram packet
        byte[] message = ("Multicasting...").getBytes();
        DatagramPacket packet = new DatagramPacket(message, message.length, 
            InetAddress.getByName(ip), port);
        // send packet
        serverSocket.send(packet);
    }
    
    public void close(){
        serverSocket.close();
    }
}

Beispielcode für eine Clientseite:

public class Client {
    
    private MulticastSocket socket;
    
    public Client(String ip, int port) throws IOException {
        
        // important that this is a multicast socket
        socket = new MulticastSocket(port);
        
        // join by ip
        socket.joinGroup(InetAddress.getByName(ip));
    }
    
    public void printMessage() throws IOException{
        // make datagram packet to recieve
        byte[] message = new byte[256];
        DatagramPacket packet = new DatagramPacket(message, message.length);
        
        // recieve the packet
        socket.receive(packet);
        System.out.println(new String(packet.getData()));
    }
    
    public void close(){
        socket.close();
    }
}

Code zum Ausführen des Servers:

public static void main(String[] args) {
    try {
        final String ip = args[0];
        final int port = Integer.parseInt(args[1]);
        Server server = new Server(ip, port);
        server.send();
        server.close();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

Code zum Ausführen eines Clients:

public static void main(String[] args) {
    try {
        final String ip = args[0];
        final int port = Integer.parseInt(args[1]);
        Client client = new Client(ip, port);
        client.printMessage();
        client.close();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

Führen Sie den Client zuerst aus: Der Client muss die IP-Adresse abonnieren, bevor er Pakete empfangen kann. Wenn Sie den Server starten und die send() -Methode aufrufen, printMessage() einen Client (& rufen Sie printMessage() ). Nichts wird passieren, weil der Client nach dem Senden der Nachricht eine Verbindung hergestellt hat.

Deaktivieren Sie die SSL-Überprüfung vorübergehend (zu Testzwecken).

In einer Entwicklungs- oder Testumgebung wurde die SSL-Zertifikatskette manchmal (noch) nicht vollständig eingerichtet.

Um die Entwicklung und das Testen fortzusetzen, können Sie die SSL-Überprüfung programmgesteuert deaktivieren, indem Sie einen "all-trusting" Trust Manager installieren:

try {
   // Create a trust manager that does not validate certificate chains
   TrustManager[] trustAllCerts = new TrustManager[] {
      new X509TrustManager() {
       public X509Certificate[] getAcceptedIssuers() {
           return null;
       }
       public void checkClientTrusted(X509Certificate[] certs, String authType) {
       }
       public void checkServerTrusted(X509Certificate[] certs, String authType) {
       }
      }
   };

   // Install the all-trusting trust manager
   SSLContext sc = SSLContext.getInstance("SSL");
   sc.init(null, trustAllCerts, new java.security.SecureRandom());
   HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

   // Create all-trusting host name verifier
   HostnameVerifier allHostsValid = new HostnameVerifier() {
       public boolean verify(String hostname, SSLSession session) {
           return true;
       }
   };

   // Install the all-trusting host verifier
   HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
    e.printStackTrace();
}

Eine Datei mit Channel herunterladen

Wenn die Datei bereits existiert, wird sie überschrieben!

String fileName     = "file.zip";                  // name of the file
String urlToGetFrom = "http://www.mywebsite.com/"; // URL to get it from
String pathToSaveTo = "C:\\Users\\user\\";         // where to put it

//If the file already exists, it will be overwritten!
  
//Opening OutputStream to the destination file
try (ReadableByteChannel rbc = 
      Channels.newChannel(new URL(urlToGetFrom + fileName).openStream()) ) {
    try ( FileChannel channel = 
        new FileOutputStream(pathToSaveTo + fileName).getChannel(); ) {
      channel.transferFrom(rbc, 0, Long.MAX_VALUE);
    }
    catch (FileNotFoundException e) { /* Output directory not found */ }
    catch (IOException e)           { /* File IO error */ }
}
catch (MalformedURLException e)     { /* URL is malformed */ }
catch (IOException e)               { /* IO error connecting to website */ }

Anmerkungen

  • Lassen Sie die Fangblöcke nicht leer!
  • Überprüfen Sie im Fehlerfall, ob die Remote-Datei vorhanden ist
  • Dies ist ein Blockierungsvorgang, der bei großen Dateien lange dauern kann


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow