没想到看了How Tomcat Works的第一章第一节的代码示例,我似乎明白了二者的关系。带着疑问,写了如下代码,来验证自己的设想。
首先,使用java的socket模拟client,注意不是使用httpclient这种封装好的工具。
执行之后,控制台输出了页面的源码。
代码如下
public class SimpleHttpClient { public static void main(String[] args) throws Exception { Socket socket = new Socket("www.haosou.com", 80); PrintWriter writer = new PrintWriter(socket.getOutputStream(), true); BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream(), "utf-8")); writer.println("GET / HTTP/1.1"); writer.println("Host: www.haosou.com"); writer.println("Connection: keep-alive"); writer.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); writer.println("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"); writer.println("Accept-Language: zh-CN,zh;q=0.8"); writer.println(); // 木有这一行,阻塞 String line = reader.readLine(); while (line != null) { System.out.println(line); line = reader.readLine(); } writer.close(); reader.close(); socket.close(); } }
页面源码,如下
....
<script>LS.html2ls("stc_home_foot_js","stc_home_foot_js")</script>
</body>
</html>
篇幅原因,捧场的小伙伴可以自己跑下代码看一下。
如此,我基本验证了自己的猜想:Http是基于文本解析的约定,TCP负责传输
为了进一步验证,我又用Java的ServerSocket写了一个简陋的HttpServer,
启动该Server,也就是运行该代码,打开浏览器,在地址框输入http://localhost?name=Tom
可以看到页面显示了一个Tom的超链接,点击它,跳转到百度搜索的Tom页,当然,你可以不用Tom,而是用Jerry
代码如下,比较粗糙,将就看吧
public class SimpleHttpServer { public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(80); while (true) { Socket socket = server.accept(); new Task(socket).start(); } } } class Task extends Thread { private Socket socket; public Task (Socket socket) { this.socket = socket; } public void run () { try { PrintWriter writer = new PrintWriter(socket.getOutputStream(), true); BufferedReader reader = new BufferedReader(new InputStreamReader( socket.getInputStream(), "utf-8")); // 获取请求中的参数, 忽略header神马的 String firstLine = reader.readLine(); String name = parseName(firstLine); System.out.println("name:" + name); writer.println("<html>"); writer.println("<body>"); writer.println("<a href=\"https://www.baidu.com/s?wd=" + name +"&rsv_spt=1&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_pq=9f77f8020000142e&rsv_t=af959DHMVRjqn9YFbiJw6m4svc%2Bs125HBrbqHOXkBFUxxNS4zBQgMjxhX1xr4cGzySAr&inputT=900&rsv_sug3=22&rsv_sug1=21&rsv_sug2=0&rsv_sug4=900\">" + name + "</a>"); writer.println("</body>"); writer.println("</html>"); writer.println(); }catch (Exception e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } private String parseName(String line) { String query = line.substring(line.indexOf("?") + 1); query = query.substring(0, query.indexOf(" ")); return query.split("=")[1]; } public Socket getSocket() { return socket; } public void setSocket(Socket socket) { this.socket = socket; } }
好了,这就是我目前理解到的Http和TCP的关系:如果用快递做比喻的话,卖家发货给买家是http请求,宝贝是http内容,快递公司是tcp,卖家和买家知道宝贝的详情,而快递公司不需要知道是什么,只负责传输,买卖方也无需关注快递细节。这个和其他网络分层是一样的——下层无需关注上层的内容,逻辑上,就像两个http直接对话。希望这个比喻,能给小伙伴的理解带来一定帮助。
附件中是我写的两个类,感兴趣的同学可以下载下来,木有额外的依赖,只用到JDK的包,改下package,就能运行
能力有限,多多指教。