io之socket编程

news/2025/3/19 13:41:50/

写在前面

在这里插入图片描述

本文通过socket编程来实现一个简单的HttpServer。

1:单线程版本

我们使用单线程来实现一个HttpServer,如下:

package dongshi.daddy.io.httpserver;import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;public class HttpServer1 {public static void main(String[] args) throws Exception {ServerSocket serverSocket = new ServerSocket(8801);while (true) {try {Socket socket = serverSocket.accept();service(socket);} catch (Exception e) {e.printStackTrace();}}}private static void service(Socket socket) {String body = "hello,nio1";try {System.out.println("request come!!!");// 模拟耗时操作Thread.sleep(100);PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);// 模拟http的响应,分为响应头和响应体(对象的组成也是头和体,不过是对象头和对象体),其中响应头和响应体通过换行符分割/*** 响应头开始 ***/printWriter.println("HTTP/1.1 200 OK");printWriter.println("Content-Type:text/html;charset=utf-8");// 注意一定要有该内容告知客户端响应体的长度,不然客户端将无法正常读取数据printWriter.println("Content-Length:" + body.getBytes().length);// 空行结束响应头printWriter.println();/*** 响应头结束 ***//*** 响应体开始 ***/printWriter.write(body);/*** 响应体结束 ***/
//            printWriter.flush();printWriter.close();socket.close();} catch (Exception e) {}}
}

curl:

C:\WINDOWS\system32>curl http://localhost:8801
hello,nio1

superbenchmark,即sb压力测试:

D:\>sb -u http://localhost:8801 -c 40 -N 10
Starting at 2023/5/31 星期三 15:48:15
[Press C to stop the test]
92      (RPS: 6.4)
---------------Finished!----------------
Finished at 2023/5/31 星期三 15:48:29 (took 00:00:14.5303526)
102     (RPS: 7)                        Status 200:    102RPS: 9 (requests/second)
Max: 4471ms
Min: 194ms
Avg: 3580.1ms50%   below 4380ms60%   below 4389ms70%   below 4400ms80%   below 4405ms90%   below 4415ms95%   below 4418ms98%   below 4418ms99%   below 4420ms
99.9%   below 4471ms
130     (RPS: 9)

RPS: 9 (requests/second)可以看到处每秒请求数是9,接下来看下多线程版本的性能表现。

2:多线程版本

我们使用多线程来实现一个HttpServer,如下:

package dongshi.daddy.io.httpserver;import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;public class HttpServer2 {public static void main(String[] args) throws Exception {ServerSocket serverSocket = new ServerSocket(8802);while (true) {try {Socket socket = serverSocket.accept();
//                service(socket);new Thread(() -> {service(socket);}).start();} catch (Exception e) {e.printStackTrace();}}}private static void service(Socket socket) {String body = "hello,nio1";try {System.out.println("request come!!!");Thread.sleep(100);PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);// 模拟http的响应,分为响应头和响应体(对象的组成也是头和体,不过是对象头和对象体),其中响应头和响应体通过换行符分割/*** 响应头开始 ***/printWriter.println("HTTP/1.1 200 OK");printWriter.println("Content-Type:text/html;charset=utf-8");// 注意一定要有该内容告知客户端响应体的长度,不然客户端将无法正常读取数据printWriter.println("Content-Length:" + body.getBytes().length);// 空行结束响应头printWriter.println();/*** 响应头结束 ***//*** 响应体开始 ***/printWriter.write(body);/*** 响应体结束 ***/
//            printWriter.flush();printWriter.close();socket.close();} catch (Exception e) {}}
}

superbenchmark,即sb压力测试:

D:\>sb -u http://localhost:8802 -c 40 -N 10
Starting at 2023/5/31 星期三 15:49:33
[Press C to stop the test]
3478    (RPS: 253.3)
---------------Finished!----------------
Finished at 2023/5/31 星期三 15:49:47 (took 00:00:13.9143063)
Status 200:    3444
Status 303:    34RPS: 308.8 (requests/second)
Max: 315ms
Min: 101ms
Avg: 112.8ms50%   below 108ms60%   below 108ms70%   below 109ms80%   below 110ms90%   below 114ms95%   below 124ms98%   below 218ms99%   below 220ms
99.9%   below 238ms

RPS 是308.8,明显好于单线程版本,但是这里是每次创建线程,而创建线程本身因为涉及到底层的操作,所以比较重,我们再改为线程池的版本看下效果。

3:线程池版本

package dongshi.daddy.io.httpserver;import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class HttpServer3 {public static void main(String[] args) throws Exception {ServerSocket serverSocket = new ServerSocket(8803);
//        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);ExecutorService executorService = Executors.newFixedThreadPool(50);while (true) {try {Socket socket = serverSocket.accept();
//                service(socket);executorService.execute(() -> service(socket));} catch (Exception e) {e.printStackTrace();}}}private static void service(Socket socket) {String body = "hello,nio1";try {System.out.println("request come!!!");Thread.sleep(100);PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);// 模拟http的响应,分为响应头和响应体(对象的组成也是头和体,不过是对象头和对象体),其中响应头和响应体通过换行符分割/*** 响应头开始 ***/printWriter.println("HTTP/1.1 200 OK");printWriter.println("Content-Type:text/html;charset=utf-8");// 注意一定要有该内容告知客户端响应体的长度,不然客户端将无法正常读取数据printWriter.println("Content-Length:" + body.getBytes().length);// 空行结束响应头printWriter.println();/*** 响应头结束 ***//*** 响应体开始 ***/printWriter.write(body);/*** 响应体结束 ***/
//            printWriter.flush();printWriter.close();socket.close();} catch (Exception e) {}}
}

superbenchmark,即sb压力测试:

D:\>sb -u http://localhost:8803 -c 40 -N 10
Starting at 2023/5/31 星期三 15:59:52
[Press C to stop the test]
3422    (RPS: 248.7)
3428    (RPS: 248.9)                    ---------------Finished!----------------
3428    (RPS: 248.9)                    Finished at 2023/5/31 星期三 16:00:06 (took 00:00:13.8633252)
3466    (RPS: 251.6)                    Status 200:    3430
Status 303:    36RPS: 314.4 (requests/second)
Max: 256ms
Min: 101ms
Avg: 112.9ms50%   below 107ms60%   below 108ms70%   below 108ms80%   below 109ms90%   below 114ms95%   below 126ms98%   below 217ms99%   below 232ms
99.9%   below 255ms

RPS 是314.4,好于多线程版本的308.8。

写在后面

参考文章列表

SuperBenchmarker(简称“sb“)压力测试工具详解 。

在windows上通过choco安装superbenchmarker进行压测 。


http://www.ppmy.cn/news/121395.html

相关文章

C语言获取Linux单网卡的多IP地址

环境配置 上一篇文章主要讲了AIX系统下的单网卡多IP的IP的配置以及C语言获取的方法。相比AIX,Linux下配置就方便得多。 首先找到我们需要配置的网卡名,比如p2p2, 进入到/etc/sysconfig/network-scripts/目录,找到ifcgf-p2p2文件,…

LeetCode 70. 爬楼梯 计算爬楼梯共计多少种方法可达

1、问题: 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 示例 1: 输入:n 2 输出:2 解释:有两种方法可以爬到楼顶。 1. 1 阶 1 阶 2.…

第十九章行为型模式—中介者模式

文章目录 中介者模式解决的问题结构实例存在的问题适用场景 中介者模式和代理模式的区别代理模式中介模式桥接模式总结 行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,它涉及算法…

充电桩检测设备厂家TK4860C交流充电桩检定装置

TK4860系列是专门针对现有交流充电桩现场检测过程中接线复杂、负载笨重、现场检测效率低等问题而研制的一系列高效检测仪器,旨在更好的开展充电桩的强制检定工作。 充电桩检测设备是一款在交流充电桩充电过程中实时检测充电电量的标准仪器,仪器以新能源…

小米max2装鸿蒙,小米Max2最全评测 小米Max2值不值得买?

小米Max2最全评测 小米Max2值不值得买?【IT168 评测】2016年的5月10日,小米首款大屏手机小米Max发布。而在一代小米Max发布初期,外界对这款手机的市场预期并不高,毕竟有着6.44寸大屏的它定位有些过于“精准”,面向的用…

小米5主板原理图_小米5手机拆解及评测 小米5拆机详细图解教程(4)

来看下取下的前像头,小米5的前摄像头只有400W相对其他设备有点小了,但是f/2.0 光圈 80 广角这点还是不错的。 接下来我们看看主板,主板上覆盖了很多屏蔽罩,这些屏蔽罩都是焊接式的,接下来我们拆开看看屏蔽罩下的原件及…

小米新手机鸿蒙系统,安卓终于被抛弃了!迎来鸿蒙系统新时代:结果小米新系统惨遭吐槽...

【4月15日讯】相信大家都知道,自从华为官方确认华为手机将全面“脱离Android系统”,转投自研鸿蒙OS系统以后,很多花粉们也在不断地期待华为鸿蒙OS系统能够早日“转正”,自己也能够早日体验到华为鸿蒙OS系统正式版,但就…

小米5 android 4.1.2,小米手机2安卓4.1 MIUI系统试玩

小米手机2搭载了基于Android 4.1深度定制的MIUI系统,而且这次MIUI有了中文名——米柚。其中不但加入了Android 4.1的新特性,还有新的功能。 可以看到MIUI V4在配色上已经进行改变,不过系统设置菜单还是与原生系统较为一致。这次小米手机2搭载…