使用了线程池,N客户端--M线程,N可以大于M
利弊:这个虽然使用了线程池,比原始的bio(一个客户端《----》一个线程)更进一步,但是当客户端请求过多时,请求会被放到线程池的队列中,有可能会造成任务阻塞。
Client端代码
package CS.f2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
// 通过构造函数创建Socket,并且连接指定地址和端口的服务端
try {
Socket socket = new Socket(Comm.DEFAULT_SERVER_IP, Comm.DEFAULT_PORT);
System.out.println("请输入信息");
new ReadMsg(socket).start();
PrintWriter pw = null;
// 写数据到服务端
while (true) {
pw = new PrintWriter(socket.getOutputStream());
pw.println(new Scanner(System.in).next());
pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static class ReadMsg extends Thread {
Socket socket;
public ReadMsg(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String line = null;
// 通过输入流读取服务端传输的数据
while ((line = br.readLine()) != null) {
System.out.printf("%s\n", line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务端代码:
package CS.f2;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private static ServerSocket server;
// 线程池,处理每个客户端请求
private static ExecutorService executorService = Executors.newFixedThreadPool(5);
public static void main(String[] args) throws IOException {
start();
}
public static void start() throws IOException {
try {
// 通过构造函数创建ServerSocket
server = new ServerSocket(Comm.DEFAULT_PORT);
System.out.println("服务器已启动,端口号:" + Comm.DEFAULT_PORT);
while (true) {
// 真正处理的还是Socket
Socket socket = server.accept();// 阻塞方法
// 把客户端请求打包成一个任务,放到线程池执行
executorService.execute(new ServerHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (server != null) {
server.close();
}
}
}
}
服务端处理类:真正的任务在这个类处理
package CS.f2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* 处理类
*
*/
public class ServerHandler implements Runnable {
private Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
String message;
String result;
// 通过输入流读取客户端传输的数据
while ((message = br.readLine()) != null) {
System.out.println("server receive data:" + message);
result = response(message);
// 将业务结果通过输出流返回给客户端
pw.println(result);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
socket = null;
}
}
}
// 返回给客户端的应答
public static String response(String msg) {
return "Hello," + msg + ",Now is " + new java.util.Date(System.currentTimeMillis()).toString();
}
}
公共参数类:
package CS.f2;
public class Comm {
public static int DEFAULT_PORT = 8888;
public static String DEFAULT_SERVER_IP = "127.0.0.1";
}