C语言实现简单的http服务器(五毛钱的百度)

http协议是我们经常会用到的一个协议,比如浏览一个网站的时候,就会用到,http://www.xxx.xxx 这样的形式,有些时候不输入http就默认补充上,也有些是https,是针对http的一个升级版,是加密的,http是明文传输,在安全性上是有问题的。
今天就用c语言实现一个简单的http server,作为server就要监听来自客户端的访问,访问的内容同样也要回传给客户端。那么就可以用socket去实现。通过socket去传输超文本协议的内容,再通过浏览器去显示内容就可以了,这里用最简单的方式去实现,其中http协议得有头部,然后就是要有内容,如果没有http头的话,那就单纯是内容,就是普通文本了。待会给大家测试一下。

#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

char *read_file(char *filename, char *outstr)
{
    char str[1024*1024] = {0};
    if (!filename || !outstr)
    {
        printf("input error\n");
        return NULL;
    }
    FILE *fp = NULL;
    fp = fopen(filename, "r");
    if(!fp)
    {
        return NULL;
    }
    while( fgets(str, 1024*1024, fp) )
    {
        strcat(outstr,str);
        memset(str, 0, 1024*1024);
    }

    fclose(fp);
    return outstr;
}

int main(int argc, char *argv[])
{
    int server_sockfd;
    int client_sockfd;
    int len,pid;
    struct sockaddr_in server_addr;   
    struct sockaddr_in remote_addr; 
    int sin_size;
    char buf[BUFSIZ];  
    memset(&server_addr, 0, sizeof(server_addr)); 
    server_addr.sin_family = AF_INET; 
    server_addr.sin_addr.s_addr = INADDR_ANY; 

    server_addr.sin_port = htons(8888); 

    if((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("socket failed\n");
        exit(0);
    }
    
    if (bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
    {
        printf("bind failed\n");
        exit(0);
    }

 
    listen(server_sockfd, 5);
    sin_size = sizeof(struct sockaddr_in);
   
    while(1)
    {
        client_sockfd = accept(server_sockfd, (struct sockaddr *) &remote_addr, &sin_size);
       
        if (client_sockfd < 0)
        {
            error("failed on accept");
        }

        pid = fork();
        if (pid < 0)
        {
            error("failed on fork");
        }
        if (pid == 0)
        {
            close(server_sockfd);
            char header[] = "HTTP/1.0 200 OK\r\n\r\n";
            char html[1024*1024*10] = {0};
            recv(client_sockfd, buf, BUFSIZ, 0);
            printf("%s\n", buf);
            read_file("./baidu.html", html);
            send(client_sockfd,header,strlen(header),0);
            send(client_sockfd, html, strlen(html), 0);
           
            close(client_sockfd);
            exit(0);
        }
        close(client_sockfd);
    } 
    close(server_sockfd);
    return 0;
}

以上的代码向客户端发送的是百度首页的源码,直接右键查看源码,然后复制下来,保存起来。
在这里插入图片描述
向上图一样,这里好像不能传文件,随便找个html文件就好了。然后我们编译一下,运行。因为我绑定的是8888端口,所以web访问的时候加上端口。
在这里插入图片描述
不知道为啥显示成这样了,可能那个文件有点乱码吧,不懂前端先不管。原理大概就是这么原理,但是嗯,这就是五毛钱的百度,可以在里面搜索,跳转,以后别人给你两千块钱让你做个百度就这么做就好了,哈哈哈。把后台的打印也放上来:
在这里插入图片描述
会有http的头,这里如果我不给客户端返回http的头部的话,只传文本回去,看看会出现什么情况。
在这里插入图片描述
把发送头部注释掉,看看会发生什么。
在这里插入图片描述
就是我们文本的内容,所以头部还是很关键的,这是协议的标识,否则真的只是普通socket加上普通的流了。
我们平时使用的httpserver包括嵌入式常用的都是专门的web服务器来做http服务器,如经典的boa,nignx等等。配合cgi都会有比较好的效果。如果你不怕麻烦,也可以自己实现,放到公网服务器上,做个自己的网站,考虑并发也是一件很酷的事情。

发布了9 篇原创文章 · 获赞 5 · 访问量 1373

猜你喜欢

转载自blog.csdn.net/weixin_34153142/article/details/105311055