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

Java通过Socket请求Host URL遇400错误,如何实现目标打印与文件写入?

问题

我尝试用Java代码从gaia.cs.umass.edu获取/wireshark-labs/INTRO-wireshark-file1.html的内容,并写入/Users/brichards/message.html,但运行时返回HTTP 400错误,既无法输出指定的两行提示信息,也没正确写入目标文件。以下是我的代码、期望输出和实际错误返回:

我的代码

public static void SocketandURL(String[] args) throws Exception {


     
            String host = args[0];
            
            
            
            

            // Build and send a GET request packet. The packet is a String,
            // and therefore needs to be converted to a sequence of bytes before it
            // can be sent. There's a getBytes() method in the String class to do that.
            // The \r and \n characters are CR and LF. The first pair ends the GET line,
            // the second pair ends the "blank line" marking the end of the packet.
            // Any header info could have to be included before that blank line.

            String packet = "GET /wireshark-labs/INTRO-wireshark-file1.html HTTP/1.1\r\n\r\n";
            packet = "Host: " + host + packet;
            

            System.out.println("Sending packet to " + host);
            
        try {
            // Read the resulting data and write it to our output file. We intentionally
            // use a DataInputStream rather than an InputStreamReader to get the data from
            // the socket, since we want to allow for reading binary data files like .jpgs,
            // but that means we need to convert it to a character string if we ever want
            // to print it out. This code uses a special constructor in the String class
            // to do that. Note that this code assumes the entire response can be retrieved
            // in one call to read(). You may NOT make that assumption in your finished
            // program.


            //Get DataInputStream of Array
            theSocket = new Socket(host, 80); // Port 80 is HTTP
            byte[] buf = new byte[BUFFER_SIZE];//New byte array
            outgoing = theSocket.getOutputStream();
            incoming = new DataInputStream(theSocket.getInputStream());
            outgoing.write(packet.getBytes());
            int numBytes = incoming.read(buf);
            
            
            String filename = "textfile.txt";
            File theFile = new File(filename);

            if (args.length > 0) {
                filename = args[0];
            }

            if (theFile.exists()) {
                System.out.println("It already exists. Contents will be overwritten");
            } else {
                System.out.println("Creating new file: " + theFile.getAbsolutePath());
                FileMake(args);
            }

            FileOutputStream writer = new FileOutputStream(theFile);
            String filePath = "/Users/bakya/Downloads/HW2/textfile.txt";
            writer.write(filePath.getBytes());
            writer.close();
            while (numBytes > 0) {
                System.out.println("Got: " + (new String(buf, 0, numBytes, "UTF-8")));
                host += args[0];         
                numBytes = incoming.read(buf);
            }

            theSocket.close();
        } catch (Exception e) {
            System.out.println("ERR: Invalid File");
        }
    }

期望输出

Grabbing /wireshark-labs/INTRO-wireshark-file1.html from gaia.cs.umass.edu
Writing data to /Users/brichards/message.html

实际错误输出

Sending packet to gaia.cs.umass.edu
It already exists. Contents will be overwritten
Got: HTTP/1.1 400 Bad Request
Date: Mon, 25 Sep 2023 00:46:07 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.33 mod_perl/2.0.11 Perl/v5.16.3
Content-Length: 226
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>
解决方案

1. 修复HTTP请求格式错误(400错误的核心原因)

HTTP/1.1要求Host头必须单独以\r\n结尾,你当前的拼接方式直接把Host和GET请求行连在一起,导致请求格式非法。正确的请求构造方式:

String packet = "GET /wireshark-labs/INTRO-wireshark-file1.html HTTP/1.1\r\n" +
                "Host: " + host + "\r\n\r\n";

2. 修正输出文件逻辑

  • 不要把args[0](主机名)当作文件名,直接指定目标路径/Users/brichards/message.html,或者通过args[1]传递输出路径
  • 代码中错误地将文件路径字符串写入文件,应改为写入从Socket读取的响应内容
  • 调整文件流关闭时机,写完所有数据后再关闭

3. 添加指定的提示信息

在发送请求前输出要求的两行提示:

System.out.println("Grabbing /wireshark-labs/INTRO-wireshark-file1.html from " + host);
System.out.println("Writing data to " + outputFilePath);

4. 修复循环读取逻辑

  • 删除无意义的host += args[0];代码,避免主机名被重复拼接
  • 确保循环中持续读取Socket数据并写入文件,而非仅打印

修复后的完整代码

import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class HttpFetcher {
    private static final int BUFFER_SIZE = 4096;
    private static Socket theSocket;
    private static OutputStream outgoing;
    private static DataInputStream incoming;

    public static void SocketandURL(String[] args) throws Exception {
        if (args.length < 2) {
            System.err.println("使用方式: java HttpFetcher <主机名> <输出文件路径>");
            return;
        }

        String host = args[0];
        String outputFilePath = args[1];

        // 构造合法的HTTP请求
        String packet = "GET /wireshark-labs/INTRO-wireshark-file1.html HTTP/1.1\r\n" +
                        "Host: " + host + "\r\n\r\n";

        // 输出指定提示信息
        System.out.println("Grabbing /wireshark-labs/INTRO-wireshark-file1.html from " + host);
        System.out.println("Writing data to " + outputFilePath);

        try {
            theSocket = new Socket(host, 80);
            byte[] buf = new byte[BUFFER_SIZE];
            outgoing = theSocket.getOutputStream();
            incoming = new DataInputStream(theSocket.getInputStream());

            // 发送请求
            outgoing.write(packet.getBytes());
            outgoing.flush();

            File theFile = new File(outputFilePath);
            FileOutputStream writer = new FileOutputStream(theFile);

            // 处理文件存在提示
            if (theFile.exists()) {
                System.out.println("It already exists. Contents will be overwritten");
            } else {
                System.out.println("Creating new file: " + theFile.getAbsolutePath());
                theFile.getParentFile().mkdirs(); // 确保父目录存在
            }

            // 循环读取响应并写入文件
            int numBytes = incoming.read(buf);
            while (numBytes > 0) {
                writer.write(buf, 0, numBytes);
                numBytes = incoming.read(buf);
            }

            // 关闭资源
            writer.close();
            incoming.close();
            outgoing.close();
            theSocket.close();

        } catch (Exception e) {
            System.err.println("错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        SocketandURL(args);
    }
}

使用方式

运行时传递参数:

java HttpFetcher gaia.cs.umass.edu /Users/brichards/message.html

内容的提问来源于stack exchange,提问作者Jaykob Walson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:05:19