linux C socket编程

19 篇文章 1 订阅
12 篇文章 0 订阅

 这是一个关于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;
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

庭博

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

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

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

打赏作者

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

抵扣说明:

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

余额充值