Java编写http服务器和http客户端,服务器多线程处理客户端请求,可以实现GET、HEAD、POST请求,可以通过浏览器看到服务器信息的代码
时间: 2024-02-15 09:04:09 浏览: 122
好的,以下是一个使用Java编写的简单的HTTP服务器和HTTP客户端示例代码,可以处理GET、HEAD、POST请求,并且支持多线程处理客户端请求,同时可以通过浏览器查看服务器信息。
HTTP服务器代码:
```java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Date;
public class HttpServer {
private static final int PORT = 8080;
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(PORT);
while (true) {
Socket clientSocket = serverSocket.accept();
new Thread(() -> {
try {
handleClientRequest(clientSocket);
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void handleClientRequest(Socket clientSocket) throws IOException {
InputStream input = clientSocket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = clientSocket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
String requestLine = reader.readLine();
String[] requestLineTokens = requestLine.split("\\s+");
String method = requestLineTokens[0];
String uri = requestLineTokens[1];
String httpVersion = requestLineTokens[2];
System.out.println("Received " + method + " request for " + uri + " from " + clientSocket.getRemoteSocketAddress());
if (!method.equalsIgnoreCase("GET") && !method.equalsIgnoreCase("HEAD") && !method.equalsIgnoreCase("POST")) {
writer.println("HTTP/1.1 501 Not Implemented");
writer.println("Date: " + new Date());
writer.println("Server: Simple Java HTTP Server");
writer.println("Content-Type: text/plain");
writer.println();
writer.println("HTTP method not supported: " + method);
return;
}
int contentLength = 0;
String line;
while ((line = reader.readLine()) != null) {
if (line.isEmpty()) {
break;
}
if (line.startsWith("Content-Length: ")) {
contentLength = Integer.parseInt(line.substring("Content-Length: ".length()));
}
}
if (method.equalsIgnoreCase("POST")) {
char[] buffer = new char[contentLength];
reader.read(buffer, 0, contentLength);
String requestBody = new String(buffer);
System.out.println("Request body: " + requestBody);
}
File file = new File("." + uri);
if (file.isDirectory()) {
file = new File(file, "index.html");
}
if (!file.exists()) {
writer.println("HTTP/1.1 404 Not Found");
writer.println("Date: " + new Date());
writer.println("Server: Simple Java HTTP Server");
writer.println("Content-Type: text/plain");
writer.println();
writer.println("File not found: " + uri);
return;
}
String contentType = guessContentType(file.getName());
byte[] content = readFileContents(file);
writer.println("HTTP/1.1 200 OK");
writer.println("Date: " + new Date());
writer.println("Server: Simple Java HTTP Server");
writer.println("Content-Type: " + contentType);
writer.println("Content-Length: " + content.length);
writer.println();
if (method.equalsIgnoreCase("GET")) {
output.write(content);
}
output.flush();
output.close();
clientSocket.close();
}
private static byte[] readFileContents(File file) throws IOException {
try (FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024];
int read;
while ((read = fis.read(buffer)) != -1) {
bos.write(buffer, 0, read);
}
return bos.toByteArray();
}
}
private static String guessContentType(String name) {
if (name.endsWith(".html") || name.endsWith(".htm")) {
return "text/html";
} else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
return "image/jpeg";
} else if (name.endsWith(".gif")) {
return "image/gif";
} else if (name.endsWith(".png")) {
return "image/png";
} else if (name.endsWith(".css")) {
return "text/css";
} else if (name.endsWith(".js")) {
return "application/javascript";
} else {
return "application/octet-stream";
}
}
}
```
HTTP客户端代码:
```java
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class HttpClient {
private static final String SERVER_HOST = "localhost";
private static final int SERVER_PORT = 8080;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("Enter HTTP method (GET, HEAD, POST):");
String method = scanner.nextLine().toUpperCase();
System.out.println("Enter resource URI:");
String uri = scanner.nextLine();
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT)) {
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
writer.println(method + " " + uri + " HTTP/1.1");
writer.println("Host: " + SERVER_HOST + ":" + SERVER_PORT);
if (method.equals("POST")) {
System.out.println("Enter request body:");
String requestBody = scanner.nextLine();
writer.println("Content-Length: " + requestBody.getBytes().length);
writer.println();
writer.print(requestBody);
} else {
writer.println();
}
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
```
上述代码中,我们使用Socket和ServerSocket类实现了一个简单的HTTP服务器和HTTP客户端。服务器支持处理GET、HEAD和POST请求,可以通过浏览器查看服务器信息。客户端可以向服务器发送GET、HEAD和POST请求,并且可以手动输入请求体。同时,服务器使用多线程处理客户端请求,可以同时处理多个客户端请求。
需要注意的是,这只是一个简单的示例,实际应用中可能需要更复杂的代码来处理更多的HTTP请求和响应头信息。
阅读全文