jpg c语言读取_光城归来之C语言开发网站

news/2024/5/9 23:08:13/文章来源:https://blog.csdn.net/weixin_39845206/article/details/111258225

C语言开发网站

0.导语

最近要把防火墙项目做个页面,而底层全部c语言实现,那么就得做个web页面,想了一下,C大法这么厉害,也应该可以的,然后大家就见到了这篇文章。

本篇文章主要讲使用C语言如何开发网站,CGI,Nginx+CGI如何部署等问题。

1.Socket通信

初探网站开发,直接上手熟悉的Socket通信编程,这方面网上资料非常多。以网上一张图片为例:

979201651df3deb098c0942188f924e0.png

图片来自:https://www.jianshu.com/p/dd580395bf11

本次实践以Get/Post提交表单为例,学习如何解析Html,后端与前端如何通信,Socket如何使用的问题。

直接先放主函数,然后再从每个函数讲解。

 1int main(){
2    //1.创建监听套接字,返回是套接字描述符
3    int sockfd = create_listenfd();
4    int fd;
5    while (1){
6        //2.等待客户端响应
7        int fd = accept(sockfd,NULL,NULL);
8        //3.处理客户端发来的请求
9        handle_request(fd);
10        close(fd);
11    }
12    close(sockfd);
13}

Socket操作分别为:

  • 创建监听套接字,返回是套接字描述符

  • 接收客户端发来的请求

  • 处理客户端发来的请求

上述便是Socket通信的核心三步骤。

1.1 创建套接字

下面一一来分析上述三步如何写。

引入相关头文件

1#include 
2#include 

核心函数解析

(1)获取一个socket descriptor

 1/** 2获取一个socket descriptor 3@params: 4    domain: 此处固定使用AF_INET 5    type: 此处固定使用SOCK_STREAM 6    protocol: 此处固定使用0 7@returns: 8    nonnegative descriptor if OK, -1 on error. 9*/
10int socket(int domain, int type, int protocol);

(2)客户端socket向服务器发起连接

 1/** 2客户端socket向服务器发起连接 3@params: 4    sockfd: 发起连接的socket descriptor 5    serv_addr: 连接的目标地址和端口 6    addrlen: sizeof(*serv_addr) 7@returns: 8    0 if OK, -1 on error 9*/
10int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

(3)绑定

 1/** 2服务器socket绑定地址和端口 3@params: 4    sockfd: 当前socket descriptor 5    my_addr: 指定绑定的本机地址和端口 6    addrlen: sizeof(*my_addr) 7@returns: 8    0 if OK, -1 on error 9*/
10int bind(int sockfd, struct sockaddr *my_addr, int addrlen)11

(4)监听

1/**2将当前socket转变为可以监听外部连接请求的socket3@params:4    sockfd: 当前socket descriptor5    backlog: 请求队列的最大长度6@returns:7    0 if OK, -1 on error8*/
9int listen(int sockfd, int backlog);

开始对上述操作进行封装,上述封装函数如下:

 1//监听套接字创建
2int create_listenfd(){
3    //创建Tcp连接
4    int fd = socket(AF_INET,SOCK_STREAM,0);
5    int option = 1;
6    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
7    struct sockaddr_in sin;
8    bzero(&sin,sizeof(sin));
9    sin.sin_family=AF_INET;
10    sin.sin_port=htons(80);
11    sin.sin_addr.s_addr=INADDR_ANY;
12
13    int res = bind(fd,(struct sockaddr *)&sin,sizeof(sin));
14    if (res==-1){
15        perror("bind");
16    }
17    listen(fd,100);
18    return fd;
19}

1.2 等待客户端请求到达

等待客户端请求到达

 1/** 2等待客户端请求到达,注意,成功返回得到的是一个新的socket descriptor, 3而不是输入参数listenfd。 4@params: 5    listenfd: 当前正在用于监听的socket descriptor 6    addr: 客户端请求地址(输出参数) 7    addrlen: 客户端请求地址的长度(输出参数) 8@returns: 9    成功则返回一个非负的connected descriptor,出错则返回-110*/
11int accept(int listenfd, struct sockaddr *addr, int *addrlen);

在main函数中,使用while 1循环来进行等待:

1while (1){
2    int fd = accept(sockfd,NULL,NULL);
3}

1.3 处理客户端发来的请求

上述完成后,其实就可以运行代码,通过:

1gcc -o main main.c 
2./main

即可完成socket的web server搭建,而客户端与服务端的更多交互操作,则需要更深入的学习,那么接下来就是来做这方面工作的。

首先来看一下我们的运行结果:

8c3877a8d9efb9fefa330ad4bd3e537f.png

index.html图

f0dfbf741bbe2c24af797a210fc88324.png

 post图

c84c425e0e916565dd9dd4118b4913e8.png

 info.html图

e64c7efa2184459e41655d4112e3c2e6.png客户端post前服务端接受数据图

0fb3d097ba54b4f0971b0347c55e91c7.png

客户端post后服务端接受数据图

该函数完成了如下操作:

分别有两个页面,分别是index.htmlinfo.html

当第一次打开index.html时候,会通过get方式获取相关资源,如下图所示:

我们看到了获取index.html与2.jpg,所以我们看到了index页面信息。

而当我们发送post请求跳转到info.html时,我们会在info.html中看到post后的数据。

接下来就来看代码如何实现:

首先来看服务器端如何获取数据呢(也就是终端打印数据):

1char buffer[40*1024]={0};
2int nread=read(fd,buffer,sizeof(buffer));
3printf("读到的请求是:\n");
4printf("%s",buffer);
5printf("\n--------------------\n");
6sscanf(buffer,"%s /%s HTTP/1.1",method,filename);

这里直接通过read函数传递一个socket描述符,然后通过read便可获取到当前index.html的数据。

接下来就是get请求:

在上述sscanf函数中,我们解析出来了文件名与请求方法,然后根据请求方法做判断即可!

打开文件并发送该文件内容给浏览器,浏览器便可以接收到服务器端的响应数据!

 1char filename[10]={0};
2char method[10]={0};
3
4if(strcmp(method,"GET")==0){
5
6    printf("\n解析出来的文件名是%s\n",filename);
7    char mime[40*1024]={0};
8    get_filetype(filename,mime);
9    char response[40*1024]={0};
10
11    //\r\n\r\n表示换行后有一个空行
12    sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type: %s\r\n\r\n", mime);
13    int headlen = strlen(response);
14    //打开文件,读取内容,构建响应,发回给客户端
15    int filefd = open(filename,O_RDONLY);
16    int filelen = read(filefd,response+headlen,sizeof(response)-headlen);
17
18    //发送响应头+内容
19    write(fd,response,headlen+filelen);
20    close(filefd);
21
22}

最后就是post请求:

上述我们通过post数据后到了info.html页面,那么这个如何做到的呢,就是通过解析post方法,然后对客户端,也就是浏览器做出响应即可!

 1char username[50] = { 0 };
2char sex[50] = { 0 };
3char email[50] = { 0 };
4else if(strcmp(method,"POST")==0){
5    char response[40*1024]={0};
6    char mime[40*1024]={0};
7    get_filetype(filename,mime);
8    //\r\n\r\n表示换行后有一个空行
9    sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type: %s\r\n\r\n", mime);
10    int headlen = strlen(response);
11    char *postbuffer = strstr(buffer, "username=");
12    if(postbuffer){
13        // char * after = strchr(buffer, '&');
14        printf("------>%s\n",postbuffer);
15        // printf("------>%s\n",postbuffer+9);
16        char *sexbuffer = strstr(postbuffer, "&sex=");
17        char *emailbuffer = strstr(sexbuffer, "&email=");
18        printf("email:%s\n",emailbuffer);
19        strncpy(username,(const char *)postbuffer,strlen(postbuffer)-strlen(sexbuffer));
20        printf("用户名=%s\n",urldecode(username+9));
21        strncpy(sex,(const char *)sexbuffer,strlen(sexbuffer)-strlen(emailbuffer));
22        printf("性别=%s\n",urldecode(sex));
23        printf("邮箱=%s\n",urldecode(emailbuffer+7));
24        // char *email = strstr(buffer, "&email=");
25        // int sex_email = email-sex;
26    }
27    char *res[100]={0};
28    //发送数据给浏览器
29    sprintf(res,"html>结果

POST结果:%s

",urldecode(postbuffer));
30    sprintf(response,"%s",res);
31    write(fd,response,headlen+strlen(res));
32    printf("%s\n",response);
33
34    // close(filefd);
35    printf("\n解析出来的文件名是%s\n",filename);
36
37}

除此之外,上述post后,碰到中文会出现乱码,以%的数据发送了过去,也就是通常的url编码与解码,这里直接用c实现解码函数即可:

 1// 解码url
2char * urldecode(char url[]) 3{
4    int i = 0;
5    int len = strlen(url);
6    int res_len = 0;
7    char res[BURSIZE];
8    for (i = 0; i  9    {
10        char c = url[i];
11        if (c != '%')
12        {
13            res[res_len++] = c;
14        }
15        else
16        {
17            char c1 = url[++i];
18            char c0 = url[++i];
19            int num = 0;
20            num = hex2dec(c1) * 16 + hex2dec(c0);
21            res[res_len++] = num;
22        }
23    }
24    res[res_len] = '\0';
25    strcpy(url, res);
26    return url;
27}

最后就会得到post后的含有特殊字符与中文的结果!

2.CGI+Nginx

2.1 概念初探

CGI

通用网关接口(Common Gateway Interface/CGI)描述了客户端和服务器程序之间传输数据的一种标准,可以让一个客户端,从网页浏览器向执行在网络服务器上的程序请求数据。CGI 独立于任何语言的,CGI 程序可以用任何脚本语言或者是完全独立编程语言实现,只要这个语言可以在这个系统上运行。Unix shell script, Python, Ruby, PHP, perl, Tcl,C/C++, 和 Visual Basic 都可以用来编写 CGI 程序。

如下图所示:

5543f854fe50d6dccf0727a6f908203e.png

FastCGI

快速通用网关接口(Fast Common Gateway Interface/FastCGI)是通用网关接(CGI)的改进,描述了客户端和服务器程序之间传输数据的一种标准。FastCGI致力于减少Web服务器与CGI程式之间互动的开销,从而使服务器可以同时处理更多的Web请求。与为每个请求创建一个新的进程不同,FastCGI使用持续的进程来处理一连串的请求。这些进程由FastCGI进程管理器管理,而不是web服务器。

6f6ac2fa16496e302e2cf066942eb15a.png

Nginx

Nginx是异步框架的Web服务器,也可以用作反向代理,负载平衡器 和 HTTP缓存。

Nginx+CGI

nginx 不能直接执行外部可执行程序,并且cgi是接收到请求时才会启动cgi进程,不像fastcgi会在一开就启动好,这样nginx天生是不支持 cgi 的。nginx 虽然不支持cgi,但它支持fastCGI。所以,我们可以考虑使用fastcgi包装来支持 cgi。原理大致如下图所示:pre-fork几个通用的代理fastcgi程序——fastcgi-wrapper,fastcgi-wrapper启动执行cgi然后将cgi的执行结果返回给nginx(fork-and-exec)。

d1bbb33e38bb22e9af325d4b077a6b4b.png

fastcgi-wrapper安装:进入下面地址:

https://github.com/gnosek/fcgiwrap

1autoreconf -i
2./configure
3make && make install

启动fastcgi-wrapper

1spawn-fcgi -f /usr/local/sbin/fcgiwrap -p 9000

nginx源码安装同上(不用执行第一行auto操作)。

安装完后,进入conf目录进行fcgiwrap配置:

1location ~ ^/cgi-bin/.*$ {
2    root /home/light/nginx/; # 填写自己的nginx目录
3    #cgi path 
4    if (!-f $document_root$fastcgi_script_name) {
5        return 404;
6    }
7    fastcgi_pass 127.0.0.1:9000;
8    include fastcgi.conf;
9}

在nginx目录下新建一个cgi-bin目录用于放置cgi程序。

编写cgi程序main.c

 1#include 
2#include 
3
4int main(void) 5{
6    int count = 0;
7    printf("Content-type: text/html;charset=utf-8\r\n"
8        "\r\n"
9        "光城第一次使用CGI!"
10
11        "

光城第一次使用CGI!

"
12        "Request number %d running on host %s\n",
13        ++count, getenv("SERVER_NAME"));
14    return 0;
15}

编译程序:

1gcc -o main main.c

开始部署,移动main到cgi-bin目录:

然后启动nginx:

1./sbin/nginx

打开浏览器:

2be5f1406bc0e20ae396e8644b52b9d8.png

看到如上页面,成功!

e6f37c79ff2caf572b9ae95bfa914376.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_754066.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

squid代理快速搭建_网站安全渗透 之squid代理漏洞挖掘与修复

在对网站进行渗透测试的时候,发现很多网站都在使用squid反向代理系统,该系统存在可以执行远程代码的漏洞,很多客户找我们做渗透测试服务的同时,我们会先对客户的网站进行信息搜集工作,包括域名,二级域名收集…

图片展示网站源码_arcgis api 4.x for js 自定义叠加图片图层实现地图叠加图片展示(附源码下载)...

前言关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 4.x for js:esri 官网 api,里面详细的介绍 arcgis api 4.x 各个类的介绍,还有就是在线例子:esri 官网在线例子,这个也是学习…

pygame.image.load()找不到图片_PPT背景low?找不到好看的图片?那是因为你不知道这几个图片网站...

大家都知道,做PPT想要做得高大上一点,一些精美、高逼格的图片就不可缺少了。那么日常你是不是总是为PPT的背景、图片而烦恼,觉得PPT的背景太单调了,里面的图片太low了,想要换成高大上一点的图片,但是又不知…

最新ie图标变灰css,网站变灰的CSS代码(兼容火狐、Chrome、IE系浏览器)——w3cdream|前端学习-开发...

之前找了一些代码在火狐下无效,于是百度谷歌一起上,终于被我找到了支持火狐、谷歌等浏览器的把网页变黑白代码:/* 网站黑白代码 */html{ filter: grayscale(100%); -webkit-filter: grayscale(100%); -moz-filter: grayscale(100%); -ms-filt…

使用Python-Flask框架开发Web网站系列课程(四)构建前端

版权声明:如需转载,请注明转载地址。 https://blog.csdn.net/oJohnny123/article/details/81988424 前言 使用IDE:PyCharm 操作系统:Mac Python的版本:3.6 我的邮箱:51263921qq.com 交流群:3724…

【2018可信云大会】CTO袁国成:HTTPS网站安全评估与监测告警解决方案

2019独角兽企业重金招聘Python工程师标准>>> 袁国成:现在下午时间大家都比较累了,给大家带来一些干货。我今天分享的主题是关于HTTPS网站的安全评估与告警监测。 以往我们在分享安全话题的时候,比较多的是关于网络安全的&#xff…

【Gridsome】静态网站生成

Gridsome 介绍 Gridsome 是一个免费、开源、基于 Vue.js技术栈的静态网站生成器 什么是静态网站生成器静态网站的好处常见的静态网站生成器JAMStack静态应用的使用场景 不适合管理系统 简单页面展示 想要有更好的 SEO 想要有更好的渲染性能 Gridsome 是由Vue.js驱动的Jamsta…

echarts 各种图表网站,留着有用

2019独角兽企业重金招聘Python工程师标准>>> https://echarts.baidu.com/examples/#chart-type-treemap 转载于:https://my.oschina.net/u/3222944/blog/3001309

Java程序员的职业发展路线 附:大型网站 -- 架构技能进阶图谱

职业发展道路基本有3条: 第一条路线(技术专精): 初级Java开发---中级--高级---项目主管--Java项目经理---网站架构师----资深专家 第二条路线(技术转产品):初级Java开发---中级--产品策划--产品…

宜春网站建设

2019年“五一”小长假结束,很多人给假期生活的总结估计是“人从众”、“买买买”,以致文化和旅游部都用“繁荣超预期”来形容“五一”的文化和旅游市场。据调查,许多人都是通过网上购买火车票、飞机票、各景点门票以及预订酒店,很…

jquery 当页面图片加载之后_谷歌SEO页面速度的重要性

什么是页面速度?页面速度是指网页加载所需的时间。一个页面的加载速度是由几个不同的因素决定的,包括网站的服务器、页面文件大小和图片压缩。也就是说,"页面速度 "并不像 "网页速度 "那么重要。"页面速度 "并…

网站建设协议_了解这几个企业建站流程做出来的网站更让客户喜欢

网站建设步骤是网站建设当中一个重要环节,一个网站看它好不好,重要一点就是这个网站建设了。因为好的网站建设能够让浏览网站用户,一直停留在网站当中。很多人会问这个网站建设要怎么样才能够让用户喜欢,为什么宁开亮传媒免费做的…

javamail发送html_SpringBoot入门建站全系列(十)邮件发送功能

SpringBoot入门建站全系列(十)邮件发送功能Spring Mail API都在org.springframework.mail及其子包org.springframework.mail.javamail中封装。 JavaMailSenderImpl: 邮件发送器,主要提供了邮件发送接口、透明创建Java Mail的MimeMessage、及邮…

访问调用https_(二)http协议的网站装ssl升级成https

最终目标:微信小程序要想上线 必须内部所有域名都是https,比如网络图片,比如后端接口,比如其他链接。问:既然https://minihome.top/能直接访问了,那我用eggjs(node)写的后端接口是不是就可以正常访问了&…

推荐几个很好很好用的网站

1. MSDN 这是非官方性质的微软网站,但是它无广告,提供了很多的微软资源,却是相当的良心。如果要安装操作系统、office、VS、Visio等都可以从这个网站上进行下载。 2. 高清图片 该网站提供很多高清壁纸,风格清新,艺术风…

大型网站架构技术一览

大型网站的挑战主要来自庞大的用户,高并发的访问和海量数据,任何简单的业务一旦需要处理数以P计的数据和面对数以亿计的用户,问题就会变得棘手。大型网站架构主要就是解决这类问题。 本文内容大部分来自《大型网站技术架构》,这本书很值得一…

大型网站架构演化历程

摘自《大型网站技术架构》:第一章 大型网站架构演化 目录 一、大型网站系统的特点 二、 大型网站架构演化发展历程 1. 初始阶段的网站架构 2. 应用服务和数据服务分离 3. 使用缓存改善网站性能 4. 使用应用服务器集群改善网站的并发处理能力 5. 数据库读写分离 6. 使…

珍藏30年的网站都在这了,自媒体运营必不可少

目录 01办公协作 02 图库 03新媒体相关 04 APP相关 05 小程序相关 06 H5制作 06 二维码 07 问卷 08 gif 09 大数据 10 SasS类平台 11 KOL采购及广告投放 12活动会议 13 长短连接 14 搜索工具 15 思维导图 16 图片处理 17 识图工具 18 表情包 01办公…

HMDB网站 爬取工具

HDMB网站有一个特别不友好的地方是: 搜索相应太慢,成功率还低,这个简直太不爽了。不过白天体验明显好于晚上体验…原因自己品吧 效果图工具使用部分效果 根据HMDBID下载结果 设置搜索条件搜索结果 解析成Excel文件 接受定制任务

网站、数据库的衍变之路(三)

话接前文《网站、数据库的衍变之路(二)》。上文讲了几种静态化方案的利弊,有朋友要讲详细一点,呵呵,这不属于本文的范畴。也有朋友说有些网站不适合搞静态化,是有这种情况。但是在这个时期,网站还处于刚发展的起始阶段…