zoukankan      html  css  js  c++  java
  • ISAPI精彩编程

     以前想做一点ISAPI方面的程序,上网找了很长时间一直没有写得全一些的,书店里的书里写的又不是很深,于是经过两个月的摸索,总算做了一些东西。很长一段时间以来,总想写一写ISAPI方面的文章,可是一直没有时间,今稍有空,遂把最近所学写下,以归所愿。
    略作构思,欲写以下几点:
    1, ISAPI简介
    2, 一个简单的ISAPI程序
    3, ISAPI实现 客户/服务器 交互
    4, ISAPI操作数据库
    5, 利用ISAPI进行网络数据传送
    6, ISAPI传输数据的加密
    7, ISAPI网络数据传送进阶(网络大数据包传送)
    8, 总结

    一、 ISAPI简介

       通用网关接口CommonGatewayInterface(CGI)很早就作为交互式的Web应用程序的一个标准广泛应用在Internet之中。CGI脚本允许人们用多种编程语言(如Basic、C、Perl、Shell等等)来编写简单的应用程序。这些脚本运行在Web服务器上,而在客户的Web浏览器上输出运行结果。客户的输入通过环境变量或者标准输入设备来进行传递,然后CGI程序根据需要完成特定的操作,并通过HTML格式显示在客户的浏览器中。CGI的这一特性给互联网带来了生机,网站的建设也从此从沉默的处子变为热烈的少女,随着时间的推移,这位曾经轰动一时的白雪公主也日益疲乏起来。
    人们在长期的使用中还是发现了CGI应用程序的一个很大的缺点:性能不高。我每请求一次CGE程序时,CGI执行文件(或者脚本的解释器)都要为每一个请求创建一个新的进程。对于一个信息量比较大的站点来说,这无疑给服务器增加了一个沉重的负担。
    在以后的岁月里,热闹的互联网又推出了ASP,JSP等好多提高安全性及服务器性能的措施,可其安全性及开发工具的成熟度远远不及VC,Delphi等成功的工具,而作为一个熟悉软件编程的程序员来说,利用现成的开发工具及现有的资源开发一套网站系统更是得心应手。

    ISAPI(Internet Server Aplication Programing Interfase)就是一种用编程工具进行开发,、运行于NT服务的一种标准的编程接口,Web 开发者可用它编写交互式应用程序。ISAPI 扩
    展(Extension)应用程序具有 CGI 脚本同样的功能,但它比 CGI 具有更快、更有效的性能。
    ISAPI for Windows NT 编写的应用程序,Web 用户可通过填写 HTML 表单(form)或单击 Web 节点上 HTML 页面中的链接来激活该应用程序。服务器端获取用户提供的信息后,被激活的ISAPI 应用程序对获取的信息作出处理。根据 ISAPI 应用程序的功能或把获取的信息存入数据库,或以获取的信息为条件访问数据库中的数据,然后把结果以 HTML 页面的形式送回到客户端。
    ISAPI 的应用程序被编译为动态链接库(DLL, Dynamic Linked Library),该库在WWW 服务(Service)启动时装载入内存。它要求较少的系统开销,性能明显优于CGI 应用程序。因为每个请求并不启动单独的进程。而如用 CGI 作交互程序,每个请求需要启动单独的进程。

    ISAPI有明显的性能优势,但其调试不方面,开发资料较少,一直成为开发人员不优选的原因。为了更广泛地运用ISAPI,特作此文,以供广大开发者更快地进入开发过程。 

    返回


    二、一个简单的ISAPI程序

    New,Object,ISAPI Extension Wizard,Object Name就起个FirstISAPI,OK,第二步什么也不要变,点Finshed完成。按下F7把生成的DLL放到C:\inetpub\wwwroot\firstisapi目录下(建文件夹不用我教吧?),打开浏览器,在地址栏内输入 http://127.0.0.1/firstisapi/FirstISAPI.dll
    OK
    我们立马可以看到如下内容:
    This default message was produced by the Internet Server DLL Wizard. Edit your CFirstISAPIExtension::Default() implementation to change it.
    你看到了吗?
    如果你看到了上面这一串英文字符,说明你的服务器可以用啦。如果你看到了一个下载文件对话框,别哭!说明你的服务器还没有配置好,下面由我来一步步教你,会用的朋友也别错过这个好机会!
    开始,程序,管理工具,Internet 服务管理器,打开左边树,找到 默认Web站点下 的firstisapi,把鼠标入在上面单击右键,属性,在 执行许可 里面下拉列表,选中 脚本和可执行程序 其他什么也别动(如果你觉得动着好玩的话就动吧,不过服务器配置不好了可别怪我没提前“声明:)”).下面我们要做什么呢?忘了,等等!哦,对了,点击OK,如果没有呢,你的是中文版吧,那就点确定吧!
    好了,http://127.0.0.1/firstisapi/FirstISAPI.dll ----------------------->>>

    This default message was produced by the Internet Server DLL Wizard. Edit your CFirstISAPIExtension::Default() implementation to change it.
    这回看到了吧?
    还没有?
    算了,别学ISAPI了,多烦,你不烦我都烦了,臭机子!
    (想了想,这种可能还是有的,我还是为人为到底吧,免得你又骂娘了,好,把开光驱,把2000的盘放进去啊,还愣着干么?添加组件,重装一遍你的INTERNET服务!......)
    这回不会不行吧?
    不行?
    oicq608@163.com
    OICQ:67406204
    http://www.ourcode.net/
    联系我吧,我会帮你的!!!~~~~~~~~~


    如此,我们的第一个ISAPI就做成了,你可以放心的说,我会做ISAPI了........---------屁!这也叫会?

    对了,忘了WIN98的朋友,对不起啊,你有没有装PWS啊
    没有?
    那装一个吧!
    其他的和2000大同小异,不用我教吧?
    :):)


    返回

    三、ISAPI实现 客户/服务器 交互

    我们现在已经可以做一个简单的ISAPI程序了,但是,它什么功能也没有实现,毕竟我们还没有加让它动起来的代码嘛!
    在CFirstISAPIExtension类里象做一般程序一样加入一个成员函数 void Getdata(CHttpServerContext *pCtxt, char *data);然后在BEGIN_PARSE_MAP(CFirstISAPIExtension, CHttpServer)和END_PARSE_MAP(CFirstISAPIExtension)之间加入ON_PARSE_COMMAND(Getdata, CFirstISAPIExtension,ITS_PSTR)和ON_PARSE_COMMAND_PARAMS("data")
    ,如下所示:

    BEGIN_PARSE_MAP(CFirstISAPIExtension, CHttpServer)
    // TODO: insert your ON_PARSE_COMMAND() and
    // ON_PARSE_COMMAND_PARAMS() here to hook up your commands.
    // For example:
    ON_PARSE_COMMAND(Getdata, CFirstISAPIExtension,ITS_PSTR)

    ON_PARSE_COMMAND_PARAMS("data")
    ON_PARSE_COMMAND(Default, CFirstISAPIExtension, ITS_EMPTY)
    DEFAULT_PARSE_COMMAND(Default, CFirstISAPIExtension)
    END_PARSE_MAP(CFirstISAPIExtension)

    ON_PARSE_COMMAND和ON_PARSE_COMMAND_PARAMS是参数映射宏,ON_PARSE_COMMAND的第一个参数Getdata是要处理事件的函数名,第二个参数CFirstISAPIExtension为以CHttpServer为父类的应用程序子类,后面的参数要传给Getdata函数的参数列表,它们可以是:ITS_EMPTY: 没 有 数 据; ITS_PSTR: 字 符 串; ITS_I2:short 整 型; ITS_I4:long 整 型; ITS_R4:float 浮 点 数; ITS_R8:double 浮 点 数。参数的个数一般与下面ON_PARSE_COMMAND_PARAMS解析的参数相对应。我们在这里可以data参数赋给一个初值,当我们在浏览器里没有传上来这个参数的实际数值时就是它了。如data=www.ourcode.net;这里data就是我们定义函数Getdata里所要传入的参数名。

    有了上面这些准备工作,下面我们就可以添加代码了,因为它和平常编程时没什么两样,因此我们就简单地加上一点代码看看我们劳动了半天到底做了些什么?

    如下:

    void CFirstISAPIExtension::Getdata(CHttpServerContext *pCtxt, char *data)
    {

    StartContent(pCtxt);//写HTML文件头
    WriteTitle(pCtxt);//写标题
    *pCtxt << _T("这是你提交上来的数据:<br>\r\n");//向浏览器发送数据
    *pCtxt <<data <<"\r\n";//写上一个换行和回车
    EndContent(pCtxt)

    }  

    CHttpServerContext *pCtxt是一个服务器上下文标志,我们向浏览器传输数据就全靠它 .
    *pCtxt <<后的字串就是浏览器里的HTML源码,因此,你可以把"这是你提交上来的数据:<br>\r\n"
    改成你想要的HTML,想怎么改随你吧!:)

    现在是不是要按下F7了?哈哈,好,F7,马上把FirstISAPI.dll Ctrl+C,Ctrl+V........

    "无法创建或替换FirstISAPI:指定的文件正被Windows使用",没法了?

    我就重起计算机啦,谁教它装入内存呢!不过你把DLL改个名字也行,要不又要等一支烟工夫了!

    下面ISAPI调试的文章,不爱老重起计算机的朋友可以看一下。
    ISAPI 在运行时是IIS的一部分,而IIS又作为NT的一个服务而运 行。这一事实使用调试过程变得复杂了,因为在IIS运 行时,VC++的调试器不能够接管ISA。为了解决这个问 题,微软公司以两种形式发行了IIS:作为一项服务, 以及作为一个单独的可执行程序。对于后一种情况, 我们就可以在命令行上来控制服务器。虽然这样可以 解决上述问题并使得开发过程变得容易一些,但实现 起来显得很繁琐。下面我们来介绍这个过程。


    当用户处于debug调试模式时,VC++( 以及IIS)将在用户的帐号和权限下运行。由于通常IIS完 成的一些工作是不允许大多数用户有相应的权限的, 因此用户(或用户的系统管理员)需要做以下工作:

    在桌面上选择“开始\程序\管 理工具(公用)\域用户管理器”,打开域用户管理器;
    在“规则”菜单中选择“用户 权限”;
    选择“显示高级用户权限”检 查框;
    在“权限”下拉列表中选择“ 以操作系统方式操作”;
    选择“添加”按钮得到“添加 用户及组”对话框,选择“显示用户”按钮,并在“名 称”列表中选择用户使用的帐号,然后选择“添加” 按钮;
    选择“确定”按钮;
    对“产生安全审核”权限重复 上述步骤。

    为了使这些设置生效,用户必 须先退出登录,然后再登录回来。
    IIS中包含了三项服务:FTPPublishing Service,GopherPublishingService和WorldWideWeb。由于调试器要在命 令行上运行IIS,所以所有这三项服务都必须停止。这 可以通过“控制面板”中的“服务”程序或者使用IIS 的“Internet服务管理器”来实现。如果需要进行大量的 调试工作,我们建议用户通过“控制面板”中的“服 务”程序来关闭IIS服务并禁止它们自动启动,这样可 以避免用户每次启动计算机时都要进行关闭服务的 操作。
    接下来就必须对工程进行一些 配置了:
    在Project菜单中选择Settings菜单 项;
    选择Debug面板,并在Category下拉 列表中选择General;
    在Executablefordebugsession框中输入 或者寻找IIS执行文件的路径(通常情况下位于WINNT\system32\inetsrv\inetinfo.exe);
    在Programarguments框中输入-ew3svc,如 图3所示;图3 Debug面板设置
    选择Link面板;
    在Outputfilename框中输入被编译 后的DLL将被放置的路径和文件名。这个路径必须位于Web 服务器的根目录下或者某个虚拟目标下,以便客户可 以通过URL来访问。例如,我们的Web服务器的目录是c:\InetPub\wwwroot\firstisapi, 我们把firstisapi.dll放置在该目录下,这样客户就可以使用 下面的URL来访问它:
    http://127.0.0.1/firstisapi/firstisapi.dll
    如果用户现在还没有退出登录 以改变权限,请现在行动,然后再登录回来。
    如此,我们的服务器DLL就大功告成啦,赶快在浏览器里输入http://127.0.0.1/firstisapi/firstisapi.dll?Getdata&data=这是我发给服务器的信息!

    OK?

    这是你提交上来的数据:

    这是我发给服务器的信息!

    OK!

    要是我们想以form的表单形式向服务器提交数据呢?

    把下面这段HTML源码存为一个firstisapi.htm文件,放在DLL相同目录下。


    <form method="post" action="firstisapi.dll?">
    <p align="center"> </p>
    <input type="hidden" name="MfcISAPICommand" value="Getdata">
    <p align="center">要提交的数据:<input type="text" name="data" size="20"></p>
    <p align="center"><input type="submit" value="提交" > </p></form> </body> 


    返回


    四、ISAPI操作数据库

    上面我们定义了一个Getdata函数,在函数里我们实现了这样一个功能:把客户传送上的数据发给客户.要是操作数据库呢?一样的道理,我们只要在自己定义的函数里添加上操作数据库的代码,就可以实现存取数据库.输入的数据在变量data里,输出给客户机用*pCtxt 发给浏览器。
    现在我们建立一个数据库,用什么库由你选取吧,可以是ACCESS,SQL Server ,Sbase等,我们只要用数据源来操作它就行了,我们在建好库后建立系统数据源(不要建成用户数据源啊?为什么?问比尔.盖茨去吧)FirstODBC,用下面的SQL建立一个简单的表。
    表:用户资料
    create table user_info (
    id int (4) not null,
    friend_id int(4) not null,
    user_name varchar (30) not null,
    user_sex varchar (2) not null,
    address varchar (20),
    age int (4),
    zip char (6),
    phone varchar (20) )

    有了数据源,我们就可以添加代码实现数据库的查询,修改等。
    同上一节一样,在CFirstISAPIExtension里添加一个成员函数void Reg(CHttpServerContext *pCtxt,char *user_name,char *sex,char*address,int age,char*zip,char*phone)
    参数分别是:用户名,性别,地址,年龄,邮编和电话.我们要它实现的功能是把用户通过表单提交的数据写到FirstODBC数据库.然后同样在BEGIN_PARSE_MAP(CFirstISAPIExtension, CHttpServer)和END_PARSE_MAP(CFirstISAPIExtension)之间加入ON_PARSE_COMMAND(Reg, CFirstISAPIExtension,ITS_PSTR ITS_PSTR ITS_PSTR ITS_I2 ITS_PSTR ITS_PSTR)
    和ON_PARSE_COMMAND_PARAMS("user_name sex address='' age=20 zip='' phone='')
    ,如下所示:

    BEGIN_PARSE_MAP(CFirstISAPIExtension, CHttpServer)
    // TODO: insert your ON_PARSE_COMMAND() and
    // ON_PARSE_COMMAND_PARAMS() here to hook up your commands.
    // For example:
    ON_PARSE_COMMAND(Reg, CFirstISAPIExtension,ITS_PSTR ITS_PSTR ITS_PSTR ITS_I2 I
    ITS_PSTR ITS_PSTR)
    ON_PARSE_COMMAND_PARAMS("user_name sex address age zip phone)
    ON_PARSE_COMMAND(Getdata, CFirstISAPIExtension,ITS_PSTR)
    ON_PARSE_COMMAND_PARAMS("data")
    ON_PARSE_COMMAND(Default, CFirstISAPIExtension, ITS_EMPTY)
    DEFAULT_PARSE_COMMAND(Default, CFirstISAPIExtension)
    END_PARSE_MAP(CFirstISAPIExtension)

    下面我们定义自己的函数并进行数据库的操作,单击左边FirstISAPI classes,New Class,Name:CUserSet,Base class:CRecordset---------------OK,ODBC:FirstODBC,Table Name:user_info,OK.
    (请先看看stdafx.h里有没有#include )

    void Reg(CHttpServerContext *pCtxt,char *user_name,char *sex,char*address,int age,char*zip,char*phone)

    {//打开数据库源代码
    StartContent(pCtxt); // 打印 <HTML> 和 <BODY> 标记
    WriteTitle(pCtxt); // 打印 <TITLE> 、“标题内容”和 </TITLE> 标记等
    CDatabase db;
    if(!db.Open(_T("FirstODBC"), //(系统源名)
    FALSE, //bExclusive
    FALSE, //bReadOnly
    _T("ODBC; UID=sa; PWD=;"), //lpszConnect (与数据库的连接方式)
    FALSE)){ //bUseCursorLib
    *pCtxt << "Could not open database.";
    return;
    }
    CRecordset set(&db);
    try
    {
    set.Open();
    }
    catch (CDBException* pEx)
    {
    *pCtxt << _T("Error Selecting from table:");
    TCHAR szErrorMessage[1024];
    if (pEx->GetErrorMessage(szErrorMessage, sizeof(szErrorMessage)))
    {
    *pCtxt << szErrorMessage;
    *pCtxt << _T("\r\n");
    }
    return;
    }
    set.AddNew();
    set.Edit();
    set.m_id=0;
    set.m_user_name=user_name;
    set.m_sex=sex;
    set.m_address=address;
    set.m_age=age;
    set.m_zip=zip;
    set.m_phone=phone;
    set.Update();
    set.Close();
    db.Close();
    *pCtxt << _T("你已成功注册!\r\n");
    // 打印 </BODY> 和 </HTML> 标记
    EndContent(pCtxt);
    }
    把下面的HTML存为reg.htm

    <HTML>
    <BODY>
    <CENTER>
    <FONT COLOR='#FF0000'><H3>请在下面输入你的注册信息(含*的为必填内容)</H3>
    </FONT>
    </CENTER>
    <HR>
    <CENTER>
    <form method="post" action="firstisapi.dll?">
    <p align="center"> </p>
    <input type="hidden" name="MfcISAPICommand" value="Reg">
    <p align="center">姓名:<input type="text" name="user_name" size="20"></p>
    <p align="center">性别:
    <select name="sex" size="1">
    <option selected value="1">男</option>
    <option value="0">女</option>
    </select></p>
    <p align="center">地址:<input type="text" name="address" size="20"></p>
    <p align="center">年龄:<input type="text" name="age" size="20"></p>
    <p align="center">邮编:<input type="text" name="zip" size="20"></p>
    <p align="center">电话:<input type="text" name="phone" size="20"></p>
    <p align="center"><input type="submit" value="提交" > </p></form>
    </center>
    </BODY>
    </HTML>

    然后放到firstisapi目录里,.................. http://127.0.0.1/firstisapi/reg.htm 这样在浏览器的表单里输入你的数据后提交,看看你我服务器数据库,哈,有了----------->你已成功注册!! 本想再做一个查询程序,可是时间太紧,还是自己想想吧,和注册程序没什么两样,只要再加一个Chaxun(...)就
    OK That is all right!
    程序还有一些不完美的地方就是还不能检验用户名是否已被注册,还没有到得ID的最大值,不过在此只是为了演示如何操作数据库,笔者因此没有深虑,有兴趣的朋友自己可以加上这方面的代码。

    返回


    五、利用ISAPI进行网络数据传送

    所谓网络数据传送,简单地说,就是把数据从一台计算机传输到网络上的另外一台计算机.说起数据传输,大家最熟的不过socket套接字了,无论在UNIX,WINDOWS,它一贯都是公认的传输方案.笔者在研究了ISAPI之后,成功地实现了用ISAPI进行网络数据传输,并且解决了局域网防火墙内数据的有效传输.
    首先,我们要建立服务器数据接收ISAPI程序.在第三节<ISAPI实现 客户/服务器 交互 >里我们已经建立了一个Getdata(..char *data)函数,其中data里存放的就是我们从客户机传上来的数据,在这个函数里,我们就可以对它进行处理,如写文件,写数据库等,再通过*pCtxt向客户发送回执.关于如何写库写文件已超出本节范围,在此不再赘述。
    在第三节里,我们是通过form表单通过浏览器把数据发送给服务器,在这里,我们要通过我们客户机的程序向服务器发送数据。在你的程序里添加一个成员函数:BOOL SendData(char *ip,char *request, char *buffer, unsigned int bufferlen),其中参数ip为服务器IP地址,如果是本机调,传入 127.0.0.1;request为要发送到服务器的数据,最终由Getdata()接收,存放在data里供服务器处理程序处理;buffer为服务器传回回执存放绶冲区,即*pCtxt串行回的数据 bufferlen为buffer绶冲区长度。SendData代码如下:
    BOOL SendData(char *ip,char *request, char *buffer, unsigned int bufferlen)
    {
    int ret=0;
    CString URL;
    URL="http://";
    URL+=(CString)ip;
    URL+="/firstisapi/firstisapi.dll?Getdata&data=";
    URL+=(CString)request;
    //
    //AfxMessageBox(URL);
    CInternetSession session;
    CInternetFile *cf;
    //----------------
    try {
    cf = (CInternetFile * )session.OpenURL (URL);
    }
    catch (CInternetException * Exp)
    {
    char err[1024];
    Exp->GetErrorMessage (err, 1024, NULL);
    AfxMessageBox(err);
    cf = NULL;
    Exp->Delete ();
    }
    if (cf) {
    ret=cf->Read(buffer, bufferlen);
    cf->Close ();
    }
    session.Close ();
    return(ret);
    }
    这样我们在程序里可以这样调用它:
    void CSassDlg::OnButton1()
    {
    // TODO: Add your control notification handler code here
    CString ip="127.0.0.1",data="这是我要发给服务器的数据",buffer;
    BOOL b=SendData((char *)LPCTSTR(ip),(char *)LPCTSTR(data),buffer.GetBuffer(1204), 1024);
    if(b){
    MessageBox("数据发送成功");
    }
    }
    这样,我们只要把要发送给服务器的数据传给SendData的第二个参数,服务器data就可收到,你想怎么处理就怎么处理吧。

    返回


    六、ISAPI传输数据的加密

    为了提高数据传的安全性,可靠性,我们在数据传输之前都要对数据进行加密,但是无论哪种加密算法,进行加密的数据都有可能出现诸如"@#$%^&*-+"及不可字符,可是用ISAPI这种方法传输时,服务器经过ON_PARSE_COMMAND和ON_PARSE_COMMAND_PARAMS参数映射宏进行处理后,如"%,&"等字符将会进行自动转换或作为分隔字符处理, 这样,服务器收到的数据将会是错误的。为了保证数据传输的可靠性,笔者经过多方面研究,自己定义了下面两个函数,分别作为客户机加密后上传前数据处理和服务器接收到数据后解密前处理。
    客户机加密后上传前数据处理函数:
    void code(char *buf, int len, char *outstr)//加密后处理
    {
    CString str;
    int outstr_len;
    outstr_len=0;
    char *tmp;
    tmp=new char[16];
    outstr[0]=0;
    for (int i=0; i<len ;i++)
    {
    tmp[0]=0;
    if(buf[i]=='%'||buf[i]=='&'||buf[i]=='!'||buf[i]=='?'||buf[i]=='+'||buf[i]=='\\'||buf[i]=='/')
    {
    str.format("%%%x",buf[i]);
    strcpy(tmp,str);
    outstr_len+=3;
    }
    else
    {tmp[0]=buf[i];tmp[1]=0;outstr_len++;}
    if(buf[i]=='$')
    {strcpy(tmp,"$$");outstr_len+=2;}
    if(buf[i]==0)
    {strcpy(tmp,"$0");outstr_len+=2;}
    strcat(outstr,tmp);
    }
    return;
    }
    其中 buf 为传入数据绶冲区指针,len为buf数据长度,outbuf为处理后数据存放绶冲区.处理时将诸如"%,&,+"等特殊字符及0字符进行处理,这样,数据传送到服务器后将会是正确的,之后经过服务器处理函数进行还原,再解密,那我们的数据就不会有错了。

    服务器接收到数据后解密前处理函数:
    int decode(char *buff, int len, char *outstr)
    //上传后处理
    {
    int i, p;
    char v;
    p=0;
    for (i=0; i<len; i++)
    {
    if (buff[i]=='$')
    {
    if (buff[i+1]=='$')
    {
    v='$';
    }
    else
    {
    if(buff[i+1]=='0')
    v=0;
    }
    i++;
    }
    else
    {
    v = buff[i];
    }
    outstr[p]=v; p++;
    }
    return(p);
    }
    其中 buff 为传入数据绶冲区指针,len为buff数据长度,outstr为处理后数据存放绶冲区.
    处理流程:
    对Data 进行加密-------->code函数进行处理-------->服务器接到data------- >decode进行上传后处理------->解密


    返回


    七、ISAPI网络数据传送进阶(网络大数据包传送)

    笔者曾尝试用上述方法传输大数据包,可是发现这种方法只可传输小于2K的数据包,这无疑成为它一个缺点。经过多方面的研究,发现这种方法是用GET方法发送数据,操作系统本身就限制了它的数据量。以后经过测试,如用POST方法传输,发送数据包的大小将不受限制。下节将讲解如何用POST方法向服务器发送数据。

    BOOL PostData(char *ip,char *request,char *out_buf,int buf_len)
    {
    BOOL ret=FALSE;
    char *buffer,*buff,*out;
    buffer=new char[2048];
    int bb_len=strlen(request);
    buff=new char[bb_len];
    out=new char[bb_len+1000];
    CInternetSession session;
    CHttpFile* pFile=NULL;
    CHttpConnection* pConnection=NULL;

    CString m_ip,sql;
    m_ip=(CString)ip;
    //----------------------------对request加密
    strcpy(buff,request);
    for(int i=0;i<bb_len;i++)//
    buff[i]=buff[i]^(char)((i+0x56)%255);
    code (buff,bb_len,out);//上传前处理
    //-----------------------------------
    sql=(CString)out;
    CString strHeaders =_T("Content-Type: application/x-www-form-urlencoded");
    CString str,strformData = _T("data=");
    strformData+=sql;
    try
    {
    pConnection =
    session.GetHttpConnection(m_ip);
    pFile =
    pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,
    _T("/firstisapi/firstisapi.dll?Getdata"));
    BOOL result = pFile->SendRequest(strHeaders,
    (LPVOID)(LPCTSTR)strformData, strformData.GetLength());
    DWORD dwRet;
    pFile->QueryInfoStatusCode(dwRet);
    //--------------
    if (dwRet == HTTP_STATUS_OK)
    {
    buf_len=pFile->Read(buffer,2048);
    str=(CString)buffer;
    str=str.Left(buf_len);
    ret=TRUE;
    }
    else
    str="服务器处理错误!";
    pFile->Close ();
    delete pFile;
    pConnection->Close();
    delete pConnection;
    }
    catch(CInternetException* pEx)
    {
    TCHAR szErr[1024];
    pEx->GetErrorMessage(szErr, 1024);
    str=szErr;
    pEx->Delete();
    }
    catch (...)
    {
    str="和服务器通信时发生意外!";
    }

    session.Close();
    strcpy(out_buf,str);
    buf_len=str.GetLength ();
    MessageBox(NULL, str, "系统提示", MB_OK);
    delete buffer;
    delete buff;
    delete out;
    return ret;
    }
    其中参数ip为服务器IP地址,如果是本机调,传入 127.0.0.1;request为要发送到服务器的数据,最终由Getdata()接收,存放在data里供服务器处理程序处理;buffer为服务器传回回执存放绶冲区,即*pCtxt串行回的数据 bufferlen为buffer绶冲区长度。

    服务器接收程序同前,这样,我们就可以发送大于2K的数据了。

    返回


    八、总结

    强抢时间,终于完成了,只是简单的完成,肯定还有很多不正确的地方,望大家的使用时发现错误请回函!谢谢!

    此文可在保留作者著作权的前提下自由转载。

    龙飞信箱

    OurCode.Net

  • 相关阅读:
    LeetCode
    <OFFER15> 15_NumberOf1InBinary
    《OFFER14》14_CuttingRope
    Convert DataFrame string complex i to j python // “Cloning” row or column vectors
    Sorting arrays in NumPy by column
    【説明する】深度优先及宽度优先算法比较
    codevs 2924 数独挑战 x(三种做法+超详细注释~)
    第四次考试大整理
    洛谷 P1048 采药
    codevs 3137-3139 栈练习 x
  • 原文地址:https://www.cnblogs.com/chenbg2001/p/1553123.html
Copyright © 2011-2022 走看看