TCP实现服务器与客户端的连接(多线程)
程序员文章站
2022-06-06 12:09:56
...
上一篇博客中,我们用TCP实现了服务器与客户端的连接。但是有一个问题,即一个客户端在和服务器交互时,其他客户端无法连接,为解决这一问题,我们将服务器端改造为线程池的版本。
(1)在主线程中服务器只负责接待客户端的请求。接收到客户端的请求后,我们把请求提交至线程池是工作队列中。
public static void main(String[] args) throws IOException {
//创建线程池,大小为10
ExecutorService pool = Executors.newFixedThreadPool (10);
//服务器起一个端口
ServerSocket serverSocket = new ServerSocket (8080);
while(true){
Socket socket = serverSocket.accept ();//接收客户端请求,返回一个socket供通信
pool.execute (new ServerTask(socket));//把任务提交至线程池
}
}
(2)Executors类 的 newFixedThreadPool() 方法,返回一个 ExecutorService 的线程池
- public static ExecutorService newFixedThreadPool( int nThreads )
- 创建一个线程池,该线程池重用固定数量的从共享*队列中运行的线程。
- 在任何时候,最多nThreads线程将处于主动处理任务。 如果所有线程处于活动状态时都会提交其他任务,则它们将等待队列中直到线程可用。
- 如果任何线程由于在关闭之前的执行期间发生故障而终止,则如果需要执行后续任务,则新线程将占用它。
(3)将任务提交至线程池之后,线程池则主动处理任务。
(4)ServerTask 为一个用户自定义类,用来处理任务。
private static class ServerTask implements Runnable{
private Socket socket;
ServerTask(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
InetAddress clientAddress = socket.getInetAddress ();
int clientPort = socket.getPort();
System.out.printf ("有客户端连接上来:%s%d%n",clientAddress,clientPort);
//获取输入字节流(即客户端发送来的消息)
InputStream is = socket.getInputStream ();
//字节流转换为字符流
InputStreamReader isReader = new InputStreamReader (is);
//字符流转换为缓冲字符流
BufferedReader reader = new BufferedReader (isReader);
//输出字符流
OutputStream os = socket.getOutputStream ();
PrintStream out = new PrintStream (os,true,"UTF-8");
while(true){
String line;
while(!(line = reader.readLine ()).isEmpty ()){
System.out.println ("收到消息:" + line);
Scanner sc = new Scanner (System.in);
System.out.print ("请回复:");
String response = sc.nextLine ();
out.println (response);
}
}
} catch (IOException e) {
e.printStackTrace ();
}
}
}
完整程序:
https://github.com/WangWenQian12/Java_Practice/tree/master/JavaSE/IDEA/JavaWeb/TCP2/src
这样我们就实现了多个客户端连接一台服务器的功能。