杰瑞科技汇

java linux socket

Of course! This is a classic and powerful combination. Let's break down how to use Java Sockets on a Linux system, covering the core concepts, a complete client-server example, and important Linux-specific considerations.

java linux socket-图1
(图片来源网络,侵删)

Core Concepts: The Client-Server Model

Socket communication in Java (and most networking) follows a client-server model.

  • Server (The Listener):

    1. A server application creates a ServerSocket and "binds" it to a specific IP address and a port number. This makes it listen for incoming connection requests on that port.
    2. The server calls accept(). This method blocks (waits) until a client tries to connect.
    3. When a client connects, accept() returns a new Socket object that represents the specific connection to that client. The original ServerSocket continues listening for new clients.
    4. The server uses the new Socket's InputStream to read data from the client and its OutputStream to send data back.
  • Client (The Initiator):

    1. A client application creates a Socket object, specifying the server's IP address (or hostname) and the port number it wants to connect to.
    2. The Socket constructor attempts to establish a connection to the server. This call blocks until the connection is made or it fails.
    3. Once connected, the client uses the Socket's OutputStream to send data to the server and its InputStream to read data back.

Key Java Classes:

java linux socket-图2
(图片来源网络,侵删)
  • java.net.ServerSocket: For the server to listen for connections.
  • java.net.Socket: For both client and server ends of a connection.
  • java.io.InputStream / java.io.OutputStream: For low-level byte-based communication.
  • java.io.BufferedReader / java.io.PrintWriter: For convenient, high-level, text-based communication (recommended for most cases).

Step-by-Step Code Example

Let's create a simple "Echo Server" that receives a message from a client and sends it back.

The Server (EchoServer.java)

This server will listen on port 6789. It will handle one client at a time.

// EchoServer.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
    public static void main(String[] args) {
        int port = 6789;
        // The try-with-resources statement ensures the ServerSocket is closed automatically.
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server is listening on port " + port);
            // The accept() method waits until a client connects.
            // It returns a Socket object representing the connection to the client.
            Socket clientSocket = serverSocket.accept();
            System.out.println("Client connected: " + clientSocket.getInetAddress().getHostAddress());
            // Set up streams for communication with the client
            // PrintWriter for sending messages (autoFlush=true is important!)
            PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
            // BufferedReader for reading messages
            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);
                out.println("Server: " + inputLine); // Echo back the message
            }
            System.out.println("Client disconnected.");
        } catch (IOException e) {
            System.out.println("Server exception: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

The Client (EchoClient.java)

This client will connect to the server (which can be on the same machine or another) and send a message.

// 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"; // Use the server's IP address if it's remote
        int port = 6789;
        // The try-with-resources statement ensures the socket and streams are closed.
        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 echo server.");
            System.out.println("Type a message and press Enter. Type 'exit' to quit.");
            String userInput;
            // Read from user input, send to server, and print the server's response
            while ((userInput = stdIn.readLine()) != null) {
                if ("exit".equalsIgnoreCase(userInput)) {
                    break;
                }
                out.println(userInput); // Send user input to the server
                System.out.println("Echo from server: " + in.readLine()); // Read and print the server's reply
            }
        } 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);
            System.exit(1);
        }
    }
}

How to Run on Linux

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

    java linux socket-图3
    (图片来源网络,侵删)
  2. Compile the Java Code: Open a terminal and run the Java compiler:

    javac EchoServer.java EchoClient.java

    This will create EchoServer.class and EchoClient.class.

  3. Run the Server: In your terminal, start the server. It will now be listening on port 6789.

    java EchoServer

    You should see the output: Server is listening on port 6789. The terminal will now be blocked, waiting for a connection.

  4. Run the Client (in a new terminal): Open a new terminal window. Now, run the client application.

    java EchoClient

    You will see: Connected to the echo server. and a prompt to type a message.

  5. Test the Communication:

    • In the client's terminal, type a message and press Enter.
      Hello, Server!
    • The client will immediately receive and display the echo:
      Echo from server: Server: Hello, Server!
    • In the server's terminal, you will see:
      Received from client: Hello, Server!
    • Type exit in the client terminal to close the connection. The server will print Client disconnected. and will be ready for a new connection.

Linux-Specific Considerations

A. Port Numbers and Permissions

  • Well-Known Ports (0-1023): On Linux, binding to ports below 1024 requires root privileges. This is a security measure to prevent regular users from running services on standard ports like 80 (HTTP) or 22 (SSH).

    • If you try to run your server on port 80 as a regular user, you'll get a java.net.BindException: Permission denied.
    • Solution: Either use a port number above 1024 (like 6789 in our example) or run your server with sudo.
  • Port Already in Use: If you try to run your server and another application is already using port 6789, you'll get a java.net.BindException: Address already in use.

    • How to find what's using the port:
      # The -t flag for TCP, -n for numeric addresses, -l for listening
      sudo netstat -tulpn | grep :6789
      # Or using the newer ss command
      sudo ss -tulpn | grep :6789
    • How to kill the process (replace <PID> with the Process ID from the command above):
      sudo kill -9 <PID>

B. Firewalls

Your Linux machine's firewall will block incoming connection requests on any port by default. You need to create a rule to allow traffic on your chosen port.

  • ufw (Uncomplicated Firewall - common on Ubuntu/Debian):

    # Allow traffic on TCP port 6789
    sudo ufw allow 6789/tcp
    # To check the rules
    sudo ufw status
    # To delete the rule later
    sudo ufw delete allow 6789/tcp
  • firewalld (common on CentOS/RHEL/Fedora):

    # Add a permanent rule to allow traffic on port 6789
    sudo firewall-cmd --permanent --add-port=6789/tcp
    # Reload the firewall to apply the new rule
    sudo firewall-cmd --reload
    # To check the rules
    sudo firewall-cmd --list-all

C. IP Address Binding

In our server example, we used new ServerSocket(port). This makes the server listen on all available network interfaces (e.g., 0.0.1, 168.1.100, etc.).

If you want your server to be accessible only from the local machine, you can bind it to 0.0.1:

// Listen only on localhost
try (ServerSocket serverSocket = new ServerSocket(port, 50, InetAddress.getByName("127.0.0.1"))) {
    // ...
}

This is more secure if you don't need external access.

Going Further: Multi-threading

The simple server above can only handle one client at a time. If a client connects, all other clients have to wait. For a real-world application, you need a multi-threaded server.

A common pattern is:

  1. The main thread creates a ServerSocket and enters an infinite accept() loop.
  2. For each new client connection accepted, the main thread creates a new Thread (or a Runnable task) to handle that specific client's communication.
  3. The main thread immediately goes back to listening for the next client.

This way, each client gets its own thread, and the server can handle many clients concurrently.

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