杰瑞科技汇

Java中TCP Socket如何实现通信?

Of course! Here is a comprehensive guide to using TCP sockets in Java, covering both the server and client sides, with detailed explanations and complete, runnable code examples.

Java中TCP Socket如何实现通信?-图1
(图片来源网络,侵删)

What is a TCP Socket?

A socket is one endpoint of a two-way communication link between two programs running on the network. The TCP (Transmission Control Protocol) is a connection-oriented protocol, meaning it establishes a reliable, ordered, and error-checked connection before any data is sent.

Think of it like a phone call:

  1. Dialing (Client connects to Server): The client tries to establish a connection.
  2. Answering (Server accepts connection): The server "picks up the phone."
  3. Conversation (Data Exchange): Both parties can send and receive messages.
  4. Hanging Up (Closing the connection): Either party can end the call.

Core Java Classes for TCP Sockets

Java's networking API is primarily in the java.net package.

Class Role
java.net.ServerSocket Used by the server to listen for incoming client connections. It's like a receptionist waiting for calls.
java.net.Socket Represents the connection between the client and the server. Once a connection is established, both the client and server use a Socket object to send and receive data.
java.net.InetAddress Represents an IP address. You use it to specify the host (e.g., "localhost", "127.0.0.1", or a domain name) to connect to.
java.io.InputStream / java.io.OutputStream Used for reading bytes from and writing bytes to the socket's connection.
java.io.BufferedReader / java.io.PrintWriter More convenient, higher-level classes for reading text lines and writing text, respectively. They are often "wrapped" around the stream from the socket.

The Server Side (ServerSocket)

The server's job is to wait for a client to connect and then handle that connection.

Java中TCP Socket如何实现通信?-图2
(图片来源网络,侵删)

Steps for the Server:

  1. Create a ServerSocket: Specify a port number (e.g., 1234). The server will listen on this port.
  2. Accept a Connection: Call serverSocket.accept(). This method blocks (pauses the program) until a client connects. When a client connects, it returns a Socket object representing the connection to that specific client.
  3. Set up I/O Streams: Get the InputStream and OutputStream (or more commonly, BufferedReader and PrintWriter) from the returned Socket.
  4. Communicate: Use the streams to read data from the client and send data back.
  5. Close the Connection: Close the Socket and the streams when done.

Complete Server Code (EchoServer.java)

This server will listen for a client, receive a message, print it, and send back an acknowledgment.

// EchoServer.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
    public static void main(String[] args) {
        int port = 1234; // The port number the server will listen on
        // Using try-with-resources to automatically close the ServerSocket
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server is listening on port " + port);
            // The accept() method waits (blocks) until a client connects
            Socket clientSocket = serverSocket.accept();
            System.out.println("Client connected: " + clientSocket.getInetAddress().getHostAddress());
            // Set up I/O streams
            // PrintWriter for sending text to the client
            PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
            // BufferedReader for reading text from the client
            BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            String inputLine;
            // Read from the client until the client closes the connection
            while ((inputLine = in.readLine()) != null) {
                System.out.println("Received from client: " + inputLine);
                // Send a response back to the client
                out.println("Server: Message received -> " + inputLine);
            }
            System.out.println("Client disconnected.");
        } catch (IOException e) {
            System.out.println("Server exception: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

The Client Side (Socket)

The client's job is to initiate a connection to the server and then communicate.

Steps for the Client:

  1. Create a Socket: Specify the server's IP address (or hostname) and port number. This constructor blocks until the connection is successfully established or an exception is thrown.
  2. Set up I/O Streams: Get the InputStream and OutputStream from the Socket.
  3. Communicate: Use the streams to send data to the server and read data back.
  4. Close the Connection: Close the Socket and the streams when done.

Complete Client Code (EchoClient.java)

This client will connect to the server, send a message, and read the server's response.

// EchoClient.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class EchoClient {
    public static void main(String[] args) {
        String hostname = "localhost"; // The server's address
        int port = 1234;             // The port the server is listening on
        // Using try-with-resources to automatically close the socket and streams
        try (
            Socket socket = new Socket(hostname, port);
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))
        ) {
            System.out.println("Connected to the server.");
            System.out.print("Enter a message (or 'exit' to quit): ");
            String userInput;
            // Read from the user's console
            while ((userInput = stdIn.readLine()) != null) {
                if ("exit".equalsIgnoreCase(userInput)) {
                    break;
                }
                // Send the user's message to the server
                out.println(userInput);
                // Read the server's response
                String response = in.readLine();
                System.out.println("Server response: " + response);
                System.out.print("Enter a message (or 'exit' to quit): ");
            }
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host " + hostname);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to " +
                hostname + ". Is the server running?");
            System.exit(1);
        }
    }
}

How to Run the Example

  1. Save the files: Save the two code blocks above as EchoServer.java and EchoClient.java in the same directory.

    Java中TCP Socket如何实现通信?-图3
    (图片来源网络,侵删)
  2. Compile the code: Open a terminal or command prompt in that directory and run the Java compiler.

    javac EchoServer.java EchoClient.java
  3. Run the Server: In the same terminal, start the server. It will wait for a connection.

    java EchoServer

    You should see the output: Server is listening on port 1234

  4. Run the Client: Open a new terminal or command prompt (leave the server running in the first one). Start the client.

    java EchoClient

    You should see: Connected to the server. followed by the prompt Enter a message (or 'exit' to quit):

  5. Interact:

    • Type a message in the client's terminal and press Enter.
    • The server's terminal will print the received message.
    • The client's terminal will print the server's response.
    • Type exit in the client's terminal to close the connection and exit the program.
    • The server will then print Client disconnected. and will wait for a new connection.

Important Considerations and Best Practices

  1. Blocking I/O: The basic Socket and ServerSocket use blocking I/O. The accept() and read() methods pause the program until an event occurs. This is simple but inefficient for handling many clients simultaneously. For real-world applications, you would typically use:

    • Multithreading: Create a new thread for each client connection.
    • Non-blocking I/O (java.nio): A more scalable, modern approach.
    • Asynchronous I/O (CompletableFuture, AsSocketChannel): A more advanced, event-driven model.
  2. Resource Management: Network resources (sockets, streams) are limited and must be closed properly. The try-with-resources statement is the best way to ensure this happens automatically, even if exceptions occur.

  3. Ports: Ports below 1024 are "privileged" and usually require administrator rights to bind to. Use ports from 1024 to 49151 for applications.

  4. Data Serialization: The examples above send simple text (strings). If you need to send complex objects (like custom classes), you should use ObjectOutputStream and ObjectInputStream. The classes you send must implement the Serializable interface.

分享:
扫描分享到社交APP
上一篇
下一篇