使用套接字Java向服务器发送错误请求的错误请求

时间:2018-03-29 08:11:15

标签: 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",我得到了Error 400, BAD Request,什么时候我必须收到代码200.

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

enter image description here

1 个答案:

答案 0 :(得分:2)

您的问题是由多种原因造成的:

writeUTF

的用法

来自ouput.writeUTF(head);

的文档
  

使用修改后的UTF-8编码以与机器无关的方式将字符串写入基础输出流。   首先,将两个字节写入输出流,就像writeShort方法一样,给出要跟随的字节数。该值是实际写出的字节数,而不是字符串的长度。在该长度之后,使用针对该字符的修改的UTF-8编码依次输出该字符串的每个字符。如果没有抛出异常,则写入的计数器将增加写入输出流的总字节数。这至少是两个加上str的长度,最多两个加上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";

缺少用户代理

虽然这不违反协议persee,但是某些服务器可能现在需要用户代理标头,并拒绝没有此标头的所有连接。

这很容易。

        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";