網頁

2020/6/15

Java Socket 範例

Java Socket Client與Server溝通範例。

範例環境:

  • Java 8
  • Maven

本範例建立兩個Java Maven (Quickstart Archetype)應用程式專案,分別代表Socket Client與Socket Server。


Client與Server的pom.xml設定如下,重點在maven-jar-plugin用來打包成可執行的jar檔的相關設定。

Socket Client - pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.abc.demo</groupId>
    <artifactId>socket-client</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>socket-client</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>socket-client</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <addClasspath>true</addClasspath>
                                <mainClass>com.abc.demo.App</mainClass> <!-- main類別的full qualified name -->
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

Socket Server - pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.abc.demo</groupId>
    <artifactId>socket-server</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>socket-server</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>socket-server</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <addClasspath>true</addClasspath>
                                <mainClass>com.abc.demo.App</mainClass> <!-- main類別的full qualified name -->
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

Client與Server皆只有一支App.java,為程式的main進入點及處理Socket溝通的邏輯。


Socket Client - App.java

package com.abc.demo;

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

public class App {

    private static final String HOST = "127.0.0.1"; // Socket Server IP
    private static final int PORT = 5000; // Socket Server port

    public static void main(String[] args) throws IOException {
        new SocketClient(HOST, PORT);
    }

    static class SocketClient {

        SocketClient(String host, int port) {
            System.out.println("Socket Client starting...");

            try (
                    Socket socket = new Socket(host, port);
                    PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            ) {
                System.out.println("Socket connected, host=" + host + ", port=" + port);

                BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
                String serverMessage = "";
                String userInput;
                while ((userInput = stdIn.readLine()) != null) {
                    if ("exit".equalsIgnoreCase(userInput)) {
                        break;
                    }
                    System.out.println("User input: " + userInput);
                    out.println(userInput);
                    serverMessage = in.readLine();
                    System.out.println("Socket Server: " + serverMessage);
                }
                System.out.println("Socket closed.");
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }
}



Socket Server - App.java

package com.abc.demo;

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

public class App {

    private static final int PORT = 5000;

    public static void main(String[] args) {
        new SocketServer(PORT);
    }

    static class SocketServer {

        SocketServer(int port) {
            System.out.println("Socket Server starting...");
            try (
                    ServerSocket serverSocket = new ServerSocket(port);
                    Socket clientSocket = serverSocket.accept(); // 監聽Client的Socket請求
                    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
                    BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            ) {
                System.out.println("Socket Server started, port=" + PORT);
                String inputLine, outputLine;
                while ((inputLine = in.readLine()) != null) {
                    System.out.println("Socket Client: " + inputLine);
                    if ("exit".equalsIgnoreCase(inputLine)) {
                        break;
                    }

                    outputLine = inputLine + " - from Socket Server";
                    out.println(outputLine);
                }
                System.out.println("Socket Server closed");
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }
}

完成以上後,使用Maven將兩專案打包成可執行的jar檔,可在Client專案目錄的target資料夾找到socket-client.jar,及在Server專案目錄的target找到socket-server.jar

在cmd或terminal分別用下指令執行兩個jar檔。先啟動Socket Server,然後再啟動Socket Client。

Socket Server

$ java -jar socket-server.jar
Socket Server starting...

Socket Client

$ java -jar socket-client.jar
Socket Client starting...
Socket connected, host=127.0.0.1, port=5000

然後在Client的命令視窗輸入一些文字,例如hello world。

Socket Client

hello world
User input: hello world
Socket Server: hello world - from Socket Server

Server會接收來自Client的輸入,然後會在命令視窗顯示如下。

Socket Server

Socket Server started, port=5000
Socket Client input: hello world

在Client輸入exit可結束執行。

Socket Client

exit
Socket closed.

參考GitHub:ClientServer


沒有留言:

張貼留言