Java进阶学习笔记104——实现一个简易版的BS架构
Java进阶学习笔记
·
要求从浏览器访问服务器
并立即让服务器响应一个很简单的网页给浏览器显示
网页的内容是:“我爱你,中国。”
BS架构的基本原理:
浏览器通过URL统一资源定位符,地址:http://服务器IP:服务器端口找到服务器程序,与服务器建立一个通信管理,响应浏览器请求的数据。
BS架构的基本原理:

注意:服务器必须给浏览器响应HTTP协议规定的数据格式,否则浏览器不识别返回的数据。
HTTP协议规定:响应给浏览器的数据格式必须满足如下格式:

代码:
Server:
package cn.chang.d8_tcp5;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 目标:完成TCP通信快速入门—服务端开发,要求实现与多个客户端同时通信
*/
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("===服务端启动成功===");
// 1. 创建ServerSocket的对象,同时为服务端注册端口,方便客户端程序找到它
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
// 2. 需要使用serverSocket对象调用accept方法等待客户端的连接请求
Socket socket = serverSocket.accept(); // 端到端的通信管道
System.out.println("有人上线了!" + socket.getRemoteSocketAddress());
// 3. 把这个客户端对应的socket通信管道交给一个独立的线程负责处理。
new ServerReaderThread(socket).start();
}
}
}
ServerReaderThread:
package cn.chang.d8_tcp5;
import java.io.*;
import java.net.Socket;
public class ServerReaderThread extends Thread{
private Socket 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("<div style='color:red;font-size:14px;text-align:center;'>我爱你,中国</div>");
ps.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
启动服务器,然后使用浏览器进行访问:

扩展知识:
每次请求都开一个新线程,到底好不好?
高并发的时候,容易死机。
10万个并发,那就产生10万个线程,线程是占用资源的,那么就容易宕机。
我们可以使用线程池进行优化。

复用线程,让线程可以处理另外一个管道的任务。
固定了线程池的线程和任务数量。
代码:
Server类:
package cn.chang.d9_tcp6;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
/**
* 目标:完成TCP通信快速入门—服务端开发,要求实现与多个客户端同时通信
*/
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("===服务端启动成功===");
// 1. 创建ServerSocket的对象,同时为服务端注册端口,方便客户端程序找到它
ServerSocket serverSocket = new ServerSocket(8080);
// 创建出一个线程池,负责处理通信管道的任务
ThreadPoolExecutor pool = new ThreadPoolExecutor(32, 32, 0,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(8),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
while (true) {
// 2. 需要使用serverSocket对象调用accept方法等待客户端的连接请求
Socket socket = serverSocket.accept(); // 端到端的通信管道
// 3. 把这个客户端对应的socket通信管道交给一个独立的线程负责处理。
pool.execute(new ServerReaderRunnable(socket));
}
}
}
ServerReaderRunnable类:
package cn.chang.d9_tcp6;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
public class ServerReaderRunnable implements Runnable {
private Socket 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("<div style='color:red;font-size:14px;text-align:center;'>我爱你,中国</div>");
ps.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行结果:

可以反复把网络通信这部分内容好好练习练习,消化一下。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)