You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Java Socket通信被Wireshark识别为HTTP协议?

问题

我使用Java编写了Socket通信代码,通过Wireshark抓包时,工具显示该通信使用TCP协议而非HTTP协议。我是否未遵循HTTP头格式?请告知如何修改代码,使Wireshark抓包时识别为HTTP协议。

原代码

MyServer.java

import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
import java.io.DataInputStream;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Locale;


public class MyServer {
    public static void main(String[] args) {

        ServerSocket serverSocket = null;
        Socket socket = null;

        InputStream inputStream = null;
        DataInputStream dataInputStream = null;

        OutputStream outputStream = null;
        DataOutputStream dataOutputStream = null;

        String blank = "";

        try {
            serverSocket = new ServerSocket(9000);
            System.out.println("已准备好接收客户端数据");

            socket = serverSocket.accept();
            System.out.println("客户端连接完成");
            System.out.println("socket: " + socket);

            inputStream = socket.getInputStream();
            dataInputStream = new DataInputStream(inputStream);

            outputStream = socket.getOutputStream();
            dataOutputStream = new DataOutputStream(outputStream);

            while (true) {

                String clientMessage = dataInputStream.readUTF();
                String[] clientMessages = clientMessage.split("\\r\\n");
                String slot1 = clientMessages[0]; // 示例) "GET / HTTP/1.1"
                String[] slot2 = slot1.split(" ");
                String request_method = slot2[0]; // 示例) GET
                String request_version = slot2[2]; // 示例) HTTP/1.1

                String server_name = "Socket Server";
                String strDate = "";

                Date date = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
                strDate = sdf.format(date);
                String response_data = "";

                if (request_method.equals("GET") && request_version.equals("HTTP/1.1")){
                    System.out.printf("%s %s 200\n", request_method, request_version);
                    response_data = String.format("%s 200 OK\nServer: %s\nDate: %s\n", request_version, server_name, strDate);
                }
                else if (request_method.equals("POST") && request_version.equals("HTTP/1.1")){
                    System.out.printf("%s %s 201", request_method, request_version);
                    response_data = String.format("%s 201 OK\nServer: %s\nDate: %s\n", request_version, server_name, strDate);
                }
                else if (request_method.equals("HEAD") && request_version.equals("HTTP/1.1")){
                    System.out.printf("%s %s 203", request_method, request_version);
                    response_data = String.format("%s 203 OK\nServer: %s\nDate: %s\n", request_version, server_name, strDate);
                }
                else if (request_method.equals("PUT") && request_version.equals("HTTP/1.1")){
                    System.out.printf("%s %s 202", request_method, request_version);
                    response_data = String.format("%s 202 OK\nServer: %s\nDate: %s\n", request_version, server_name, strDate);
                }
                else if (request_method.equals("DELETE") && request_version.equals("HTTP/1.1")){
                    System.out.printf("%s %s 204", request_method, request_version);
                    response_data = String.format("%s 204 OK\nServer: %s\nDate: %s\n", request_version, server_name, strDate);
                }
                else {
                    System.out.printf("%s %s 405", request_method, request_version);
                    response_data = String.format("%s 405 OK\nServer: %s\nDate: %s\n", request_version, server_name, strDate);
                }

                dataOutputStream.writeUTF(response_data);
                dataOutputStream.flush();

                if (clientMessage.equals("STOP")) break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (dataOutputStream != null) dataOutputStream.close();
                if (outputStream != null) outputStream.close();
                if (dataInputStream != null) dataInputStream.close();
                if (inputStream != null) inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

MyClient.java

import java.net.Socket;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.DataInputStream;
import java.util.Scanner;

public class MyClient {
    public static void main(String[] args) {
        Socket socket = null;

        OutputStream outputStream = null;
        DataOutputStream dataOutputStream = null;

        InputStream inputStream = null;
        DataInputStream dataInputStream = null;

        String inputMessage = "";
        String outputMessage = "";
        Scanner scanner = null;

        try{
            socket = new Socket("localhost", 9000);
            System.out.println("服务器连接完成");

            outputStream = socket.getOutputStream();
            dataOutputStream = new DataOutputStream(outputStream);

            inputStream = socket.getInputStream();
            dataInputStream = new DataInputStream(inputStream);

            scanner = new Scanner(System.in);

            while(true){
                System.out.print("请输入消息:");

                inputMessage = scanner.next();

                if (inputMessage.equals("GET")) {
                    outputMessage = "GET / HTTP/1.1\\r\\nHost: 127.0.0.1:9000\\r\\nUser-Agent: Mozilla/5.0\\r\\nAccept: */*\\r\\n\\r\\n";
                } else if (inputMessage.equals("POST")) {
                    outputMessage = "POST / HTTP/1.1\\r\\nHost: 127.0.0.1:9000\\r\\nUser-Agent: insomnia/2022.2.1\\r\\nAccept: */*\\r\\nContent-Length: 0\\r\\n\\r\\n";
                } else if (inputMessage.equals("HEAD")) {
                    outputMessage = "HEAD / HTTP/1.1\\r\\nHost: 127.0.0.1:9000\\r\\nUser-Agent: insomnia/2022.2.1\\r\\nAccept: */*\\r\\n\\r\\n";
                } else if (inputMessage.equals("PUT")) {
                    outputMessage = "PUT / HTTP/1.1\\r\\nHost: 127.0.0.1:9000\\r\\nUser-Agent: insomnia/2022.2.1\\r\\nAccept: */*\\r\\nContent-Length: 0\\r\\n\\r\\n";
                } else if (inputMessage.equals("DELETE")) {
                    outputMessage = "DELETE / HTTP/1.1\\r\\nHost: 127.0.0.1:9000\\r\\nUser-Agent: insomnia/2022.2.1\\r\\nAccept: */*\\r\\n\\r\\n";
                } else {
                    outputMessage = "NotAllowed / HTTP/1.1\\r\\nHost: 127.0.0.1:9000\\r\\nUser-Agent: insomnia/2022.2.1\\r\\nAccept: */*\\r\\n\\r\\n";
                }
                dataOutputStream.writeUTF(outputMessage);
                dataOutputStream.flush();
                String receivedMessage = dataInputStream.readUTF();
                System.out.println(receivedMessage);

                if (inputMessage.equals("STOP")) break;
            }
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            try{
                if (dataOutputStream != null) dataOutputStream.close();
                if (outputStream != null) outputStream.close();
                if (dataInputStream != null) dataInputStream.close();
                if (inputStream != null) inputStream.close();
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

问题原因与修改方案

核心问题是你使用了DataInputStream.readUTF()和DataOutputStream.writeUTF()方法,这两个方法会在传输的文本前添加2字节的长度标识,破坏了HTTP协议要求的纯文本格式,导致Wireshark无法识别为HTTP流量。

要解决这个问题,需要替换为纯文本字符流进行读写:

  • 服务器端:用BufferedReader读取HTTP请求,用PrintWriter发送HTTP响应
  • 客户端:用PrintWriter发送HTTP请求,用BufferedReader接收HTTP响应

同时注意两个关键细节:

  1. HTTP协议的换行必须是\r\n,不能使用Java字符串中的转义写法\\r\\n
  2. HTTP响应需要以空行结尾,用于分隔响应头和响应体(即使响应体为空)

修改后的代码

MyServer.java

import java.net.ServerSocket;
import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Locale;

public class MyServer {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        BufferedReader reader = null;
        PrintWriter writer = null;

        try {
            serverSocket = new ServerSocket(9000);
            System.out.println("已准备好接收客户端数据");

            socket = serverSocket.accept();
            System.out.println("客户端连接完成");
            System.out.println("socket: " + socket);

            // 用BufferedReader读取纯文本请求
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 用PrintWriter发送纯文本响应,自动刷新缓冲区
            writer = new PrintWriter(socket.getOutputStream(), true);

            String line;
            String requestLine = "";
            // 读取请求的第一行(请求行),直到空行结束请求头
            while ((line = reader.readLine()) != null) {
                if (line.isEmpty()) break;
                if (requestLine.isEmpty()) {
                    requestLine = line;
                }
            }

            if (!requestLine.isEmpty()) {
                String[] slot2 = requestLine.split(" ");
                String request_method = slot2[0];
                String request_version = slot2[2];

                String server_name = "Socket Server";
                Date date = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
                String strDate = sdf.format(date);
                String responseStatus = "";

                switch (request_method) {
                    case "GET":
                        responseStatus = "200 OK";
                        System.out.printf("%s %s 200\n", request_method, request_version);
                        break;
                    case "POST":
                        responseStatus = "201 Created";
                        System.out.printf("%s %s 201\n", request_method, request_version);
                        break;
                    case "HEAD":
                        responseStatus = "203 Non-Authoritative Information";
                        System.out.printf("%s %s 203\n", request_method, request_version);
                        break;
                    case "PUT":
                        responseStatus = "202 Accepted";
                        System.out.printf("%s %s 202\n", request_method, request_version);
                        break;
                    case "DELETE":
                        responseStatus = "204 No Content";
                        System.out.printf("%s %s 204\n", request_method, request_version);
                        break;
                    default:
                        responseStatus = "405 Method Not Allowed";
                        System.out.printf("%s %s 405\n", request_method, request_version);
                        break;
                }

                // 构造符合HTTP规范的响应,结尾加空行分隔头和体
                String response = String.format("%s %s\r\nServer: %s\r\nDate: %s\r\n\r\n",
                        request_version, responseStatus, server_name, strDate);
                writer.print(response);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) writer.close();
                if (reader != null) reader.close();
                if (socket != null) socket.close();
                if (serverSocket != null) serverSocket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

MyClient.java

import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Scanner;

public class MyClient {
    public static void main(String[] args) {
        Socket socket = null;
        PrintWriter writer = null;
        BufferedReader reader = null;
        Scanner scanner = null;

        try {
            socket = new Socket("localhost", 9000);
            System.out.println("服务器连接完成");

            // 用PrintWriter发送纯文本请求
            writer = new PrintWriter(socket.getOutputStream(), true);
            // 用BufferedReader接收纯文本响应
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            scanner = new Scanner(System.in);

            while (true) {
                System.out.print("请输入消息:");
                String inputMessage = scanner.next();

                if (inputMessage.equals("STOP")) break;

                String outputMessage;
                // 直接使用\r\n作为HTTP换行符
                switch (inputMessage) {
                    case "GET":
                        outputMessage = "GET / HTTP/1.1\r\nHost: 127.0.0.1:9000\r\nUser-Agent: Mozilla/5.0\r\nAccept: */*\r\n\r\n";
                        break;
                    case "POST":
                        outputMessage = "POST / HTTP/1.1\r\nHost: 127.0.0.1:9000\r\nUser-Agent: insomnia/2022.2.1\r\nAccept: */*\r\nContent-Length: 0\r\n\r\n";
                        break;
                    case "HEAD":
                        outputMessage = "HEAD / HTTP/1.1\r\nHost: 127.0.0.1:9000\r\nUser-Agent: insomnia/2022.2.1\r\nAccept: */*\r\n\r\n";
                        break;
                    case "PUT":
                        outputMessage = "PUT / HTTP/1.1\r\nHost: 127.0.0.1:9000\r\nUser-Agent: insomnia/2022.2.1\r\nAccept: */*\r\nContent-Length: 0\r\n\r\n";
                        break;
                    case "DELETE":
                        outputMessage = "DELETE / HTTP/1.1\r\nHost: 127.0.0.1:9000\r\nUser-Agent: insomnia/2022.2.1\r\nAccept: */*\r\n\r\n";
                        break;
                    default:
                        outputMessage = "NotAllowed / HTTP/1.1\r\nHost: 127.0.0.1:9000\r\nUser-Agent: insomnia/2022.2.1\r\nAccept: */*\r\n\r\n";
                        break;
                }

                writer.print(outputMessage);
                writer.flush();

                // 读取并打印服务器响应
                System.out.println("服务器响应:");
                String responseLine;
                while ((responseLine = reader.readLine()) != null) {
                    if (responseLine.isEmpty()) break;
                    System.out.println(responseLine);
                }
                System.out.println();
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) writer.close();
                if (reader != null) reader.close();
                if (scanner != null) scanner.close();
                if (socket != null) socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Issac Kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:40:57