java - 使用 Sockets Java 向服务器发送消息的错误请求

标签 java sockets request tcpclient

我正在尝试打开一个套接字,发送一条消息(请求 HEAD)并从服务器获取响应。

我的代码与我正在寻找的许多其他代码类似,在SO或谷歌搜索中。

这里是:

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;

public class ClientTCPSocket {

    public static final int PORT = 80;

    public static void main(String argv[]) {


        BufferedReader inputKeyboard = new BufferedReader(new InputStreamReader(System.in));

        Socket socket;

        InetAddress ipAddress;

        String host = "";

        String head = "";

        String input_message = "";

        try {

            System.out.println("Host to connect?");

            host = inputKeyboard.readLine();
            head = "HEAD / HTTP/1.1\r\n"
                    + "Host: "+ host +"\r\n"
                    + "\r";
            ipAddress = InetAddress.getByName(host);

            socket = new Socket(ipAddress, PORT);

            DataOutputStream ouput = new DataOutputStream(socket.getOutputStream());


            System.out.println("\nSending info...");
            System.out.println(head);
            System.out.println("===============================");

            ouput.writeUTF(head);
            BufferedReader inputFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));


            while ((input_message = inputFromServer.readLine()) != null) {
                System.out.println(input_message);
            }
            System.out.println("===============================");

            socket.close();
            inputFromServer.close();

        } catch (IOException e) {
            System.out.println("Alguna cosa ha anat malament");
            e.printStackTrace();
        }
    }
}

(正如我在wiki中读到的:https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Message_format我需要放置回车符和换行符。我这么说是因为我只使用“\n”进行了测试)

但毕竟,如果我调用“localhost”(我在 mac 中打开了一个基本的 xampp)甚至“google.com”,我会收到错误 400,BAD 请求 ,什么时候我必须收到代码 200。

我不知道我忘记了什么,也不知道我必须发送哪种信息组合。

enter image description here

最佳答案

您的问题是由多种原因引起的:

writeUTF的用法

来自ouput.writeUTF(head);的文档

Writes a string to the underlying output stream using modified UTF-8 encoding in a machine-independent manner. First, two bytes are written to the output stream as if by the writeShort method giving the number of bytes to follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each character of the string is output, in sequence, using the modified UTF-8 encoding for the character. If no exception is thrown, the counter written is incremented by the total number of bytes written to the output stream. This will be at least two plus the length of str, and at most two plus thrice the length of str.

由于这 2 个字节是您的字符串的前缀,因此会导致无效的 HTTP 请求

您应该手动将字符串转换为字节,然后发送,或者使用 InputStreamWriter

ouput.write(head.getBytes(StandardCharsets.UTF_8));

缺少尾随 \n

消息中的最后一个换行符不完整

        head = "HEAD / HTTP/1.1\r\n"
                + "Host: "+ host +"\r\n"
                + "\r";

应该是

        head = "HEAD / HTTP/1.1\r\n"
                + "Host: "+ host +"\r\n"
                + "\r\n";

假设到达流末尾

在 HTTP 1.1 中,默认情况下所有连接都是持久的,这意味着服务器会在请求后保持连接打开一段时间。

虽然您目前看不到效果(因为请求格式错误,服务器假定其 HTTP 1.0),但如果您开始发送有效请求,就会出现问题。

由于这意味着您的程序永远不会跳出 for 循环,因此我们需要检测请求的结束(很难!),或者稍微降低效率并告诉服务器我们要关闭我们的连接:

        head = "HEAD / HTTP/1.1\r\n"
                + "Host: "+ host +"\r\n"
                + "Connection: close\r\n"
                + "\r\n";

缺少用户代理

虽然这本身并不违反协议(protocol),但某些服务器现在可能需要用户代理 header ,并拒绝所有没有此 header 的连接。

这真的很简单。

        head = "HEAD / HTTP/1.1\r\n"
                + "Host: "+ host +"\r\n"
                + "user-agent: Test program made by https://stackoverflow.com/users/1282166/shudy\r\n"
                + "\r\n";

关于java - 使用 Sockets Java 向服务器发送消息的错误请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49551039/

相关文章:

java - 验证的正则表达式必须包含字母数字

java - 如何匹配 3 个参数,包括通配符匹配?

c# - 将复杂对象从 View 传递到 Controller

android - 子标记的 SOAP 请求

java - 改变 TextInputLayout 提示行为

Java 两个类我需要 main 方法的帮助

java - Netty 或 java.net.Socket 用于绿地项目?

java - 两个 TCP 客户端作为一个客户端?

Java 慢 socket.connect()

javascript - Django:从 QueryDict 读取 JSON 对象数组