Server代码
package com.test.tomcat.servlet;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
public class Server {
/**
* 初始化服务器
*
* @param host
* @param port
*/
public void init(String host, int port) {
try {
ServerSocket serverSocket = new ServerSocket();
System.out.println("服务器 " + host + ":" + port + " 启动成功...");
SocketAddress socketAddress = new InetSocketAddress(host, port);
serverSocket.bind(socketAddress);
readyAccept(serverSocket);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 接收请求
*
* @param serverSocket
* @throws IOException
*/
public void readyAccept(ServerSocket serverSocket) throws IOException {
while (true) {
Socket client = serverSocket.accept();
System.out.println();
new HandlerThread(client);
}
}
/**
* 请求处理
*/
static class HandlerThread implements Runnable {
private Socket socket;
public HandlerThread(Socket socket) {
this.socket = socket;
new Thread(this).start();
}
@Override
public void run() {
try {
showRequestData(socket);
writeResponseData(socket);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
System.out.println("socket closed...");
} catch (Exception e) {
socket = null;
System.out.println("socket close failed:" + e.getMessage());
}
}
}
}
/**
* 不能使用BufferedReader读取数据,因为会有数据读不全,导致读取数据一直阻塞
* 错误代码:
* BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
* String line;
* while ((line = br.readLine()) != null) {
* System.out.println(line);
* }
*
* @param socket
* @throws Exception
*/
public void showRequestData(Socket socket) throws Exception {
DataInputStream input = new DataInputStream(socket.getInputStream());
byte[] bytes = new byte[input.available()];
input.read(bytes);
System.out.println(new String(bytes));
}
public void writeResponseData(Socket socket) throws IOException {
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 200 ok").append("\r\n").append("Content-Type: application/json").append("\r\n").append("\r\n").append("{\"code\":200}");
out.write(sb.toString().getBytes("UTF8"));
}
}
public static void main(String[] args) {
Server server = new Server();
server.init("localhost", 8081);
}
}
数据
application/x-www-form-urlencoded
multipart/form-data
application/json
遇到的问题
一下情况都是以postman作为客户端模拟请求的!
获取请求数据的代码不同会导致不同的结果
- InputStream#read(byte b[]) +while循环发生阻塞问题
public void showRequestData(Socket socket) throws Exception {
byte[] bytes = new byte[1024];
int len;
InputStream inputStream = socket.getInputStream();
while ((len = inputStream.read(bytes)) != -1) {
String s = new String(bytes, 0, len);
System.out.println(s);
}
}
此代码循环完请求数据后,由于postman没有断开链接,会一直阻塞在while ((len = inputStream.read(bytes)) != -1)代码块这,并且通过idea的Evaluate Expression计算不出值,会一直阻塞。此时如果在postman上取消请求,这样才会跳出while循环。
- BufferedReader#readLine发生阻塞问题
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
此代码与上面的代码时一个效果
3. 使用DataInputStream可以解决阻塞的问题
DataInputStream input = new DataInputStream(socket.getInputStream());
byte[] bytes = new byte[input.available()];
input.read(bytes);
System.out.println(new String(bytes));
总结
- HTTP/1.1这一行上面都有一行空行
- Content-length下一行是空行,再下一行是数据