小威
...

  1.练习 : 简单的Web服务器

 1 #ifndef _HEAD_H_
 2 #define _HEAD_H_
 3 
 4 #include <stdio.h>
 5 #include <string.h>
 6 #include <stdlib.h>
 7 #include <fcntl.h>
 8 #include <sys/socket.h>
 9 #include <arpa/inet.h>
10 #include <unistd.h>
11 
12 #define MAX 1024
13 #define MAX_LISTEN 10
14 #define MAX_PATH 37
15 #define MAX_NAME 18
16 
17 #define SER_IP "127.0.0.1"
18 #define SER_PORT 8000
19 #define ROOT "./www"
20 
21 #define REPLY_HEAD "HTTP/1.1 200 OK\r\nContent-Type:"
22 #define TEXT "text/html"
23 //#define IMG "image/html"
24 #define IMG "jpg/html"
25 #define REPLY_END "\r\n\r\n"
26 
27 void perror_exit(char *);
28 
29 #endif//_HEAD_H_
heah.h
  1 //main.c
  2 #include "head.h"
  3 
  4 void perror_exit(char *str)
  5 {
  6     perror(str);
  7     exit(1);
  8 }
  9 
 10 int main(int argc, char *argv[])
 11 {
 12     int fd_socket = 0, opt = 1, err = 0, fd_ctl = 0, len = 0, fd_write;
 13     struct sockaddr_in serve_addr;
 14     char buf[MAX] = {0};
 15     char *start = NULL, *end = NULL, *type = NULL, *filename = NULL;
 16     char *asgv[2] = {0};
 17 
 18     fd_socket = socket(AF_INET, SOCK_STREAM, 0);
 19 
 20     bzero(&serve_addr, sizeof(serve_addr));
 21     serve_addr.sin_family = AF_INET;
 22     serve_addr.sin_port = htons(SER_PORT);
 23     inet_pton(AF_INET, SER_IP, &serve_addr.sin_addr.s_addr);
 24 
 25     err = setsockopt(fd_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 26     if(-1 == err) {
 27         perror_exit("setsockopt");
 28     }
 29     err = bind(fd_socket, (struct sockaddr *)&serve_addr, sizeof(serve_addr));
 30     if(-1 == err) {
 31         perror_exit("bind");
 32     }
 33     err = listen(fd_socket, MAX_LISTEN);
 34     if(-1 == err) {
 35         perror_exit("listen");
 36     }
 37 
 38     while(1)
 39     {
 40         char path[MAX_PATH] = {0};
 41 
 42         bzero(buf, sizeof(buf));
 43         len = 0;
 44         //fd_ctl = accept(fd_socket, &serve_addr, sizeof(serve_addr));
 45         fd_ctl = accept(fd_socket, NULL, NULL);
 46         if(-1 == fd_ctl) {
 47             perror_exit("accept");
 48         }
 49         len = read(fd_ctl, buf, MAX);
 50         if(-1 == len) {
 51             perror_exit("read");
 52         }
 53         buf[len] = '\0';
 54         start = strstr(buf, " ");
 55         end = strstr(start + 1, " ");
 56         *end = '\0';
 57         filename = start + 2;
 58         printf("filename == %s\n", filename);
 59         if(0 == strlen(filename)) {
 60             filename = "index.html";
 61         }
 62         printf("filename == %s\n", filename);
 63         sprintf(path, "%s/%s", ROOT, filename);
 64         printf("path == %s\n", path);
 65         err = access(path, X_OK);
 66         if(0 == err)
 67         {
 68             pid_t pid = 0;
 69             write(fd_ctl, REPLY_HEAD, strlen(REPLY_HEAD));
 70             write(fd_ctl, TEXT, strlen(TEXT));
 71             write(fd_ctl, REPLY_END, strlen(REPLY_END));
 72 
 73             pid = fork();
 74             if(-1 == pid) {
 75                 perror_exit("fork");
 76             }
 77             if(0 == pid) {
 78                 dup2(fd_ctl, STDOUT_FILENO);
 79                 asgv[0] = path;
 80                 asgv[1] = NULL;
 81                 execvp(asgv[0], asgv);
 82             }
 83             else {
 84                 close(fd_ctl);
 85                 wait(NULL);
 86             }
 87         }
 88         else {
 89             start = rindex(filename, '.');
 90             //if((! strcmp(start, "png")) || (! strcmp(start, "jpg"))) {
 91             if((! strcmp(start, "jpg"))) {
 92                 type = IMG;
 93             }
 94             else {
 95                 type = TEXT;
 96             }
 97 
 98             fd_write = open(path, O_RDONLY);
 99             if(fd_write != -1) {
100                 write(fd_ctl, REPLY_HEAD, strlen(REPLY_HEAD));
101                 write(fd_ctl, type, strlen(type));
102                 write(fd_ctl, REPLY_END, strlen(REPLY_END));
103 
104                 while((len = read(fd_write, buf, MAX)))
105                 {
106                     write(fd_ctl, buf, len);
107                 }
108 
109                 close(fd_write);
110             }
111         }
112         close(fd_ctl);
113     }
114 
115     return 0;
116 }
main.c

  2.首先运行编译好的文件

   打开浏览器 , 输入127.0.0.1:8000访问服务器

  3.UNIX Doamin Socket IPC

    优点 :更有效率 , 不需要经过网络协议栈,不需要打包拆包,计算效验和,维护序号和应答等,只需要将应用层数据从一个进程拷贝到另一个进程。

    原因 : IPC机制本质上是可靠的通讯 而网络通讯协议是为不可靠通讯设计的。

    扩展:面向流,数据报,消息时都是可靠的,即不会丢失也不会顺序错乱。

    是全双工的

    不同点 :UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示

  4,网络编程的地址是IP地址加端口号

    UNIX Doamin Socket IPC 的地址是一个socket类型的文件在文件系统的路径

  5.注意程序中的offsetof宏,它在stddef.h头文件中定义

    #define offsetof(TYPE, MEMBER)  ((int) & ((TYPE *) 0) -> MEMBER)

     作用 :测量结构里面成员的偏移量

    offsetof(struct sockaddr_un, sun_path)就是取sockaddr_un结构体的sun_path成员在结构体中的偏移,也就是从第几个字节开始是sun_path成员

  6.注意事项 :在回头http协议中每一行的末尾都是回车加换行

     HTTP头的第二行表示即将发送的文件的类型(称为)

      Text/html  

      纯文本文件是text/plain

      图片则是image/jpg, image/png 

    

posted on 2013-09-23 20:05  小威_  阅读(199)  评论(0编辑  收藏  举报