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.
沒有留言:
張貼留言