關於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 }
四、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>
然后部署在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 }
該代碼還沒有實現判斷后綴文件,多用戶連接,返回的狀態碼等問題。這個只是一個簡單的服務器。如果你對服務器有興趣可以查看服務器源代碼。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