[点点搬家]C语言开发Web和C语言处理字符

[四年前的博客了,当年还真面过百度,可惜那个部门用的是c,非要用c写程序……]


这是一篇沉痛的文章...以此纪念被百度鄙视的经历。


哥从来没有用C写过Web,这也是被鄙视的主要原因之一,补之。

可以通过以下方式:

CGI/FastCGI: FastCGI能让进程常驻内存,不像CGI那样每次都要创建销毁进程,所以会很快,但要注意内存溢出和进程崩溃。

ISAPI/NSAPI:Internet Server API,可以把Dll加载进来,一个Dll可以对应多个响应,这样进程数就少了。NSAPI是啥我就不关心了……

ATL:Active Template Library,支持C++编写ASP和ActiveX

Asp.net: Dot Net framework么,用C++很正常。


OK,下面自己争取写第一个C的Web程序。

从网上找到比较好的一篇教程是:http://www.xxlinux.com/linux/article/development/soft/20090220/15535.html


好了,先写个helloWorld,试试刚下的VC6能不能用:

#include <stdio.h>

#include <stdlib.h>

int main()

{

printf ("hello world!");

}

差点包含进来std namespace,现在先写c,不谈c++。泪流满面,hello world,多长时间没写c了....

再造一下:

#include <stdio.h>

#include <stdlib.h>

int main()

{

printf("Content-type:text/html\n\n");

printf("Hello world from C.");

}

然后部署这个exe到cgi-bin下,浏览器中,泪流满面,哥如今也是用c写过Web的人了……



Content-type:text这个是MIME格式,眼熟啊。

\n\n规定包头和体必须有一个空行!这里不是http协议,是CGI协议,不过很像,哈。


程序还可以写成:

int main()

{

printf("Content-type:text/html\n\n");

int n=0;

if(getenv("CONTENT_LENGTH"))

n = atoi(getenv("CONTENT_LENGTH"));

else

return 0;

for(int i=0; i<n; ++i)

{

putchar(getchar());

putchar('\n');

fflush(stdout);

}

}

这样如果有CONTENT_LENGTH域的值的话,就可以查看POST里面的东东,并打印出来了!

其实像getchar, putchar, getenv这样的小函数,看着还是很亲切的。

CGI用的是标准输入输出流,Web服务器与CGI交换消息用的是环境变量,可以读出来HTTP协议的头之类的东东。这些环境变量是属于这个进程的。

如:REQUEST-METHOD,REMOTE-HOST,SCRIPT-NAME,CONTENT-TYPE,QUERY-STRING等等。

程序改成如下:

int main()

{

printf("Content-type:text/html\n\n");

int n=0;

if(getenv("CONTENT-LENGTH"))

n = atoi(getenv("CONTENT_LENGTH"));

printf("There are %d chars in content<br>", n);

printf("Request method:%s<br>",getenv("REQUEST_METHOD"));

printf("Remote Host:%s<br>",getenv("REMOTE_HOST"));

printf("Script Name:%s<br>",getenv("SCRIPT_NAME"));

printf("Content Type:%s<br>",getenv("CONTENT_TYPE"));

printf("Query String:%s<br>",getenv("QUERY_STRING"));


for(int i=0; i<n; ++i)

{

putchar(getchar());

putchar('\n');

fflush(stdout);

}

}

写一个HTML,放到htdoc下:

<html>

<head>

<title>Test c in CGI</title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 

</head>

<body>

<form method="GET" action="/cgi-bin/123.exe">

<input type="text" name="input1" width="20"/>

<br />

<input type="submit" value="SUBMIT" />

</form>

</body>

</html>

然后访问浏览器,等到如下:


这里有URL encoding,等会再说...


把方法改成了POST后,得到如下:

There are 0 chars in content
Request method:POST
Remote Host:(null)
Script Name:/cgi-bin/123.exe
Content Type:application/x-www-form-urlencoded
Query String:

鬼魅啊,为啥没有Content_length呢?好吧,认为是只有POST的时候才能去取Content_length,把代码改成:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main()

{

printf("Content-type:text/html\n\n");

printf("Request method:%s<br>",getenv("REQUEST_METHOD"));

printf("Remote Host:%s<br>",getenv("REMOTE_HOST"));

printf("Script Name:%s<br>",getenv("SCRIPT_NAME"));

printf("Content Type:%s<br>",getenv("CONTENT_TYPE"));

printf("Query String:%s<br>",getenv("QUERY_STRING"));

if(!strcmp(getenv("REQUEST_METHOD"), "POST"))

{

int n = atoi(getenv("CONTENT_LENGTH"));

printf("There are %d chars in content<br>", n);

for(int i=0; i<n; ++i)

{

putchar(getchar());

fflush(stdout);

}

}

return 1;

}

然后输出为:

Request method:POST
Remote Host:(null)
Script Name:/cgi-bin/123.exe
Content Type:application/x-www-form-urlencoded
Query String:
There are 10 chars in content
input1=234344
好的,这样可以看POST的内容了。


然后,又是心中的一个痛,当年哥被问怎么处理中文字符,哥不知道……哥虽然现在也不知道,但哥快知道了。

先说一下URL Encoding,因为URL只能用ASCII,而且只能用:

[0-9a-zA-Z],  "$-_.+!*'(),"<---不包括引号,还有一些保留字。

http://www.blooberry.com/indexdot/html/topics/urlencoding.htm

所以遇到中文之类的就要Encoding了,规则如下

1,加号变为空格

2,%xx索引ASCII码表,xx为16进制,正好覆盖ASCII256个东东


修改代码如下:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>


int htoi(char *s)

{

char *digits= "0123456789ABCDEF";

if (islower (s[0])) s[0]=toupper(s[0]);

if (islower (s[1])) s[1]=toupper(s[1]);

return 16 * (strchr(digits, s[0])-strchr(digits,'0'))+(strchr(digits,s[1])-strchr(digits,'0'));

}


int main()

{

printf("Content-type:text/html\n\n");

printf("Request method:%s<br>",getenv("REQUEST_METHOD"));

printf("Remote Host:%s<br>",getenv("REMOTE_HOST"));

printf("Script Name:%s<br>",getenv("SCRIPT_NAME"));

printf("Content Type:%s<br>",getenv("CONTENT_TYPE"));

printf("Query String:%s<br>",getenv("QUERY_STRING"));

char original[255];

if(!strcmp(getenv("REQUEST_METHOD"), "POST"))

{

int n = atoi(getenv("CONTENT_LENGTH"));


printf("There are %d chars in content<br>", n);


char c;

for(int i=0; i<n; ++i)

{

c = getchar();

original[i]=c;


switch(c)

{

case '&':

c='|';

break;

case '+':

c=' ';

break;

case '%':{

char s[3];

s[0]=getchar();

s[1]=getchar();

s[2]=0;

c=htoi(s);

i+=2;

original[i+1]=s[0];

original[i+2]=s[1];

}

break;

case '=':

c=':';

break;

}

putchar(c);

}

original[i]=0;

}

printf ("<br>Encoded URL is:%s<br>", original);

return 1;

}

这样得到输出:

Request method:POST
Remote Host:(null)
Script Name:/cgi-bin/123.exe
Content Type:application/x-www-form-urlencoded
Query String:
There are 22 chars in content
input1:try another one
Encoded URL is:input1=try+another+one

或者:

input1:||||
Encoded URL is:input1=%烫%C%C%C

这里看到烫,因为数字到字符的转换问题,其实他是两个16进制,input1能转换一些这种字符了。

但是中文还是不能得到完美解决。

留个链接:http://qingbo.net/blog/post144.html

改天继续研究了……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值