linux C socket编程

    科技2025-04-05  11

     这是一个关于socket的题:要求你自己写一个socket程序,然后解析客户端从浏览器地址栏提交的数据。

    要求:在浏览器中输入http://localhost:8500 后,你的socket程序向浏览器返回一个网页,以后就用这个网页向你写得这个socket程序提交数据,你的socket程序负责解析这些数据关回答到那个网页上去。

    涉及的知识点:1. socket编程; 2.http请求与响应;

    #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<sys/types.h> #include<netinet/in.h> #include<sys/socket.h> #include<sys/wait.h> #include<sys/fcntl.h>

    #define PORT 8500//端口号  #define BACKLOG 5/*最大监听数*/ 

    int main(){     char* trim(char* str);

        int sockfd,new_fd;/*sockfd是监听套接字,new_fd是通信套接字*/     struct sockaddr_in my_addr;/*本方地址信息结构体,下面有具体的属性赋值*/     struct sockaddr_in their_addr;/*对方地址信息*/     socklen_t sin_size;     char mybuf_1[520] = { 0 };//本socket要返回给网页的信息     char* get_value[10];

        sockfd=socket(AF_INET,SOCK_STREAM,0);//获得监听套接字      if(sockfd==-1){             printf("socket failed:%d",errno);             return -1;     }     my_addr.sin_family=AF_INET;/*协议簇*/     my_addr.sin_port=htons(PORT);/*端口号*/     my_addr.sin_addr.s_addr=htonl(INADDR_ANY);/*IP,括号内容表示本机IP*/     bzero(&(my_addr.sin_zero),8);/*将其他属性置0*/     if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))<0){//绑定地址结构体和socket             printf("bind error");             return -1;     }     listen(sockfd,BACKLOG);//开启监听 ,第二个参数是最大监听数 

        int number = 0;     while(1){         sin_size=sizeof(struct sockaddr_in);         new_fd=accept(sockfd,(struct sockaddr*)&their_addr,&sin_size);//在这里阻塞知道接收到消息,参数分别是socket句柄,接收到的地址信息以及大小          if(new_fd==-1){             printf("receive failed");         }         else {             char request[1024];             recv(new_fd, request, 1024, 0);             request[strlen(request) + 1] = '\0';             printf("%s", request);             printf("网页请求数据接收成功!\n");

                //如果是第一次接受请求,就向网页发送响应网址exec.html             //number 代表网页发请求的次数             if (number == 0) {                 //char buf[520] = "HTTP/1.1 200 ok\r\nconnection: close\r\n\r\n";//HTTP响应                 char buf[520] = "HTTP/1.1 200 ok\r\n\r\n";//HTTP响应                 int s = send(new_fd, buf, strlen(buf), 0);//发送响应                 int f1 = open("exec.html", O_RDONLY);//消息体                 sendfile(new_fd, f1, NULL, 2500);//零拷贝发送消息体                 close(f1);                 close(new_fd);             }             else {                 int m = 0;                 /*下面是我对请求协议的解析*/                 char* p1 = NULL;//p1代表获取到的网页请求信息中第一行                 p1 = strtok(request, "\r\n"); //p1的结果是: GET /?aaa=18&b=99 HTTP/1.1

                    char* p2 = NULL;//p2代表网页请求信息中的第二行,即网址部分,应该是以空格分割的第二个数据                 p2 = strtok(p1, " ");                 while (p2 != NULL) {                     if (m == 1) {                         break;                     }                     p2 = strtok(NULL, " ");                     m++;                 }                 printf("%s\n", p2); //  p2的结果要么是 / ,要么是 /?aaa=18&b=99

                    char* p3 = NULL;//请求网址中的变量部分                 p2 = trim(p2); //去除p2前后的空格                 if (strcmp(p2, "/") == 0) {                     strcpy(mybuf_1, "请输入get数据\n");                     char buf[520] = "HTTP/1.1 200 ok\r\n\r\n";//HTTP响应                     int s = send(new_fd, buf, strlen(buf), 0);//发送响应                     int s1 = send(new_fd, mybuf_1, strlen(mybuf_1), 0);//发送响应                     close(new_fd);                 }                 else {                     p3 = strtok(p2, "?");                     m = 0;                     while (p3 != NULL) {                         if (m == 1) {                             break;                         }                         p3 = strtok(NULL, "?");                         m++;                     }                     printf("%s\n", p3);    // 得到的数据是这样的形式:   aaa=18&b=99

                        //下面是对aaa=18&b=99这样的数据用&进行拆分                     char* v[15];                     char* p4 = NULL;                     m = 0;                     if (p3 != NULL) {                         p4 = strtok(p3, "&");                         while (p4) {                             v[m] = p4;                             ++m;                             p4 = strtok(NULL, "&");                         }                     }                     printf("共get了%d个参数\n", m);                     printf("以下是get提交的数据,分别取出来后存放在get_value[]中\n");                     int j;                     int z = 0;                     for (j = 0; j < m; ++j)                     {                         printf("v数组的数据是:%s\n", v[j]);                         char* p5 = NULL;                         if (v[j] != NULL) {                             p5 = strtok(v[j], "=");                             while (p5) {                                 get_value[z] = p5;                                 ++z;                                 p5 = strtok(NULL, "=");                             }                         }                     }                     printf("get_value的数据分别是:\n");                     for (j = 0; j < z; j++) {                         printf("%s\n", get_value[j]);                     }                     printf("get_value[1]= %s\n", get_value[1]);

                        if (strcmp(get_value[1], "cat+test") == 0) {                         char buf[520] = "HTTP/1.1 200 ok\r\n\r\n";//HTTP响应                         int s = send(new_fd, buf, strlen(buf), 0);//发送响应                         int f1 = open("test.txt", O_RDONLY);//消息体                         sendfile(new_fd, f1, NULL, 2500);//零拷贝发送消息体                         close(f1);                         close(new_fd);                     }                     else {                         /*把数字转成字符串时,不能用itoa(),linux C它不认*/                         char buf[520] = "HTTP/1.1 200 ok\r\n\r\n";//HTTP响应                         int s = send(new_fd, buf, strlen(buf), 0);//发送响应                         char* buffer = get_value[1];                         //strcat(mybuf_1, buffer);                         strcpy(mybuf_1, buffer);                         int s1 = send(new_fd, mybuf_1, strlen(mybuf_1), 0);//发送响应                         close(new_fd);                         //下面是把数字转成字符串。不能用itoa(),因为linux c不认                         //char buffer[12] = { 0 };                         //snprintf(buffer, 3, "%d", number);                         //strcat(mybuf_1, buffer);                     }

                    }

                }         }         number++;     }     return 0; }

    //去除尾部空格 char* rtrim(char* str) {     if (str == NULL || *str == '\0')     {         return str;     }

        int len = strlen(str);     char* p = str + len - 1;     while (p >= str && isspace(*p))     {         *p = '\0';         --p;     }

        return str; }

    //去除首部空格 char* ltrim(char* str) {     if (str == NULL || *str == '\0')     {         return str;     }

        int len = 0;     char* p = str;     while (*p != '\0' && isspace(*p))     {         ++p;         ++len;     }

        memmove(str, p, strlen(str) - len + 1);

        return str; }

    //去除首尾空格 char* trim(char* str) {     char* rtrim(char* str);     char* ltrim(char* str);     str = rtrim(str);     str = ltrim(str);

        return str; }

      

    Processed: 0.008, SQL: 8