首先了解 Socket
实现步骤
- 创建工程(2个程序)
- Maven配置
- 服务端实现
a. 准备 ServerSocket 对象
b. 接受客户端连接,Socket 对象
c. 接收数据,发送数据 - 客户端实现
a. 准备 ServerSocket 对象,连接到服务器
b. 发送数据,接收数据 - 配置Maven项目,变成可执行的Java程序
单线程
- 功能
服务器
客户端 - 业务
客户端发数据给服务器,服务器接收数据,并打印
服务器响应数据给客户端,客户端接收数据,并打印 - 技术
服务器:ServerSocket 类
客户端:Socket 类
服务器程序,客户端程序
JKD8、Maven 管理
多线程
功能
- 服务器(注册、私聊、群聊、退出)
- 客户端(发送聊天信息、接收聊天信息)
业务
服务端:
- 管理注册的用户
- 私聊对象发送数据
- 在线用户发数据
- 退出时用户删除掉
客户端:
- 交互式输出数据
- 输出服务器响应的数据
技术
- 服务器:ServerSocket 类
- 客户端:Socket 类
- 服务器程序
- 客户端程序 JKD8、Maven 管理
- 多线程处理
一个客户端一个服务器
一个客户端多个服务器
代码
配置maven
客户端
ChatRoomClient
<?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">
<parent>
<artifactId>ChatRoom</artifactId>
<groupId>com.github</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ChatRoomClient</artifactId>
<packaging>jar</packaging>
<description>聊天室的客户端程序</description>
<!--配置程序打包输出可执行的jar-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<!--Java 打包规范中的内容-->
<manifest>
<mainClass>com.github.chatroom.client.multi.MultiThreadClient</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
服务器
ChatRoomServer
<?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">
<parent>
<artifactId>ChatRoom</artifactId>
<groupId>com.github</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ChatRoomServer</artifactId>
<packaging>jar</packaging>
<description>聊天室的服务端程序</description>
<!--配置程序打包输出可执行的jar-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<!--Java 打包规范中的内容-->
<manifest>
<mainClass>com.github.chatroom.server.multi.MultiThreadServer</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
父类maven
ChatRoom
<?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.github</groupId>
<artifactId>ChatRoom</artifactId>
<version>1.0.0</version>
<modules>
<module>ChatRoomServer</module>
<module>ChatRoomClient</module>
</modules>
<packaging>pom</packaging>
<description>聊天室的父工程</description>
<!--配置项目属性-->
<properties>
<encoding>UTF-8</encoding>
<java.version>1.8</java.version>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.source>${java.version}</maven.compiler.source>
</properties>
</project>
单线程
SingleThreadClient.java
package com.github.chatroom.client.single;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class SingleThreadClient {
public static void main(String[] args) {
try {
// 0. 通过命令行获取参数
int port = 1234;
if(args.length > 0) {
try {
port = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.out.println("端口参数不正确,采用默认端口" + port);
}
}
String host = "127.0.0.1";
if (args.length > 1) {
host = args[1];
// host 格式化校验
}
// 1. 创建客户端,连接到服务器
Socket clientSocket = new Socket(host,port);
// 2. 发送数据,接收数据
// 2.1 发送数据
OutputStream clientOutput = clientSocket.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(clientOutput);
writer.write("您好,我是客户端\n");
writer.flush();
// 2.2 接收数据
InputStream clientInput = clientSocket.getInputStream();
Scanner scanner = new Scanner(clientInput);
String serverData = scanner.nextLine();
System.out.println("来自服务器的数据:" + serverData);
// 3. 客户端关闭
clientOutput.close();
clientInput.close();
clientSocket.close();
System.out.println("客户端关闭");
} catch (IOException e) {
e.printStackTrace();
}
}
}
SingleThreadServer.java
package com.github.chatroom.server.single;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* 单线程聊天室服务端程序
* Author: zsm
* Created: 2019/4/24
*/
public class SingleThreadServer {
public static void main(String[] args) {
try {
// 0. 通过命令行获取服务器端口
int port = 1234;
if(args.length > 0) {
try {
port = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.out.println("端口参数不正确,采用默认端口" + port);
}
}
// 1. 创建ServerSocket
ServerSocket serverSocket = new ServerSocket(port); //给端口号
System.out.println("服务器启动:" + serverSocket.getLocalSocketAddress());
// 2. 等待客户端连接
System.out.println("等待客户端连接...");
Socket clientSocket = serverSocket.accept();
System.out.println("客户端信息:" + clientSocket.getRemoteSocketAddress());
// 3. 接收和发送数据
// 3.1 接收
InputStream clientInput = clientSocket.getInputStream();
Scanner scanner = new Scanner(clientInput);
String clientData = scanner.next();
System.out.println("来自客户端的消息:" + clientData);
// 3.2 发送
OutputStream clientOutput = clientSocket.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(clientOutput);
writer.write("您好,欢迎连接到服务器\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
多线程
客户端
ReadDataFromServerThread.java
package com.github.chatroom.client.multi;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.Scanner;
public class ReadDataFromServerThread extends Thread {
private final Socket client;
public ReadDataFromServerThread(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
InputStream clientInput = client.getInputStream();
Scanner scanner = new Scanner(clientInput);
while (true) {
String message = scanner.nextLine();
System.out.println("来自服务器的消息:" + message);
if (message.equals("bye")) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
WriteDataToServerThread.java
package com.github.chatroom.client.multi;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
public class WriteDataToServerThread extends Thread {
private final Socket client;
public WriteDataToServerThread(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
OutputStream clientOutput = client.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(clientOutput);
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入消息:");
String message = scanner.nextLine();
// 给服务器发数据
writer.write(message + "\n");
writer.flush();
if(message.equals("bye")) {
// 表示客户端要关闭
client.close();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
MultiThreadClient.java
package com.github.chatroom.client.multi;
import java.io.IOException;
import java.net.Socket;
public class MultiThreadClient {
public static void main(String[] args) {
try {
// 通过命令行获取参数
int port = 1234;
if(args.length > 0) {
try {
port = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.out.println("端口参数不正确,采用默认端口" + port);
}
}
String host = "127.0.0.1";
if (args.length > 1) {
host = args[1];
// host 格式化校验
}
final Socket socket = new Socket(host,port);
// 1. 往服务器发送数据
new WriteDataToServerThread(socket).start();
// 2. 从服务器读取数据
new ReadDataFromServerThread(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器
MultiThreadServer.java
package com.github.chatroom.server.multi;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 多线程聊天室服务端程序
* Author: zsm
* Created: 2019/4/25
*/
public class MultiThreadServer {
public static void main(String[] args) {
// 通过命令行获取服务器端口
int port = 1234;
if(args.length > 0) {
try {
port = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.out.println("端口参数不正确,采用默认端口" + port);
}
}
final ExecutorService executorService = Executors.newFixedThreadPool(10);
try {
// 配置端口号
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("等待客户端连接...");
// 循环等待用户连接
while (true) {
Socket client = serverSocket.accept();
executorService.submit(new ExecuteClient(client));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码链接
https://github.com/Sasura321/ChatRoom