Java Socket HTTP GET 请求
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头部,但我不知道应该添加哪些。
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规范,避免出现请求格式错误的问题。
Java在内存中缓存所有的字符串以便重复使用,这是出于内存优化和性能方面的考虑。当Java创建一个字符串时,它会首先检查内存中是否已经存在相同内容的字符串对象,如果存在,则直接返回该对象的引用,而不需要创建新的字符串对象。这样可以避免重复创建相同内容的字符串,减少内存占用。
Java使用字符串常量池来实现字符串的缓存。字符串常量池是在堆内存中的一个特殊的内存区域,用于存储所有字符串常量。当Java编译器遇到字符串常量时,它会首先检查常量池中是否已经存在相同内容的字符串,如果存在,则直接使用该字符串的引用。如果常量池中没有相同内容的字符串,则会在常量池中创建一个新的字符串对象,并返回其引用。
通过缓存字符串,Java可以减少内存中相同内容字符串的数量,提高内存利用率。此外,由于字符串是不可变的,缓存字符串还可以避免频繁创建和销毁字符串对象,减少垃圾回收的频率,提高程序的性能。
然而,如果使用字符串拼接的方式来连接大量的字符串,比如在循环中使用"+"操作符来拼接字符串,会导致性能和内存问题。每次进行字符串拼接时,Java都会创建一个新的字符串对象,并将拼接结果复制到新的字符串对象中。这样就会导致大量的临时字符串对象被创建,占用大量的内存,并且由于字符串是不可变的,这些临时字符串对象无法被回收,最终会导致垃圾回收的频繁运行。
为了避免这个问题,可以使用StringBuilder
或StringBuffer
来进行字符串拼接操作。这两个类都是可变的字符串类,可以在原有字符串的基础上进行修改,而不需要创建新的字符串对象。这样可以避免频繁的字符串拼接操作,提高性能和内存利用率。
总之,Java通过缓存字符串来优化内存和性能。但是在进行大量的字符串拼接操作时,应该使用可变字符串类来避免性能和内存问题。