TCP案例之单聊与群聊
一、TCP案例之单聊
在基于TCP协议的单聊应用中,通常涉及客户端和服务器端的交互。
服务器端
- 建立服务器 :
- 服务器端创建一个TCP Socket并绑定到一个特定的端口,开始监听来自客户端的连接请求。
- 接受连接 :
- 服务器端接受客户端的连接请求,建立TCP连接。
- 接收消息 :
- 服务器端接收客户端发送的消息数据。
- 处理消息 :
- 服务器端处理接收到的消息,可以进行消息转发、存储、验证等操作。
- 发送响应 :
- 服务器端可以向客户端发送响应,如确认消息接收、错误提示等。
客户端
- 建立连接 :
- 客户端创建一个TCP Socket并连接到服务器端的IP地址和端口。
- 发送消息 :
- 客户端向服务器端发送消息数据。
- 接收响应 :
- 客户端接收服务器端的响应数据。
- 处理响应 :
- 客户端处理接收到的响应,可以展示在界面上或者进行其他操作。
- 关闭连接 :
- 客户端和服务器端在通信结束后关闭连接。
示例场景
- Alice和Bob是两个用户,他们分别运行客户端应用程序。
- 服务器端监听在特定端口上,等待客户端连接。
- Alice连接到服务器端,发送一条消息给Bob。
- 服务器端接收Alice的消息,转发给Bob。
- Bob接收到消息后可以进行回复,服务器再将消息转发给Alice。
示例代码
客服端:
java
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
/**
* 知识点:TCP案例 之 优化单聊
*/
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 9082);
new ReceiveThread(socket).start();
Scanner scan = new Scanner(System.in);
PrintStream ps = new PrintStream(socket.getOutputStream());
while(true){
ps.println("小雷:" + scan.next());
}
}
}
服务器端:
java
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(9082);
Socket socket = server.accept();
new ReceiveThread(socket).start();
Scanner scan = new Scanner(System.in);
PrintStream ps = new PrintStream(socket.getOutputStream());
while(true){
ps.println("小杨:" + scan.next());
}
}
}
接收线程(相当于中转站):
java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
public class ReceiveThread extends Thread{
private Socket socket;
public ReceiveThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
while(true){
String readLine = br.readLine();
System.out.println(readLine);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
二、TCP案例之群聊
基于TCP协议的群聊应用涉及多个客户端与服务器之间的交互,实现了群组内的消息广播功能。
服务器端
- 建立服务器 :
- 服务器端创建一个TCP Socket并绑定到一个特定的端口,开始监听来自客户端的连接请求。
- 接受连接 :
- 服务器端接受客户端的连接请求,建立TCP连接。
- 加入群组 :
- 客户端可以向服务器发送加入群组的请求,服务器更新群组成员列表。
- 接收消息 :
- 服务器端接收客户端发送的消息数据。
- 消息广播 :
- 服务器端将接收到的消息广播给所有群组成员。
- 处理退出 :
- 客户端可以发送退出群组的请求,服务器更新群组成员列表并通知其他成员。
客户端
- 建立连接 :
- 客户端创建一个TCP Socket并连接到服务器端的IP地址和端口。
- 加入群组 :
- 客户端向服务器发送加入群组的请求。
- 发送消息 :
- 客户端向服务器发送消息数据。
- 接收广播 :
- 客户端接收服务器端广播的消息数据。
- 处理消息 :
- 客户端展示接收到的消息数据。
- 退出群组 :
- 客户端可以发送退出群组的请求。
示例场景
- 服务器端维护一个群组成员列表,包括Alice、Bob、Charlie等用户。
- Alice、Bob、Charlie分别连接到服务器端,加入群组。
- Alice发送一条消息给所有群组成员。
- 服务器端接收Alice的消息,将消息广播给Bob、Charlie等成员。
- Bob和Charlie接收到消息后可以进行回复或者其他操作。
- Bob决定退出群组,发送退出请求给服务器端。
示例代码
服务器端:
java
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
/**
* 知识点:TCP案例 之 群聊
*/
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 7080);
new ReceiveThread(socket).start();
Scanner scan = new Scanner(System.in);
PrintStream ps = new PrintStream(socket.getOutputStream());
while(true){
ps.println("小杨:" + scan.next());
}
}
}
服务器端:
java
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
public class Server {
public static final ConcurrentHashMap<String, PrintStream> map = new ConcurrentHashMap<>();
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(7080);
while(true){
Socket socket = server.accept();
String ip = socket.getInetAddress().toString();
PrintStream ps = new PrintStream(socket.getOutputStream());
map.put(ip, ps);
new ServerThread(socket).start();
}
}
}
服务器线程:
java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.Map.Entry;
import java.util.Set;
public class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//接受当前客户端的消息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
while(true){
String readLine = br.readLine();
System.out.println(readLine);
//发送给其他客户端消息
Set<Entry<String,PrintStream>> entrySet = Server.map.entrySet();
for (Entry<String, PrintStream> entry : entrySet) {
String ip = entry.getKey();
PrintStream ps = entry.getValue();
if(!socket.getInetAddress().toString().equals(ip)){
ps.println(readLine);
}
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
接受线程:
java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
public class ReceiveThread extends Thread{
private Socket socket;
public ReceiveThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
while(true){
String readLine = br.readLine();
System.out.println(readLine);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
TCP群聊理解图 :