Windows客户端开发--wininet和winsock实现上传文件

写了《 Windows客户端开发–URLDownloadToFile下载文件》,继续写文件上传吧。

上传文件的方法应该会很多,这里介绍两种wininet和winsock,其中wininet和WinHTTP 有很多相似的地方,我们这里就只介绍wininet了。

为实现Http访问,微软提供了二套API:WinINet, WinHTTP。WinHTTP比WinINet更加安全和健壮,可以这么认为WinHTTP是WinINet的升级版本。

关于wininet和WinHTTP的区别,可以参考链接:
https://msdn.microsoft.com/en-us/library/aa384068.aspx

正式开始!!!!

wininet

WinInet(“Windows Internet”)API帮助程序员使用三个常见的Internet协议,这三个协议是用于World Wide Web万维网的超文本传输协议(HTTP:Hypertext Transfer Protocol)、文件传输协议(FTP:File Transfer Protocol)和另一个称为Gopher的文件传输协议。WinInet函数的语法与常用的Win32 API函数的语法类似,这使得使用这些协议就像使用本地硬盘上的文件一样

下面来说说实现wininet访问的流程(WinHTTP比WinINet都一样的流程):

1 打开一个Session获得一个HINTERNET session句柄;

2 使用这个session句柄与服务器连接得到一个HINTERNET connect句柄;

3 使用这个connect句柄来打开Http 请求得到一个HINTERNET request句柄;

4 使用这个request句柄来发送数据与读取从服务器返回的数据;

5 依次关闭request,connect,session句柄。

看看代码:

#include <windows.h>
#include <wininet.h>
#include <tchar.h>
#include <iostream>

#pragma comment(lib,"wininet.lib")

using namespace std;

int main()
{

    static TCHAR frmdata[] = "-----------------------------7d82751e2bc0858\nContent-Disposition: form-data; name=\"uploadedfile\"; filename=\"C:\test.txt\"\nContent-Type: text/plain\n\nfile contents  here\n-----------------------------7d82751e2bc0858--"; 

    static TCHAR hdrs[] = "Content-Type: multipart/form-data; boundary=---------------------------7d82751e2bc0858"; 

    HINTERNET hSession = InternetOpen("MyAgent",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
     if(hSession==NULL)
    {
     cout<<"Error: InternetOpen";  
    }


    HINTERNET hConnect = InternetConnect(hSession, _T("localhost"),INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
     if(hConnect==NULL)
    {
     cout<<"Error: InternetConnect";  
    }

    HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",_T("upload.php"), NULL, NULL, (const char**)"*/*\0", 0, 1);
    if(hRequest==NULL)
    {
     cout<<"Error: HttpOpenRequest";  
    }

    BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), frmdata, strlen(frmdata));
    if(!sent)
    {
     cout<<"Error: HttpSendRequest";
     }


    InternetCloseHandle(hSession);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hRequest);

    return 0;
}

winsock

Windows下网络编程的规范-Windows Sockets是Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口。

#include <iostream>
#include <winsock2.h>
#include <string>
using namespace std;

//link libwsock32.a

unsigned long WinsockStart()
{
     WSADATA wsa;
     unsigned long ulong;
     struct hostent *host;

     if(WSAStartup(MAKEWORD(2,2), &wsa) < 0)
     {
          cout << "Error WinsockStart()" << endl;
          WSACleanup();
          return 1;
     }

     if((host=gethostbyname("www.example.com"))<0)
     {
          cout << "Fehler gethostbyname()" << endl;
          WSACleanup();
          return 2;
     }

     ulong = *(unsigned long*) host->h_addr;

     return ulong;
}

void error_exit(string text)
{
     cout << text;
     WSACleanup();
     exit(EXIT_FAILURE);
 }



int main()
{
    SOCKET sock;
    struct sockaddr_in addr;
    unsigned long win=0;
    int con = 0, gr=0, send_r=0, rec=0;
    char header[2048], puffer[2018]; 
    string to_send="hello world";
    string name="test99.txt";

    win=WinsockStart();
    if(win==1||win==2)
       error_exit("Error WinsockStart()");

    addr.sin_family=AF_INET;
    addr.sin_port=htons(80);
    addr.sin_addr.s_addr = win;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock<0)
       error_exit("Error socket()");

    gr = (to_send.size()+name.size()+287);

    sprintf(header, "POST /upload.php HTTP/1.1\r\n");
    sprintf(header, "%sHost: www.example.com\r\n", header);
    sprintf(header, "%sConnection: Keep-Alive\r\n", header);
    sprintf(header, "%sContent-Type: multipart/form-data; boundary=---------------------------90721038027008\r\n", header);
    sprintf(header, "%sContent-Length: %d\r\n", header, gr);
    sprintf(header, "%s\r\n", header);
    sprintf(header, "%s-----------------------------90721038027008\r\n", header);
    sprintf(header, "%sContent-Disposition: form-data; name=\"upfile\"; filename=\"%s\"\r\n", header, name.c_str());
    sprintf(header, "%sContent-Type: text/plain\r\n", header);
    sprintf(header, "%s\r\n", header);
    sprintf(header, "%s%s\r\n", header, to_send.c_str());
    sprintf(header, "%s-----------------------------90721038027008\r\n", header);
    sprintf(header, "%sContent-Disposition: form-data; name=\"post\"\r\n", header);
    sprintf(header, "%s\r\n", header);
    sprintf(header, "%supload\r\n\r\n", header);
    sprintf(header, "%s-----------------------------90721038027008--\r\n\r\n\0", header);      

    con = connect(sock, (SOCKADDR*)&addr, sizeof(addr));
    if(con < 0)
       error_exit("Error connect()");

    if(send_r=send(sock, header, strlen(header), 0)<0)
       error_exit("Error send()");

     while(rec=recv(sock, puffer, 2048, 0))
     {
          if(rec==0)
              error_exit("Server quit");

          printf("%s", puffer);
     }               

    closesocket(sock);
    WSACleanup();
    return EXIT_SUCCESS;
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一苇渡江694

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

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

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

打赏作者

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

抵扣说明:

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

余额充值