您的位置:首页 > 理论基础 > 计算机网络

了解HTTP协议栈(实践篇)

2016-03-28 20:38 495 查看
 关于http协议的理论知识,我在这里就不详细说明了,具体下面给出的链接有。接下来都是用具体的操作显示的,各位可以结合起来看。
  一、使用nc打开端口,并使用浏览器进行访问 (对应文章中的HTTP协议详解之请求篇)

  nc -lp 8888      #使用nc打开本地的8888端口


  使用浏览器,在地址栏上输入http://localhost:8888 进行访问(提出请求),此时nc界面上就会有得到一个请求的HTTP协议,具体的请求信息如下:

GET / HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/33.0.1750.154 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6


  


  


  请求后nc没有给出回应的话,浏览器会一直在该页面进行等待。如果手动结束nc程序的话,由于没有给出回应信息,浏览器会给出无法访问该页面。

  二、nc后面接着一个资源文件(对应文章中的HTTP协议详解之响应篇)
  首先写一个html的helloworld

1 <html>
2 <head>
3 <title>welcome</title>
4 <head>
5 <body>
6 <h1>Hello World</h1>
7 </body>
8 </html>


  然后再命令行中输入

nc -lp 8888 < helloworld.html


  再浏览器中进行访问就可以得到一个页面了
  


  我们打开浏览器的开发工具,chrome浏览器的快捷键是F12,再network中可以看到下面信息
  


  可以看到里面有200 OK这个响应类别号

  三、代码实现一个简单的服务器(这里给出一个网上的java实现)
  没有办法,http服务器,就要用到Socket编程,而c++在这一方面又没有具体的标准。所以会有linux和windows下的不同,不过java在这方面就没有问题了,先给出个java版的尝尝鲜。代码虽然多,但是具体不难理解。





1 import java.io.*;
2 import java.net.ServerSocket;
3 import java.net.Socket;
4
5
6 public class SingleFileHTTPServer extends Thread {
7
8     private byte[] content;
9     private byte[] header;
10     private int port=80;
11
12     private SingleFileHTTPServer(String data, String encoding,
13                 String MIMEType, int port) throws UnsupportedEncodingException {
14         this(data.getBytes(encoding), encoding, MIMEType, port);
15     }
16
17     public SingleFileHTTPServer(byte[] data, String encoding, String MIMEType, int port)throws UnsupportedEncodingException {
18         this.content=data;
19         this.port=port;
20         String header="HTTP/1.0 200 OK\r\n"+
21             "Server: OneFile 1.0\r\n"+
22             "Content-length: "+this.content.length+"\r\n"+
23             "Content-type: "+MIMEType+"\r\n\r\n";
24         this.header=header.getBytes("ASCII");
25     }
26
27     public void run() {
28         try {
29             ServerSocket server=new ServerSocket(this.port);
30             System.out.println("Accepting connections on port "+server.getLocalPort());
31             System.out.println("Data to be sent:");
32             System.out.write(this.content);
33
34             while (true) {
35                 Socket connection=null;
36                 try {
37                     connection=server.accept();
38                     OutputStream out=new BufferedOutputStream(connection.getOutputStream());
39                     InputStream in=new BufferedInputStream(connection.getInputStream());
40
41                     StringBuffer request=new StringBuffer();
42                     while (true) {
43                         int c=in.read();
44                         if (c=='\r'||c=='\n'||c==-1) {
45                             break;
46                         }
47                         request.append((char)c);
48
49                     }
50
51                         //如果检测到是HTTP/1.0及以后的协议,按照规范,需要发送一个MIME首部
52                         if (request.toString().indexOf("HTTP/")!=-1) {
53                             out.write(this.header);
54                         }
55
56                         out.write(this.content);
57                         out.flush();
58
59                 } catch (IOException e) {
60                     // TODO: handle exception
61                 }finally{
62                     if (connection!=null) {
63                         connection.close();
64                     }
65                 }
66             }
67
68         } catch (IOException e) {
69             System.err.println("Could not start server. Port Occupied");
70         }
71     }
72
73     public static void main(String[] args) {
74         try {
75             String contentType="text/plain";
76             if (args[0].endsWith(".html")||args[0].endsWith(".htm")) {
77                 contentType="text/html";
78             }
79
80             InputStream in=new FileInputStream(args[0]);
81             ByteArrayOutputStream out=new ByteArrayOutputStream();
82             int b;
83             while ((b=in.read())!=-1) {
84                 out.write(b);
85             }
86             byte[] data=out.toByteArray();
87
88             //设置监听端口
89             int port;
90             try {
91                 port=Integer.parseInt(args[1]);
92                 if (port<1||port>65535) {
93                     port=80;
94                 }
95             } catch (Exception e) {
96                 port=80;
97             }
98
99             String encoding="ASCII";
100             if (args.length>2) {
101                 encoding=args[2];
102             }
103
104             Thread t=new SingleFileHTTPServer(data, encoding, contentType, port);
105             t.start();
106
107         } catch (ArrayIndexOutOfBoundsException e) {
108              System.out.println("Usage:java SingleFileHTTPServer filename port encoding");
109         }catch (Exception e) {
110             System.err.println(e);// TODO: handle exception
111         }
112     }
113 }


View Code

  四、jsp等动态网站的问题
  在myeclipse中创建一个web工程,然后创建一个index.jsp文件





1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
3 <html>
4   <head>
5    <title>welcome</title>
6   </head>
7   <body>
8     <% String str="<h1>Hello JSP</h1>"; %>
9     <% out.println(str); %>
10   </body>
11 </html>


View Code
  然后部署在tomcat中,在浏览器中访问。
  


  我们可以在tomcat的work目录(D:\tomcat-6.0.18\work\Catalina\localhost\test\org\apache\jsp)下找到一个名字为index_jsp.java的文件。
  


  使用servlet,对jsp文件进行打印输出。具体的原理我也不是很懂,可以看《How Tomcat Works》。不过我想最后还是输出成一个html文件不然在客户端查看源代码怎么会是html呢。
  


  其他的动态语言应该也是这个思路了。

  五、图解服务器-客户端连接过程(单服务器)
  


六、C++版的Http服务器(Linux Socket)
  在centos 6.4 g++/gcc4.4.7





1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/socket.h>
4 #include <netinet/in.h>
5 #include <string.h>
6 #include <arpa/inet.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9
10 int main(int argc,char * argv[])
11 {
12     int server_sockfd;
13     int client_sockfd;
14     int len;
15     struct sockaddr_in my_addr;
16     struct sockaddr_in remote_addr;
17     socklen_t sin_size;
18     char buf[BUFSIZ];
19     memset(&my_addr,0,sizeof(my_addr));
20     my_addr.sin_family=AF_INET;
21     my_addr.sin_addr.s_addr=INADDR_ANY;
22     my_addr.sin_port=htons(8888);
23
24     if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)
25     {
26         perror("socket");
27         return -1;
28     }
29     if(bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)
30     {
31         perror("bind");
32         return -1;
33     }
34
35     listen(server_sockfd,5);
36     sin_size=sizeof(struct sockaddr_in);
37
38     if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&remote_addr,&sin_size))<0)
39     {
40         perror("accept");
41         return -1;
42     }
43
44     printf("accept client %s\n",inet_ntoa(remote_addr.sin_addr));
45     char *pch="<html><h1>Hello World</h1></html>";
46     len=send(client_sockfd,pch,strlen(pch),0);
47
48     while((len=recv(client_sockfd,buf,BUFSIZ,0))>0)
49     {
50         buf[len]='\0';
51         printf("%s\n",buf);
52         /*
53         if(send(client_sockfd,buf,len,0)<0)
54         {
55             perror("write");
56             return -1;
57         }
58         */
59     }
60     close(client_sockfd);
61     close(server_sockfd);
62
63     return 0;
64 }


View Code
  该代码还没有实现判断后缀文件,多用户连接,返回的状态码等问题。这个只是一个简单的服务器。如果你对服务器有兴趣可以查看服务器源代码。apache我们看不懂。一个小一点的http总能看懂吧。

  


  参考资料:
    Nc 下载: http://joncraton.org/blog/46/netcat-for-windows/
    Nc 的使用: http://freetstar.com/use-nc-in-the-linux/
    Http 协议详解: /article/1775657.html
    Java版的http服务器: /article/1503471.html
    C++版的Http服务器: http://www.cppblog.com/kevinlynx/archive/2008/07/30/57521.html
    TCP Socket linux: http://blog.csdn.net/wangyf101/article/details/9790807
  资料下载: http://files.cnblogs.com/wunaozai/%E4%BA%86%E8%A7%A3HTTP%E5%8D%8F%E8%AE%AE%E6%A0%88.zip
  本文链接: /article/6193109.html

作者:无脑仔的小明

出处:http://www.cnblogs.com/wunaozai/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

如果文中有什么错误,欢迎指出。以免更多的人被误导。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: