zoukankan      html  css  js  c++  java
  • Server Develop (九) Simple Web Server

    Simple Web Server

      web服务器hello world!-----简单的socket通信实现。

    HTTP

      HTTP是Web浏览器与Web服务器之间通信的标准协议,HTTP指明了客户端如何与服务器建立连接,如果从服务器请求数据,服务器如何响应请求,关闭连接。HTTP是使用TCP/IP协议进行传输数据的,也就是传输层利用TCP进行连接,进行可靠连接的。

    详情:点击

    请求

    一般格式,如:

      GET /index.html HTTP/1.0
      Accept:text/html,text/plain
      User-Agent: Lyn
      Host:www.server.com

    我们主要需要的信息在第一行,共包括三个字段。

    • 第一个字段(GET)为请求动作类型:
      • GET代表请求的操作,表示要求服务器返回资源的表示;
      • HEAD表示只需要文件的首部;
      • PUT表示向服务器上传资源;
      • POST主要是向服务器发送表单数据.
    • 第二个字段(/index.html),标识服务器上所请求的资源的相对URL,必须要以"/"开头,Web浏览器在发送请求的时候会自动加上服务器的主机名。
    • 第三个字段(HTTP/1.0),客户端理解的协议版本

    注意: 

      每一个HTTP请求都要以两个回车换行结束( )
      GET发送查询字符串主要直接将查询字符串附加到URL后面,如下表示:GET /index.html/user=XXX&Age HTTP/1.0

    响应

     一般格式,如

    HTTP/1.1 200 OK
    Date:Mon 15
    Server:xxxxxx
    Content-Type:text/html;
    Content-length:xxx 代表文档的多少个字节,不包含首部字节数

    <html><head><title>Hello</title></head><body>Test</body></html>

      我们需要大概构造这样的一个格式来回复浏览器。

      所以,必须包含第一行的状态行、内容的格式、内容的长度和具体的内容。

    实例

    /*
     * A Simple Web Server
     */
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <error.h>
    
    #define PORT 9000
    
    #define EOL "
    "
    #define EOL_SIZE 2
    
    int recv_new(int fd, char *buffer); 
    void send_new(int fd, char *msg);
    
    int main(int argc, char* argv[])
    {
        int serv_fd;
        int client_fd;
    
        int ret;
    
        pid_t pid;
        struct sockaddr_in serv_addr;
        struct sockaddr_in client_addr;
        int    len = sizeof(struct sockaddr_in);
    
        serv_fd = socket(AF_INET, SOCK_STREAM, 0);
        if(serv_fd < 0){
            perror("create socket fail !
    ");
            exit(1);
        }
        
        bzero(&serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        serv_addr.sin_port = htons(PORT);
    
        int on = 1;
        ret = setsockopt(serv_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));
        if(ret < 0){
            perror("setsockopt fail !
    ");
            exit(1);
        }
        
        ret = bind(serv_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
        if(ret < 0){
            perror("bind fail !
    ");
            exit(1);
        }
    
        ret = listen(serv_fd, 5);
        if(ret < 0){
            perror("listen fail !
    ");
            exit(1);
        }
    
        while(1){
            client_fd = accept(serv_fd, (struct sockaddr*)&client_addr, &len);
            if(client_fd < 0){
                perror("accept fail !
    ");
                continue;
            }
            char buffer[200];
            recv_new(client_fd, buffer);
            printf("recv buffer: %s
    ", buffer);
            char content[] = "<head><head><title>index.html</title></head><body>hello world!</body>";
            char response[512];
            sprintf(response, "HTTP/1.1 200 OK
    Content-Type: text/html
    Content-Length: %d
    
    %s", strlen(content), content);
            send(client_fd, response, sizeof(response), 0);
            close(client_fd);
        }
    
        return 0;
    }
    
    int recv_new(int fd, char *buffer) {
        char *p = buffer; // Use of a pointer to the buffer rather than dealing with the buffer directly
        int eol_matched = 0; // Use to check whether the recieved byte is matched with the buffer byte or not
        while (recv(fd, p, 1, 0) != 0) // Start receiving 1 byte at a time
        {
            if (*p == EOL[eol_matched]) // if the byte matches with the first eol byte that is '
    '
            {
                ++eol_matched;
                if (eol_matched == EOL_SIZE) // if both the bytes matches with the EOL
                {
                    *(p + 1 - EOL_SIZE) = ''; // End the string
                    return (strlen(buffer)); // Return the bytes recieved
                }
            } else {
                eol_matched = 0;
            }
            p++; // Increment the pointer to receive next byte
        }
        return (0);
    }

    参考

    http://computerdragon.blog.51cto.com/6235984/1191176

    http://www.cnblogs.com/lynch_world/archive/2011/04/24/2026413.html

    http://css.dzone.com/articles/web-server-c

  • 相关阅读:
    学无止境,我爱python
    Flask目录
    Django目录
    前端目录
    python目录
    MySQL目录
    Oracle与Sql server的区别
    Git
    restful规范
    Django 解决跨域问题(写入到中间件中)
  • 原文地址:https://www.cnblogs.com/coder2012/p/3402221.html
Copyright © 2011-2022 走看看