与浏览器交互的web服务器

采用TCP/IP协议完成,涉及的头文件如下

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
  • socket()套接字创建:首先在主函数中定义socket套接字,断言套接字创建成功。
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
        assert( sockfd != -1 );

    分别定义两个socket_in结构体,saddr代表web服务器,caddr代表浏览器,设置web服务器端对应的信息,

协议族:AF_INET网络协议套接字类型即ipv4协议族,

端口号:80,

IP地址:ifconfig查看本地IP地址

 struct sockaddr_in saddr, caddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(80);//http
    saddr.sin_addr.s_addr = inet_addr("192.168.43.245");

bind()绑定:将相应的地址结构中的地址信息与套接字进行绑定。成功返回0,失败返回-1并设置error,断言绑定成功。

    int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    assert( res != -1 );

listen():将套接字设为监听模式,以及监听队列的最大长度5。

  listen(sockfd,5);

while循环

accept():接收浏览器的链接请求,执行系统调用的监听套接字,获取浏览器(caddr)socket的地址和长度。成功返回新的socket,该socket唯一标识这个链接,使用整形变量来接收,失败返回-1,程序退出本次循环。

      如果链接成功,打印请求链接方的IP地址

 int len = sizeof(caddr);

        int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
        if ( c < 0 )
        {
            continue;
        }

        printf("accept ip:%s\n",inet_ntoa(caddr.sin_addr));

       recv(): 创建空字符串接收浏览器发送的数据,即请求报头,如果失败返回-1,关闭连接退出本次循环。读取成功,打印接收到的数据,即浏览器的请求报头。    


        char recvbuff[1024] = {0};
        if ( recv(c,recvbuff,1023,0) <= 0 )
        {
            close(c);
            continue;
        }

        printf("recv:\n%s\n",recvbuff);

从接收到的请求报头中,获取请求方法,并设置即将执行的html文件名。


void get_filename(char buff[],char filename[])
{
    if ( buff == NULL || filename == NULL )
    {
        return;
    }

    char * s = strtok(buff," ");
    if ( s == NULL )
    {
        return;
    }

    printf("method:%s\n",s);//GET 
    s = strtok(NULL," ");
    if ( s == NULL || strcmp(s,"/") == 0  )
    {
        strcpy(filename,"/index.html");
        return;
    }

    strcpy(filename,s);

    return ;
}

当判断文件名为空时,回复报头,提示“NO filename”并关闭连接

char filename[128] = {0};
        get_filename(recvbuff,filename);//HTTP请求报文
        if ( filename[0] == 0 )//没有接收到文件
        {
            char sendbuff[512] = {0};
            strcpy(sendbuff,"HTTP/1.1 200 OK\r\n");
            strcat(sendbuff,"Server: myhttp\r\n");//strcat 拼接字符串
            strcat(sendbuff,"Content-Length: 12\r\n");
            strcat(sendbuff,"\r\n");//头部字段结束后需要添加一个空行
            strcat(sendbuff,"NO filename!");

            send(c,sendbuff,strlen(sendbuff),0);
            close(c);
            continue;
        }

接收到文件名成功,给出指定路径,将路径与文件名拼接,成为一个完整的可访问的path路径,

char path[256] = {"/home/tulunwang/src/myhttp"};
        strcat(path,filename);
        printf("path=%s\n",path);

     以只读的方式打开文件, 如果文件打开失败,即在给定的路径下资源没找到,回复报头,提示“not find file”,并关闭链接

 int fd = open(path,O_RDONLY);
        if ( fd == -1 )  //在给定路径下资源没找到
        {
            char sendbuff[512] = {0};
            strcpy(sendbuff,"HTTP/1.1 404 Not Found\r\n");
            strcat(sendbuff,"Server: myhttp\r\n");
            strcat(sendbuff,"Content-Length: 14\r\n");
            strcat(sendbuff,"\r\n");
            strcat(sendbuff,"not find file!");

            send(c,sendbuff,strlen(sendbuff),0);
            close(c);
            continue;

        }

文件打开成功,使用lseek()函数计算目标文件的大小,一起合并在应答报文中,输出应答报头,同时

       send()函数将报头发给浏览器

 int size = lseek(fd,0,SEEK_END);
        lseek(fd,0,SEEK_SET);

        char sendbuff[512] = {0};
        strcpy(sendbuff,"HTTP/1.1 200 OK\r\n");//成功,已规避两种风险
        strcat(sendbuff,"Server: myhttp\r\n");
        sprintf(sendbuff+strlen(sendbuff),"Content-Length:%d\r\n",size);
        //strcat(sendbuff,"Content-Length: 10\r\n");
        strcat(sendbuff,"\r\n");

        printf("sendbuff:\n%s\n",sendbuff);
        send(c,sendbuff,strlen(sendbuff),0);

  将使用read()函数,读取文件内容,通过send()函数将HTML内容发送给浏览器


        char databuff[1024] = {0};
        int num = 0;
        while( (num = read(fd,databuff,1024)) > 0 )
        {
            send(c,databuff,num,0);
        }

close(fd)关闭文件描述符

close(c)关闭套接字链接

  close(fd);
        close(c);

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
浏览器通过 Web 服务器与数据库交互的过程通常包含以下几个步骤: 1. 用户在浏览器上输入 URL,浏览器Web 服务器发送 HTTP 请求。 2. Web 服务器接收到请求后,会根据请求的内容进行处理,并将处理结果返回给浏览器。如果请求的内容需要从数据库中获取数据,Web 服务器会通过编写数据库查询语句来查询数据库。 3. 数据库接收到查询请求后,会根据查询语句查询数据库中的数据,并将查询结果返回给 Web 服务器。 4. Web 服务器将查询结果组织成 HTML 页面并将其返回给浏览器。 5. 浏览器接收到 Web 服务器返回的 HTML 页面后,会解析页面内容,并根据页面中包含的 JavaScript 代码与 Web 服务器进行交互,例如使用 AJAX 技术向 Web 服务器请求数据。 6. Web 服务器接收到 AJAX 请求后,会根据请求的内容进行处理,并将处理结果返回给浏览器。如果请求的内容需要从数据库中获取数据,Web 服务器同样会通过编写数据库查询语句来查询数据库,查询结果同样会返回给浏览器。 7. 浏览器接收到 Web 服务器返回的数据后,会根据数据内容更新页面内容,从而实现与数据库的交互。 需要注意的是,Web 服务器一般会充当中间层的角色,将浏览器发送的请求转发给数据库,并将数据库返回的数据包装成 HTML 页面返回给浏览器,起到了连接浏览器和数据库的桥梁作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值