目录
HTTP协议
Http(Hyper text transfer protocal)超文本传输协议,属于应用层协议,用于客户端和服务器之间的数据通信
HTTP协议的特点
1、简单和迅速
2、采用请求和响应模式
3、无连接(服务器将数据响应给客户端后,连接就断开)
4、无状态(服务器不会保存客户端的信息)
HTTP的请求方法
主要方法:
-
GET 获取信息
-
POST 增加信息
-
DELETE 删除信息
-
PUT 更新信息
-
trace 跟踪服务器状态
-
options 获得服务器参数
-
head 获取请求头部
-
connect 用于连接
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连接
HttpURLConnection 主要方法
-
setConnectTimeout(连接超时)
-
setReadTimeout(读取超时)
-
setDoOutput(是否发送数据)
-
InputStream getInputStream() 获得输入流
-
OutputStream getOutputStream() 获得输出流
-
close() 关闭
写一个文件下载:
/**
* 文件下载
*/
public class DownloadDemo {
public static final String SAVE_PATH = "D:\\upload";
public void download(String url, String fileName){
//创建URL对象
try {
URL url1 = new URL(url);
//获取连接对象
HttpURLConnection connection = (HttpURLConnection)url1.openConnection();
//设置连接超时
connection.setConnectTimeout(2000);
//判断正常连接
if (connection.getResponseCode() == 200){
//自动关闭流
try(
//获得输入流
InputStream inputStream = connection.getInputStream();
//本第输出流
OutputStream outputStream = new FileOutputStream(SAVE_PATH+fileName)
){
//定义缓冲区
byte[] bytes = new byte[1024];
//每次读的长度
int len = 0;
//循环读取数据
while ((len = inputStream.read(bytes)) != -1){
outputStream.write(bytes,0,len);
}
System.out.println(fileName+"下载完毕");
Runtime.getRuntime().exec("mspaint " + SAVE_PATH + fileName);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new DownloadDemo().download("https://img2.baidu.com/it/u=252387764,489326928&fm=253&fmt=auto&app=138&f=GIF?w=48&h=48","weixin");
}
}
自定义http服务器
流程分析:
1) 创建ServerSocket,侦听8888端口
2) 循环获得客户端socket
3) 获得客户端的输入流,读取请求报文
问题:用什么流?字符流,BufferReader
4) 将报文中URL截取
5) 通过URL名称+html目录路径获得资源文件,读取其中的文字
问题: 封装读取文字的方法
6) 拼接响应报文,发送给浏览器
代码展示:
/**
* 自定义HTTP服务器
*/
public class MyHttpServer {
public static final int PORT = 8088;
public static final String PATH = "D:\\home";
/**
* 读取流中的文字
*/
//private String read(InputStream inputStream){
// StringBuilder builder = new StringBuilder();
// try{
// //创建字符流
// BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
// String line = null;
// //循环读取一行文字
// while((line = reader.readLine()) != null){
// builder.append(line + "\n");
// if (line.length() == 0) {//""
// break;
// }
// }
// }catch (IOException ex){
// ex.printStackTrace();
// }
// return builder.toString();
//}
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+"\n");
if (line.length() == 0){
break;
}
}
System.out.println(request);
//String request = read(socket.getInputStream());
//截取报文中的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(PATH + 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 e){
e.printStackTrace();
}
System.out.println("hhtml: "+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().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 e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new MyHttpServer().start();
}
}