c语言编写一个简单的服务器<中级版>

这次加上了响应代码
编写服务器源代码winhttp.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>


#define SERVER_PORT 80

static int debug =1;

void do_http_request(int client_sock);

void do_http_response(int client_sock); 

int get_line(int sock,char *buf,int size);
int main(){

    int sock;//
    struct sockaddr_in server_addr;

    sock=socket(AF_INET,SOCK_STREAM,0);

    bzero(&server_addr,sizeof(server_addr));

    server_addr.sin_family=AF_INET;//选择协议族
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//监听本地所有IP地址

    server_addr.sin_port=htons(SERVER_PORT);//绑定端口号

    bind(sock,(struct sockaddr *)&server_addr,sizeof(server_addr));


    listen(sock,120);

    printf("等待客户端的连接\n");
    

    int done=1;

    while(done){
        struct sockaddr_in client;
        int client_sock,len,i;
        char client_ip[64];
        char buf[256];

        socklen_t client_addr_len;
        client_addr_len=sizeof(client);
        client_sock=accept(sock,(struct sockaddr *)&client,&client_addr_len);

        printf("Client ip:%s\t port:%d\n",inet_ntop(AF_INET,&client.sin_addr.s_addr,client_ip,sizeof(client_ip)),ntohs(client.sin_port));

        do_http_request(client_sock);

        close(client_sock);
    }
    close(sock);
    return 0;
}
void do_http_request(int client_sock){

    int len=0;
    char buf[256];
    char method[64];
    char url[256];
    char path[512];


    
    len=get_line(client_sock,buf,sizeof(buf));

    if(len>0){
        int i=0,j=0;
        while(!isspace(buf[j]) && (i<sizeof(method)-1)){
            method[i]=buf[j];
            i++;
            j++;
        }

        method[i]='\0';
        printf("request method:%s\n",method);


        //处理get请求
        if(strncasecmp(method,"GET",i)==0){
            if(debug){
                printf("method=GET\n");
            }

            //跳过空格
            while(isspace(buf[j++]));

            i=0;
            //读取url
            while(!isspace(buf[j]) && (i<sizeof(url)-1)){
                url[i]=buf[j];
                i++;
                j++;
            }
            url[i]='\0';

            if(debug) {
                printf("url:%s\n",url);
            }


            //继续读取header
            do{
                len=get_line(client_sock,buf,sizeof(buf));
                if(debug)  printf("read line :%s\n",buf);
            }while(len>0);

            char *pos=strchr(url,'?');
            if(pos){
                *pos='\0';
                printf("real url:%s\n",url);
            }

            sprintf(path,"./html_docs/%s",url);
            if(debug) printf("path:%s\n",path);

            //执行http响应
            do_http_response(client_sock);

        }else{
            //识别非get请求
            fprintf(stderr,"Warning!other request [%s]\n",method);


            //继续读取header
            do{
                len=get_line(client_sock,buf,sizeof(buf));
                if(debug)  printf("read line :%s\n",buf);
            }while(len>0);
        
        } 

        

    }else{

    }

    
}


void do_http_response(int client_sock){
    const char* main_header=" HTTP/1.0 200 OK \r\n Server:Linux Server\r\n Content-type: text/html\r\n Connection:Close\r\n";
    const char* content="<!DOCTYPE html>\n\
<html lang=\"en\">\n\
<head>\n\
    <meta charset=\"UTF-8\">\n\
    <title>Index</title>\n\
</head>\n\
<body>\n\
<h1>大家好,我是陈东谱,有什么问题欢迎大家加我微信,我的微信号是:<font color='red'>reg183</font></h1>\n\
</body>\n\
</html>";

    int len=write(client_sock,main_header,strlen(main_header));

    if(debug) fprintf(stdout,"...do_http_response...");
    if(debug) fprintf(stdout,"write[%d]:%s",len,main_header);

    char send_buf[64];
    int wc_len=strlen(content);
    len=snprintf(send_buf,64,"Content-Length:%d\r\n\r\n",wc_len);

    len=write(client_sock,send_buf,len);

    if(debug){
        fprintf(stdout,"write[%d]:%s",len,send_buf);
    }

    len=write(client_sock,content,wc_len);

    if(debug){
        fprintf(stdout,"write[%d]:%s",len,content);

    }



}

int get_line(int sock,char *buf,int size){

    int count=0;
    char ch='\0';
    int len=0;
    while((count<size-1) && ch!='\n'){

        len=read(sock,&ch,1);
        if(len==1){
            if(ch=='\r'){
                continue;
            }else if(ch == '\n'){
                buf[count]='\0';
                break;
            }//读取到一般字符
            buf[count]=ch;
            count++;
        }else if(len==-1){
            //读取出错
            perror("read faild");
            count=-1;
            break;
        }else{
            //客户端关闭sock连接
            fprintf(stderr,"client close.\n");
            count=-1;
            break;
        }
    }
    if(count>=0) buf[count]='\0';
    return count;
}

打包生成可执行文件

[root@localhost c++]# gcc winhttp.c -o winhttp.exe
[root@localhost c++]# ls
winhttp.c  winhttp.exe

启动服务器

[root@localhost c++]# ./winhttp.exe 
等待客户端的连接

浏览器访问

查看服务器终端输出

Client ip:192.168.137.1	 port:9004
request method:GET
method=GET
url:index.html
read line :Host: 192.168.137.151
read line :Connection: keep-alive
read line :Upgrade-Insecure-Requests: 1
read line :User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
read line :Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
read line :Accept-Encoding: gzip, deflate
read line :Accept-Language: zh-CN,zh;q=0.9
read line :Cookie: PHPSESSID=495343c481b1e5f7c0c03dad27e0817d; thinkphp_show_page_trace=0|0
read line :
path:./html_docs/index.html
...do_http_response...write[86]: HTTP/1.0 200 OK 
 Server:Linux Server
 Content-type: text/html
 Connection:Close
write[22]:Content-Length:252

write[252]:<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
</head>
<body>
<h1>大家好,我是陈东谱,有什么问题欢迎大家加我微信,我的微信号是:<font color='red'>reg183</font></h1>
</body>
</html>Client ip:192.168.137.1	 port:9005
client close.

至此一个简单的服务器代码编写完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

reg183

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值