java网络编程——多线程数据收发并行
数小钱钱的种花兔 人气:8
## 基本介绍与思路
#### 收发并行
前一篇博客中,完成了客户端与服务端的简单TCP交互,但这种交互是触发式的:客户端发送一条消息,服务端收到后再回送一条。没有做到收发并行。收发并行的字面意思很容易理解,即数据的发送与接收互相不干扰,相互独立。当然,要保证服务端和客户端都能做到收发并行。
#### 业务逻辑
脱离业务逻辑的实践是毫无意义的,先描述一下本实践中的业务逻辑:一个服务端接受多个客户端的连接,连接后,向各个客户端定时发送时间戳数据,同时在并行条件下,接受各个客户端发送来的数据并显示;客户端键盘输入字符串,发送给服务端,同时在并行条件下,接收服务器发来的时间戳数据并显示。
#### 实现思路
实现发送与接收并行,思路其实非常直观,即建立两个线程,分别用来实现输入流和输出流。我的代码的设计方案如下图所示:
![image](http://qiniu.debrisflow.cn/20200317diagram.png)
- 服务端:创建一个监听客户端连接的线程,线程中一旦接收到请求,创建一个对应该客户端收发处理的对象,对象中创建输入流线程,并使用单例线程池创建输出流线程。主线程使用键盘输入流System.in来进行阻塞。同时主线程中创建Timer定时器,定时向输出流发送数据。
- 客户端:主线程发送连接请求,与服务器建立连接。使用键盘输入流System.in来阻塞主线程,同时作为输出流使用;创建一个输入流线程,异步运行,接收服务器数据。
## 代码分析
源代码文件结构如下图所示
![image](http://qiniu.debrisflow.cn/20200317projectStructure.jpg)
#### 服务端
服务器端分为三个部分,分别是Server.java,TCPServer.java和ClientHandler.java
###### Server.java
```
package Server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.TimerTask;
import java.util.Timer;
import java.util.Date;
public class Server {
private static SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd_HH:mm:ss");
public static void main(String[] args){
try {
TCPServer.accept();
new Timer("Timer").schedule(new TimerTask() {
@Override
public void run() {
TCPServer.broadcast(df.format(new Date()));
}
}, 1000,5000);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String str;
//因为ClientListen是异步线程,使用键盘输入流将主线程阻塞住,保证跟ClientListen线程同步,同时可控制ClientListen服务的退出
do{
str = bufferedReader.readLine();
}while (str.equalsIgnoreCase("serverExit"));
}catch (Exception e){
System.out.println("监听请求过程中异常退出");
}
try {
TCPServer.stop();
} catch (IOException e) {
System.out.println("关闭套接字过程中出现异常");
} finally {
System.out.println("服务器端套接字已关闭!");
}
}
}
```
###### TCPServer.java
```
package Server;
import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.UUID;
class TCPServer {
private static int LOCAL_PORT = 3001;
private static ClientListenHandle clientListenHandle;
private static ArrayList
加载全部内容