WHCSRL 技术网

网络通信——TCP模拟B/S服务器

目录

目标

实现

服务端代码

回写页面

访问结果

问题及分析

优化与改进


目标

通过在本地电脑开放一个服务端,让其可以在浏览器中被访问

实现

服务端代码

  1. import java.io.*;
  2. import java.net.ServerSocket;
  3. import java.net.Socket;
  4. import java.nio.charset.StandardCharsets;
  5. public class TCPServer {
  6. public static void main(String[] args) throws IOException {
  7. //创建服务端并指定端口号
  8. ServerSocket server = new ServerSocket(8080);
  9. //使用accept方法获取到请求的客户端对象(浏览器)
  10. Socket socket = server.accept();
  11. //获取网络字节输入流
  12. InputStream is = socket.getInputStream();
  13. //将网络字节输入流转换为字符缓存流
  14. BufferedReader br=new BufferedReader(new InputStreamReader(is));
  15. //把客户端请求信息的第一行读出 GET /JAVA_Projrct/web/index.html HTTP/1.1
  16. String line = br.readLine();
  17. System.out.println(line);
  18. //把读取的信息进行切割,只要中间部分/JAVA_Projrct/web/index.html
  19. String[] s = line.split(" ");
  20. //去掉前面的‘/’,获得JAVA_Projrct/web/index.html
  21. String substring = s[1].substring(1);
  22. //转换为相对路径 ./web/index.html
  23. String path="./"+substring.substring(12);
  24. //创建本地的字节输入流
  25. FileInputStream fis = new FileInputStream(path);
  26. //获取网络字节输出流
  27. OutputStream os = socket.getOutputStream();
  28. //写入HTTP协议响应头(固定格式)
  29. os.write("HTTP/1.1 200 OK ".getBytes(StandardCharsets.UTF_8));
  30. os.write("Content-Type:text/html ".getBytes(StandardCharsets.UTF_8));
  31. //必须写入空行,否则浏览器不解析
  32. os.write(" ".getBytes(StandardCharsets.UTF_8));
  33. int len=0;
  34. byte[] bytes = new byte[1024];
  35. while ((len=fis.read(bytes))!=-1){
  36. os.write(bytes,0,len);
  37. }
  38. //释放资源
  39. fis.close();
  40. socket.close();
  41. server.close();
  42. }
  43. }

回写页面

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1">
  7. <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
  8. <title>欢迎光临</title>
  9. </head>
  10. <body>
  11. <div>
  12. <h1>
  13. <center>你好朋友</center>
  14. </h1>
  15. </div>
  16. <div>
  17. <center>
  18. <img src="image/图片.jpg" alt="图片">
  19. </center>
  20. </div>
  21. </body>
  22. </html>

访问结果

问题及分析

可以发现页面中的图片并未加载出来,这是由于服务器再解析图片信息时需要单独另开启一个线程,这就需要我们的服务器端一直保持监听状态去保证线程的进行

优化与改进

利用while死循环使服务端一直保持监听状态;利用线程优化多次请求时的响应速度

  1. import java.io.*;
  2. import java.net.ServerSocket;
  3. import java.net.Socket;
  4. import java.nio.charset.StandardCharsets;
  5. public class TCPServer {
  6. public static void main(String[] args) throws IOException {
  7. //创建服务端并指定端口号
  8. ServerSocket server = new ServerSocket(8080);
  9. //让服务端一直保持监听状态
  10. while (true) {
  11. //使用accept方法获取到请求的客户端对象(浏览器)
  12. Socket socket = server.accept();
  13. new Thread(() -> {
  14. try {
  15. //获取网络字节输入流
  16. InputStream is = socket.getInputStream();
  17. //将网络字节输入流转换为字符缓存流
  18. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  19. //把客户端请求信息的第一行读出 GET /JAVA_Projrct/web/index.html HTTP/1.1
  20. String line = br.readLine();
  21. System.out.println(line);
  22. //把读取的信息进行切割,只要中间部分/JAVA_Projrct/web/index.html
  23. String[] s = line.split(" ");
  24. //去掉前面的‘/’,获得JAVA_Projrct/web/index.html
  25. String substring = s[1].substring(1);
  26. //转换为相对路径 ./web/index.html
  27. String path = "./" + substring.substring(12);
  28. //创建本地的字节输入流
  29. FileInputStream fis = new FileInputStream(path);
  30. //获取网络字节输出流
  31. OutputStream os = socket.getOutputStream();
  32. //写入HTTP协议响应头(固定格式)
  33. os.write("HTTP/1.1 200 OK ".getBytes(StandardCharsets.UTF_8));
  34. os.write("Content-Type:text/html ".getBytes(StandardCharsets.UTF_8));
  35. //必须写入空行,否则浏览器不解析
  36. os.write(" ".getBytes(StandardCharsets.UTF_8));
  37. int len = 0;
  38. byte[] bytes = new byte[1024];
  39. while ((len = fis.read(bytes)) != -1) {
  40. os.write(bytes, 0, len);
  41. }
  42. //释放资源
  43. fis.close();
  44. socket.close();
  45. } catch (IOException e) {
  46. e.printStackTrace();
  47. }
  48. }).start();
  49. }
  50. }
  51. }

可见,图片也顺利加载出来了! 

推荐阅读