一、需求描述
实现简易版的B/S架构
1.1 Server
package com.itheima.tcp4;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Server {
//实现简易版的B/S架构
public static void main(String[] args) throws Exception {
System.out.println("----------服务端启动----------");
//创建serversocket对象,同时为服务端程序注册接口
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
//使用serversocket对象调用accept方法,等待客户端连接
Socket socket = serverSocket.accept();
System.out.println("有人上线了:" + socket.getRemoteSocketAddress());
//与客户端建立连接后,将任务交给独立的线程来处理
new ServerReaderThread(socket).start();
}
}
}
1.2 ServerReaderThread
package com.itheima.tcp4;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
public class ServerReaderThread extends Thread {
private Socket socket;
public ServerReaderThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
//响应一个网页内容:“黑马程序员”给浏览器展示
try {
OutputStream os = socket.getOutputStream();
//将字节输出流包装成打印流
PrintStream ps = new PrintStream(os);
ps.println("HTTP/1.1 200 OK");
ps.println("Content-Type:text/html;charset=UTF-8");
ps.println();
ps.println("黑马程序员");
ps.close();
socket.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
1.3 使用线程池进行优化
由于在高并发的情况下,创建太多线程很容易使服务端挂掉,所以用线程池优化B/S架构
1.3.1 Server
package com.itheima.tcp4;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Server {
//实现简易版的B/S架构
public static void main(String[] args) throws Exception {
System.out.println("----------服务端启动----------");
//创建serversocket对象,同时为服务端程序注册接口
ServerSocket serverSocket = new ServerSocket(8080);
//创建一个线程池,负责处理通信管道的任务
ThreadPoolExecutor pool = new ThreadPoolExecutor(16 * 2,16 * 2,0, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(8), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
while (true) {
//使用serversocket对象调用accept方法,等待客户端连接
Socket socket = serverSocket.accept();
System.out.println("有人上线了:" + socket.getRemoteSocketAddress());
//把这个客户端对应的socket通信管道,交给线程池里面的线程负责处理
pool.execute(new ServerReaderRunnable(socket));
}
}
}
1.3.2 ServerReaderRunnable
package com.itheima.tcp4;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
public class ServerReaderRunnable implements Runnable{
private Socket socket;
public ServerReaderRunnable(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
OutputStream os = socket.getOutputStream();
//将字节输出流包装成打印流
PrintStream ps = new PrintStream(os);
ps.println("HTTP/1.1 200 OK");
ps.println("Content-Type:text/html;charset=UTF-8");
ps.println();
ps.println("黑马程序员");
ps.close();
socket.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}