用Java Socket 实现发送HTTP请求和读取响应。
public class LearnHttp { private static final byte CR = '\r'; private static final byte LF = '\n'; private static final byte[] CRLF = {CR, LF}; public static void main(String[] args) throws UnknownHostException, IOException { new LearnHttp().testHttp(); } public void testHttp() throws UnknownHostException, IOException { String host = "www.baidu.com"; Socket socket = new Socket(host, 80); OutputStream out = socket.getOutputStream(); InputStream in = socket.getInputStream(); // 在同一个TCP连接里发送多个HTTP请求 for(int i = 0; i < 2; i++) { writeRequest(out, host); readResponse(in); System.out.println("\n\n\n"); } } private void writeRequest(OutputStream out, String host) throws IOException { // 请求行 out.write("GET /index.html HTTP/1.1".getBytes()); out.write(CRLF); // 请求头的每一行都是以CRLF结尾的 // 请求头 out.write(("Host: " + host).getBytes()); // 此请求头必须 out.write(CRLF); out.write(CRLF); // 单独的一行CRLF表示请求头的结束 // 可选的请求体。GET方法没有请求体 out.flush(); } private void readResponse(InputStream in) throws IOException { // 读取状态行 String statusLine = readStatusLine(in); System.out.println("statusLine :" + statusLine); // 消息报头 Map<String, String> headers = readHeaders(in); int contentLength = Integer.valueOf(headers.get("Content-Length")); // 可选的响应正文 byte[] body = readResponseBody(in, contentLength); String charset = headers.get("Content-Type"); if(charset.matches(".+;charset=.+")) { charset = charset.split(";")[1].split("=")[1]; } else { charset = "ISO-8859-1"; // 默认编码 } System.out.println("content:\n" + new String(body, charset)); } private byte[] readResponseBody(InputStream in, int contentLength) throws IOException { ByteArrayOutputStream buff = new ByteArrayOutputStream(contentLength); int b; int count = 0; while(count++ < contentLength) { b = in.read(); buff.write(b); } return buff.toByteArray(); } private Map<String, String> readHeaders(InputStream in) throws IOException { Map<String, String> headers = new HashMap<String, String>(); String line; while(!("".equals(line = readLine(in)))) { String[] nv = line.split(": "); // 头部字段的名值都是以(冒号+空格)分隔的 headers.put(nv[0], nv[1]); } return headers; } private String readStatusLine(InputStream in) throws IOException { return readLine(in); } /** * 读取以CRLF分隔的一行,返回结果不包含CRLF */ private String readLine(InputStream in) throws IOException { int b; ByteArrayOutputStream buff = new ByteArrayOutputStream(); while((b = in.read()) != CR) { buff.write(b); } in.read(); // 读取 LF String line = buff.toString(); return line; } }
值得记下的教训:
InputStream.read()返回-1表示流的结束,即流被关闭了。在这次实现同一个Socket发送多个HTTP请求的过程中,一开始总是以为一个响应报文的结束是在InputStream.read返回-1时,导致第一次读取响应时总是很久才结束,第二次的请求虽然发出去了,但响应总是空的。
读取第一次请求的响应要很久是因为,这是在等待服务器关闭连接,百度的基本上是60秒。第二次是空的是因为,请求虽然发出去了,但服务器写响应的流已经被关闭,所以也读不到响应。
导致这个问题的根本原因在于没有记住:TCP是面向流的,并不知道传输的消息的开始和结束,这是由上层的协议去控制的,这里是HTTP协议。
欢迎关注我的微信公众号: coderbee笔记。
相关推荐
javac Server.java java.exe Server 查看说明 可以简单得到http请求头 便于分析http
**Java中的HTTP和Socket** 1. **Java HTTP客户端**:Java内置的HttpURLConnection或第三方库如Apache HttpClient可以用来发送HTTP请求和处理响应。 2. **Java Socket编程**:使用java.net.Socket和ServerSocket类,...
Java Socket编程是网络编程的基础,它提供了在两个应用程序之间建立通信连接的能力。在这个场景中,我们讨论的是如何使用Java的Socket来实现文件上传功能,即从客户端将文件发送到服务器,然后保存到服务器的数据库...
标签中的"java socket http"表明这个例子可能涉及HTTP协议。HTTP协议是基于TCP/IP的应用层协议,而Socket编程是TCP/IP通信的基础。在实际的HTTP服务中,服务器会解析HTTP请求,然后返回适当的HTTP响应。在我们的简单...
总的来说,Java Socket在处理Nginx TCP转发时获取用户真实IP的关键在于正确解析和处理HTTP请求头中的"X-Forwarded-For"字段。同时,对网络架构和安全性的理解也是至关重要的。通过深入研究相关代码和实验,可以增强...
java 用socket 下载http 网页, 供参考, 其精髓是socket和http头部报文
- 在Java Socket中实现HTTP服务器,需要解析HTTP请求(GET、POST等),并返回适当的HTTP响应。 - GET请求通常用于获取资源,POST请求用于向服务器提交数据。 - 文件上传涉及到处理multipart/form-data格式的POST...
8. **Java的网络功能与编程**:基础知识—Java的网络功能与编程(1).chm这部分可能介绍了Java的网络编程基础,如URL、URLConnection等,以及如何使用它们进行HTTP请求。 学习Java Socket编程不仅需要理解TCP/IP协议...
1. 满足具有Socket客户端需求的基本应用. 2. 满足具有Socket服务端的基本应用. 具备并发能力, 能满足可设定个数客户端连接. ...参考个人博客: http://blog.csdn.net/ostrichmyself/article/details/6618349
学习这个简单的Java Socket程序,可以让你了解网络通信的基本原理,为进一步的网络编程,如HTTP、FTP等协议的实现打下基础。同时,也可以帮助你掌握Java的IO流操作,这对于处理任何类型的数据传输都是非常重要的。
1. 纯Java实现的HTTP下载客户端,不借助任何第三方库 2. 可以任意类型文件下载 3. 基于JAVA Socket编程 4. 演示了SwingUI如何通过Model更新View 5. 下载以后双击Jar就可以运行
Java Socket编程是网络编程中的重要组成部分,主要用于在两台计算机之间建立双向通信通道,实现数据的交换。在Java中,Socket类和ServerSocket类是进行网络通信的核心工具,它们提供了客户端与服务器之间的连接和...
Java Socket是Java编程语言中用于网络通信的核心API,它提供了低级别的、面向连接的、基于TCP/IP的通信机制。在Java中,Socket是基于TCP(传输控制协议)的,为应用程序提供了一种可靠的、双向的通信方式。通过...
在Java编程中,Socket是网络通信的基础,它允许两个应用程序通过TCP/IP协议进行数据传输。Socket连接分为两种类型:长连接和短连接。这两种连接方式各有特点,适用于不同的应用场景。 **1. 短连接(Short ...
虽然Java Socket是基于TCP/IP协议的,但实际的聊天室应用可能还涉及到其他协议,如HTTP、FTP等,具体取决于项目的复杂性和需求。 以上就是基于Java Socket实现的聊天室所涉及的主要技术点,这个项目对于学习网络...
本话题主要探讨如何使用Socket实现HTTP下载,这对于理解HTTP协议的工作原理和深入学习网络编程至关重要。 HTTP(超文本传输协议)是互联网上应用最广泛的一种网络协议,它定义了客户端和服务器之间的数据交互格式。...
Java Socket实现简单的Web服务器是一个基础但实用的编程实践,它涉及到网络编程、HTTP协议和文件I/O等核心概念。在本项目中,我们利用Java的Socket API构建了一个基本的服务器,该服务器仅处理HTTP GET请求并返回...
- 连接到服务器:`Socket socket = IO.socket("http://your-server-url:port");` - 注册事件监听器:例如,`socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {...});` 用于监听连接成功事件。 - 发送和...
- Java Socket遵循TCP/IP协议栈,包括IP、TCP、应用层协议(如HTTP、FTP等)。理解这些协议有助于理解Socket的工作机制。 - 协议文档提供了Socket通信的具体规则,如报文格式、连接建立和关闭的流程等。 7. **...
在Java编程语言中,使用Socket实现一个简单的HTTP服务器是一项基础但重要的技能。HTTP服务器是互联网上用于接收HTTP请求并返回响应的程序。本教程将详细解释如何通过Socket类来构建这样的服务器,同时会涉及到相关的...