一、Http 协议
介绍一下 Http 协议的特点
Http(Hyper text transfer protocal)超文本传输协议,属于应用层协议,用于客户端和服务器之间的数据通信。
有几个特点:
1)简单和快速
2)采用请求个响应的模式
3) 无连接(服务器将数据响应给客户端后,连接就断开了)
4)无状态(服务器不会保存客户端的信息)
Hppt 的请求方法
主要方法:
GET | 获取信息 |
POST | 增加信息 |
PUT | 更新信息 |
DELETE | 删除信息 |
TRACE | 跟踪服务器状态 |
OPTIONS | 获得服务器参数 |
HEAD | 获得请求头部 |
CONNECT | 用于连接 |
面试:GET 和 POST 的区别?
用途:GET 用于查询,POST 用于增加数据
传参方式:GET 放 URL,POST 放请求体里面
安全性:GET 参数直接可见,安全性低,POST 稍高
数据量:GET 受浏览器限制,2k 内,POST 没有限制
Http 的响应代码
响应码 | 说明 |
1xx | 请求没有处理完 |
2xx | 请求成功处理 |
3xx | 请求重定向 |
4xx | 客户端问题 |
5xx | 服务器端问题 |
主要响应码:
- 200 ok 成功
- 400 参数错误
- 401 没有通过登录验证
- 403 没有访问权限
- 404 资源不可用
- 405 方法不对
- 415 方法请求拒绝
- 500 服务器错误
- 503 服务器不可用
Http 的数据报文
http 的本质是使用 tcp 协议发送数据报文给服务器,服务器处理请求后,将响应数据和数据报文发给客户端。
请求报文
例子
响应报文
例子
Http 和 Https 的 区别
Http 是明文传输的,存在安全问题的;Https 是 Http 的安全版(s security),有 SSL 加密层, 数据以加密方式传输。
区别:
- Https 以对称式和非对称式混合加密;Http 是明文
- Https 需要在 CA 互联网机构购买证书;Http 不需要
- Https 协议端口号默认是 443;Http 默认是 80
二、Http 编程
相关的一些 API:
- URL 服务器资源
- HttpURLConnection http 连接
URL 创建
new URL(服务器资源URL)
主要方法:
- HttpConnection openConnection()
HttpURLConnection 主要方法
- setConnectTimeout(连接超时)
- setReadTimeout(读取超时)
- setDoOutput(是否发送数据)
- InputStream getInputStream() 获得输入流
- OutputStream getOutputStream() 获得输出流
- close() 关闭
文件下载
代码:
public class DownloadDemo {
public static final String SAVE_PATH = "D:\\upload\\";
/**
* 文件下载
*
* @param urlStr
*/
public void downLoad(String urlStr, String fileName) {
try {
// 创建URL对象
URL url = new URL(urlStr);
// 获得连接对象
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//设置连接超时
connection.setConnectTimeout(30000);
// 判断正常连接
if (connection.getResponseCode() == 200) {
try ( // 获得输入流
InputStream inputStream = connection.getInputStream();
// 本地输出流
OutputStream outputStream = new FileOutputStream(SAVE_PATH + fileName);) {
// 定义缓冲区
byte[] buffer = new byte[1024];
// 每次读的长度
int len = 0;
// 循环读取数据,写入到本地文件
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
System.err.println("图片下载完成!!!");
Runtime.getRuntime().exec("mspaint " + SAVE_PATH + fileName);
} catch (IOException ex) {
ex.printStackTrace();
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
new DownloadDemo().downLoad("https://th.bing.com/th/id/R.8f26770f97928c922a9ea3256532f1a8?rik=%2flyrKGkLA4AGaA&riu=http%3a%2f%2fpic.zsucai.com%2ffiles%2f2013%2f0922%2fshu3.jpg&ehk=FB3Jpp94A%2bR%2fve7tvkv2tR3wvc8IxHMLYbes%2fkZEf38%3d&risl=&pid=ImgRaw&r=0", "mm.jpeg");
}
}
三、Http 服务器原理
自定义 http 服务器
分析:
任务分解:
1) 创建ServerSocket,侦听8888端口
2) 循环获得客户端socket
3) 获得客户端的输入流,读取请求报文
问题:用什么流?字符流,BufferReader
4) 将报文中URL截取
5) 通过URL名称+html目录路径获得资源文件,读取其中的文字
问题: 封装读取文字的方法
6) 拼接响应报文,发送给浏览器
代码:
/**
* 自定义Http服务器
*/
public class MyHttpServer {
public static final int PORT = 999;
public static final String HTML_DIR = "D:\\home";
public void start(){
System.out.println("启动服务器");
//创建ServerSocket
try(ServerSocket serverSocket = new ServerSocket(PORT)){
while(true){
//获得客户端连接
Socket socket = serverSocket.accept();
System.out.println("客户端连接:" + socket);
//读取客户端的请求报文
StringBuilder request = new StringBuilder();
//读取请求报文
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
request.append(line);
if (line.length() == 0) {//""
break;
}
}
System.out.println(request);
//截取报文中的url
int first = request.indexOf(" ");
int second = request.indexOf(" ",first + 1);
String url = request.substring(first + 1, second);
System.out.println("url:" + url);
File file = new File(HTML_DIR + url);
StringBuilder stringBuilder = new StringBuilder();
if(file.exists()){
//读取本地html文件
StringBuilder html = new StringBuilder();
try(BufferedReader reader = new BufferedReader(new FileReader(file))){
String s = null;
while((s = reader.readLine()) != null){
html.append(s + "\n");
}
}catch (IOException ex){
ex.printStackTrace();
}
System.out.println("html:" + html);
//拼接响应报文
stringBuilder.append("HTTP/1.1 200 OK\r\n");
stringBuilder.append("Content-Type: text/html; charset=UTF-8\r\n");
stringBuilder.append("Content-Length: " + html.toString().getBytes("UTF-8").length + "\r\n");
stringBuilder.append("\r\n");
stringBuilder.append(html);
}else{
System.out.println("文件不存在" + file.getAbsolutePath());
stringBuilder.append("HTTP/1.1 404 NOT FOUND\r\n");
}
//发送响应报文给浏览器
OutputStream outputStream = socket.getOutputStream();
outputStream.write(stringBuilder.toString().getBytes());
outputStream.flush();
outputStream.close();
}
}catch (IOException ex){
ex.printStackTrace();
}
}
public static void main(String[] args) {
new MyHttpServer().start();
}
}
四、 JMeter
jJava开发的压力测试 QPS Query Per Second 每秒请求数 TPS Transaction Per Second 每秒事务量。
使用步骤:
1) 创建线程组
2) 设置线程数
3)设置HTTP请求
4) 设置请求接口信息
5) 添加监听器
6) 点击start启动测试
7)语言设置简体中文
8)启动 jmeter
自定义压力测试工具:
1) 输入线程数、IP、端口、请求方法、URL、参数、参数类型
2) 启动多个线程执行http请求
3) 显示每个线程返回响应数据以及执行时间
/**
* 调用HTTP接口的案例
*/
public class HttpDemo {
static String testGet(){
try {
URL url = new URL("http://localhost:8080/order-page?current=1&size=5");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(3000);
connection.setRequestMethod("GET");
connection.connect();
if(connection.getResponseCode() == 200){
try(BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))){
String line = null;
StringBuilder stringBuilder = new StringBuilder();
while((line = reader.readLine()) != null){
stringBuilder.append(line + "\n");
}
return stringBuilder.toString();
}catch (IOException ex){
ex.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
static String testPost(){
try {
URL url = new URL("http://localhost:8080/order");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(3000);
connection.setRequestMethod("POST");
//设置请求内容类型
connection.addRequestProperty("Content-Type","application/json");
//设置输出
connection.setDoOutput(true);
//发送参数
String args = "{\"num\":1,\"goodsId\":1,\"userId\":1,\"time\":\"2020-11-11T11:11:11\"}";
OutputStream outputStream = connection.getOutputStream();
outputStream.write(args.getBytes("UTF-8"));
outputStream.flush();
connection.connect();
if(connection.getResponseCode() == 200){
try(BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))){
String line = null;
StringBuilder stringBuilder = new StringBuilder();
while((line = reader.readLine()) != null){
stringBuilder.append(line + "\n");
}
return stringBuilder.toString();
}catch (IOException ex){
ex.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
System.out.println(testPost());
System.out.println(testGet());
}
}