我试图打开套接字,发送消息(请求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.
我不知道我忘记了什么,或者我必须发送哪些信息组合。
答案 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";