一个web服务器的实现(上)

来源:互联网 发布:关系数据库中的表 编辑:程序博客网 时间:2024/05/16 06:51
客户端(浏览器)与web服务器之间的交互主要包含客户的请求和服务器的应答。
请求和应答的格式在超文本传输协议(HTTP)中有定义。HTTP协议使用纯文本。

例如:
$telnet  www.ouc.edu.cn  80
Trying 211.64.150.68...
Connected to www.ouc.edu.cn(211.64.150.68)
Escape character is '^]'.
GET /index.html HTTP/1.0

HTTP/1.1  200  OK
Date: Wed, 21 Jun 2006  08:26:04 GMT
Server: Apache/2.0.54(Unix) DAV/2
.................................. 

原理是telnet创建了一个socket并调用了connect来连接到web服务器。服务器
接受连接请求,并创建了一个基于socket的从客户端的键盘到web服务进程的数据通道。接下来,客户端输入请求:
GET /index.html HTTP/1.0

一个HTTP请求包含有3个字符串。第一个字符串是命令,第二个是参数,第三个是所用协议的版本号。  *注意还有一空行

web服务器读取请求,检查请求,然后返回一个请求。应答有两部分:头部和内容。头部以状态行起始,如下所示:

HTTP/1.1  200  ok

状态行含有两个或更多的字符串。第一个串是协议的版本,第二个串是返回码,这里是200,其文本解释是OK。头部的其余部分是关于应答的附加信息。
应答的其余部分是返回的具体内容。


下面这个webserv.c就是一个web服务器的具体实现。

编译程序,在某个端口运行它:
$gcc webserv.c  -o  webserv
$./webserv  12345
就可以访问web服务器,网址为http://yourhostname:12345/  
将html文件放到该目录中并且用http://yourhostname:12345//filename.html就可以访问。
标签:HTTP

代码片段(1)[全屏查看所有代码]

1. [代码]webserv.c     跳至 [1] [全屏预览]

view source
print?
001/* webserv.c - a web server
002 
003 *      build: gcc webserv.c -o webserv
004 
005 */
006 
007#include    <stdio.h>
008 
009#include    <unistd.h>
010 
011#include    <sys/types.h>
012 
013#include    <sys/socket.h>
014 
015#include    <netinet/in.h>
016 
017#include    <netdb.h>
018 
019#include    <sys/stat.h>
020 
021#include    <time.h>
022 
023#include    <string.h>
024 
025 
026 
027#define   HOSTLEN  256
028 
029#define   BACKLOG  1
030 
031 
032 
033 
034 
035main(int ac, char *av[])
036 
037{
038 
039    int     sock, fd;
040 
041    FILE    *fpin;
042 
043    char    request[BUFSIZ];
044 
045 
046 
047    if ( ac == 1 ){
048 
049        fprintf(stderr,"usage: ws portnum\n");
050 
051        exit(1);
052 
053    }
054 
055    sock = make_server_socket( atoi(av[1]) );
056 
057    if ( sock == -1 ) exit(2);
058 
059 
060 
061    /* main loop here */
062 
063 
064 
065    while(1){
066 
067        /* take a call and buffer it */
068 
069        fd = accept( sock, NULL, NULL );
070 
071        fpin = fdopen(fd, "r" );
072 
073 
074 
075        /* read request */
076 
077        fgets(request,BUFSIZ,fpin);
078 
079        printf("got a call: request = %s", request);
080 
081        read_til_crnl(fpin);
082 
083 
084 
085        /* do what client asks */
086 
087        process_rq(request, fd);
088 
089 
090 
091        fclose(fpin);
092 
093    }
094 
095}
096 
097 
098 
099/* ------------------------------------------------------ *
100 
101   make_server_socket(int portnum)
102 
103   创建一个服务器套接字,并调用listen监听
104 
105   ------------------------------------------------------ */
106 
107 
108 
109int make_server_socket(int portnum)
110 
111{
112 
113    return make_server_socket_q(portnum, BACKLOG);
114 
115}
116 
117int make_server_socket_q(int portnum, int backlog)
118 
119{
120 
121    struct  sockaddr_in   saddr;   /* build our address here */
122 
123    struct  hostent     *hp;   /* this is part of our    */
124 
125    char    hostname[HOSTLEN];     /* address            */
126 
127    int sock_id;           /* the socket             */
128 
129 
130 
131    sock_id = socket(PF_INET, SOCK_STREAM, 0);  /* get a socket */
132 
133    if ( sock_id == -1 )
134 
135        return -1;
136 
137 
138 
139    /** build address and bind it to socket **/
140 
141 
142 
143    bzero((void *)&saddr, sizeof(saddr));   /* clear out struct     */
144 
145    gethostname(hostname, HOSTLEN);         /* where am I ?         */
146 
147    hp = gethostbyname(hostname);           /* get info about host  */
148 
149                                            /* fill in host part    */
150 
151    bcopy( (void *)hp->h_addr, (void *)&saddr.sin_addr, hp->h_length);
152 
153    saddr.sin_port = htons(portnum);        /* fill in socket port  */
154 
155    saddr.sin_family = AF_INET ;            /* fill in addr family  */
156 
157    if ( bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0 )
158 
159           return -1;
160 
161 
162 
163    /** arrange for incoming calls **/
164 
165 
166 
167    if ( listen(sock_id, backlog) != 0 )
168 
169        return -1;
170 
171    return sock_id;
172 
173}
174 
175 
176 
177 
178 
179/* ------------------------------------------------------ *
180 
181   read_til_crnl(FILE *)
182 
183   skip over all request info until a CRNL is seen
184 
185   ------------------------------------------------------ */
186 
187 
188 
189read_til_crnl(FILE *fp)
190 
191{
192 
193    char    buf[BUFSIZ];
194 
195    whilefgets(buf,BUFSIZ,fp) != NULL && strcmp(buf,"\r\n") != 0 )
196 
197        ;
198 
199}
200 
201 
202 
203
 
0 0
原创粉丝点击