Java Socket HTTP GET 请求

9 浏览
0 Comments

Java Socket HTTP GET 请求

我正在尝试创建一个简单的Java程序,通过使用Socket创建一个HTTP请求给本地托管的HTTP服务器。\n这是我的代码:\n

try
{
    //创建连接
    Socket s = new Socket("localhost",80);
    System.out.println("[连接成功]");
    DataOutputStream out = new DataOutputStream(s.getOutputStream());
    DataInputStream in   = new DataInputStream(s.getInputStream());
    String header = "GET / HTTP/1.1\n"
            +"Host:localhost\n\n";
    byte[] byteHeader = header.getBytes();
    out.write(byteHeader,0,header.length());
    String res = "";
    /////////////读取过程/////////////
    byte[] buf = new byte[in.available()];
    in.readFully(buf);
    System.out.println("\t[读取过程]");
    System.out.println("\t\t缓冲区长度->"+buf.length);
    for(byte b : buf)
    {
        res += (char) b;
    }
    System.out.println("\t[/读取过程]");
    /////////////结束读取过程/////////////
    System.out.println("[响应]");
    System.out.println(res);
    System.out.println("[连接关闭]");
    in.close();
    out.close();
    s.close();
}catch(Exception e)
{
    e.printStackTrace();
}

\n但是当我运行它时,服务器返回一个\'400 Bad request\'错误。\n问题是什么?也许需要添加一些HTTP头部,但我不知道应该添加哪些。

0
0 Comments

Java Socket HTTP GET请求的问题出现的原因是请求没有正确的结束标记。根据HTTP 1.1规范,除了实体主体外,所有协议元素的行尾标记应该是CR LF(即回车换行符)。

解决方法是确保请求的每一行都以\r\n结尾。

示例代码如下:

import java.io.*;
import java.net.*;
public class HttpClient {
    public static void main(String[] args) {
        try {
            // 创建Socket连接
            Socket socket = new Socket("www.example.com", 80);
            
            // 获取输出流
            OutputStream outputStream = socket.getOutputStream();
            PrintWriter writer = new PrintWriter(outputStream);
            
            // 发送HTTP GET请求
            writer.print("GET /index.html HTTP/1.1\r\n");
            writer.print("Host: www.example.com\r\n");
            writer.print("Connection: close\r\n");
            writer.print("\r\n"); // 结束标记
            
            // 刷新缓冲区并关闭流
            writer.flush();
            writer.close();
            
            // 获取输入流
            InputStream inputStream = socket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            
            // 读取响应内容
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            
            // 关闭连接
            reader.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

以上代码中,通过创建Socket连接,获取输出流并发送HTTP GET请求。在每个请求行的末尾添加\r\n作为结束标记。然后刷新缓冲区并关闭流。接着获取输入流,读取响应内容并关闭连接。

通过以上的解决方法,可以确保Java Socket发送的HTTP GET请求符合HTTP 1.1规范,避免出现请求格式错误的问题。

0
0 Comments

Java在内存中缓存所有的字符串以便重复使用,这是出于内存优化和性能方面的考虑。当Java创建一个字符串时,它会首先检查内存中是否已经存在相同内容的字符串对象,如果存在,则直接返回该对象的引用,而不需要创建新的字符串对象。这样可以避免重复创建相同内容的字符串,减少内存占用。

Java使用字符串常量池来实现字符串的缓存。字符串常量池是在堆内存中的一个特殊的内存区域,用于存储所有字符串常量。当Java编译器遇到字符串常量时,它会首先检查常量池中是否已经存在相同内容的字符串,如果存在,则直接使用该字符串的引用。如果常量池中没有相同内容的字符串,则会在常量池中创建一个新的字符串对象,并返回其引用。

通过缓存字符串,Java可以减少内存中相同内容字符串的数量,提高内存利用率。此外,由于字符串是不可变的,缓存字符串还可以避免频繁创建和销毁字符串对象,减少垃圾回收的频率,提高程序的性能。

然而,如果使用字符串拼接的方式来连接大量的字符串,比如在循环中使用"+"操作符来拼接字符串,会导致性能和内存问题。每次进行字符串拼接时,Java都会创建一个新的字符串对象,并将拼接结果复制到新的字符串对象中。这样就会导致大量的临时字符串对象被创建,占用大量的内存,并且由于字符串是不可变的,这些临时字符串对象无法被回收,最终会导致垃圾回收的频繁运行。

为了避免这个问题,可以使用StringBuilderStringBuffer来进行字符串拼接操作。这两个类都是可变的字符串类,可以在原有字符串的基础上进行修改,而不需要创建新的字符串对象。这样可以避免频繁的字符串拼接操作,提高性能和内存利用率。

总之,Java通过缓存字符串来优化内存和性能。但是在进行大量的字符串拼接操作时,应该使用可变字符串类来避免性能和内存问题。

0