zoukankan      html  css  js  c++  java
  • 了解HTTP协议栈(实践篇)

      关于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协议详解之响应篇)

      首先写一个htmlhelloworld

    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++在这一方面又没有具体的标准。所以会有linuxwindows下的不同,不过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
    "+
     21             "Server: OneFile 1.0
    "+
     22             "Content-length: "+this.content.length+"
    "+
     23             "Content-type: "+MIMEType+"
    
    ";
     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=='
    '||c=='
    '||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中,在浏览器中访问。

       

      我们可以在tomcatwork目录(D: omcat-6.0.18workCatalinalocalhost estorgapachejsp)下找到一个名字为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
    ",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]='';
    51         printf("%s
    ",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 协议详解http://blog.csdn.net/gueter/article/details/1524447 

        Java版的http服务器http://blog.csdn.net/yanghua_kobe/article/details/7296156 

        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

      本文链接: http://www.cnblogs.com/wunaozai/p/3733432.html 

     

     

  • 相关阅读:
    [hibernate]org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter
    [extjs] extjs 5.1 API 开发 文档
    [java] Unsupported major.minor version 51.0 错误解决方案
    [kfaka] Apache Kafka:下一代分布式消息系统
    [spring] org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljav 解决
    [spring] 对实体 "characterEncoding" 的引用必须以 ';' 分隔符结尾
    [java] java 中Unsafe类学习
    [java] java 线程join方法详解
    [java] jstack 查看死锁问题
    ORACLE DG之参数详解
  • 原文地址:https://www.cnblogs.com/wunaozai/p/3733432.html
Copyright © 2011-2022 走看看