`
braverong
  • 浏览: 6158 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

C++上传文件到Restful Web Service服务端——客户端篇

    博客分类:
  • HTTP
阅读更多

转载:http://blog.csdn.net/ronux/article/details/8244840

    由于项目的需要,要做一个C++的http请求客户端实现上传数据到服务端的功能,服务端用的是Spring MVC实现的Restful Web Service,起初设计时在服务端以byte[]的形式接受数据,毕竟服务端用java写的,把接收到的数据流解析成相应的文件这是完全可行的。

    如果写过Java或者其他语言的Http请求的人都知道,请求方式可以分GET和POST两种,不过GET传递的数据充其量只是简单类型的参数而已,在请求时的数据格式如代码,这是请求http://www.ip138.com:8080/search.asp?mobile=1565888&action=mobile站点的请求参数:

 

GET /search.asp?mobile=1565888&action=mobile HTTP/1.1
Host: www.ip138.com:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive

以上是用FireFox的插件Live Http Headers获取的数据,而且这个插件可以自行编辑参数定制HTTP请求,方便编程的测试工作,具体使用可以查阅资料。这里面好多参数并不是必须的,但是为了模拟浏览器的效果最好设置一下。另外对于GET请求不需要设置Content-Type和Content-Length参数,通常这两个也是成对出现的。User-Agent表示请求客户端的浏览器和OS信息,这里模拟浏览器访问可以自己定制。

 

    POST请求的数据是放在请求体里的,具体信息可参考http://blog.csdn.net/yc0188/article/details/4741871,严格按照要求组织请求数据即可。注意请求头和请求数据之间的空行。这是一个Web系统的POST请求数据:

POST /myproject/infoUpdate HTTP/1.1
Host: 192.168.52.250:8088
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://192.168.52.250:8088/myproject/infoUpdate.action
Content-Type: application/x-www-form-urlencoded
Content-Length: 24

infoId=3&currentPage=1

另外在具体组织请求信息时,Windows下是用\r\n作为换行符的,但是在linux下这样用也不错,虽然linux的换行符是\n。

 

 

strcat(requestStr, "POST ");
strcat(requestStr, api);
strcat(requestStr, " HTTP/1.1\r\n");
strcat(requestStr, "Accept: application/x-ms-application, image/gif, "
	"application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, "
	"application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n");
strcat(requestStr, "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:17.0) Gecko/17.0 Firefox/17.0\r\n");
strcat(requestStr, "Accept-Language: zh-CN,en-US;q=0.5\r\n");
strcat(requestStr, "Accept-Encoding: gzip, deflate\r\n");
strcat(requestStr, "Host: ");
strcat(requestStr, hostname);
strcat(requestStr, "\r\n");

    POST简单的数据以上就可以做到,但是对于上传文件呢。文件通常是二进制形式的,也就是要传输流。不过我们对struts2或者Spring MVC的上传文件表单不陌生,于是我监测了一个上传文件操作的请求数据:

 

 

POST /myproject/infoUpdate HTTP/1.1
Host: 192.168.52.250:8088
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------41184676334
Content-Length: 95254

-----------------------------41184676334\r\n
Content-Disposition: form-data; name="id"\r\n
\r\n
6\r\n
-----------------------------41184676334\r\n
Content-Disposition: form-data; name="doc"; filename="faq_info.jpg"\r\n
Content-Type: image/jpeg\r\n
\r\n
……请求的数据流……
\r\n-----------------------------41184676334--\r\n

这里用到了boundary(分隔符),用来间隔不同的请求数据,这是Content-Type类型为multipart/form-data(Spring MVC Restful Web Service也支持multipart/mixed的类型用于上传文件)时所要求的数据格式,和Content-Type为application/x-www-form-urlencoded时用&间隔参数是一样的。但是要注意使用的规则,可参见http://blog.csdn.net/mspinyin/article/details/6141638。Java版本的HttpURLConnection请求可参考:http://lapulande.iteye.com/blog/719581。C++版的可以用Windows下的winsock,代码可参考:http://www.cnblogs.com/evlon/archive/2007/08/13/853145.htmlhttp://www.oschina.net/code/snippet_176076_5908分别是windows下的和linux的范例,上述链接代码只是使用socket完成了请求操作,并没有做上传数据的部分。我建议用到的朋友可以先用Java版的客户端进行上传文件测试,如果测试通过了,可以比照着写C++的代码,在请求头部分C++老老实实地组织对应的参数就可以,请求数据部分要严格注意换行的地方,以及上传文件的长度加入Content-Length(包括上传数据长度和分隔符等其他字符的长度)。

    文件流的长度可以这样获得:

 

ifstream fin(filePath ,ios::in|ios::binary);
  if(!fin){
    cout<<"File open error!\n";
    return -1;
  }
  //---get the length of the file
  int temp = fin.tellg();
  fin.seekg(0,ios_base::end);
  int len = fin.tellg();
  fin.seekg(temp);

获得长度后重新定位到文件开始处。

 

    上传文件流时要读取多少send多少,否则服务端得到的是错误的流,且在send时不要用strlen(c)来指定发送的长度,因为char* c中可能包含‘\0’这样的空字符,从而使用了错误的长度。

 

  char c[1024];
  memset(c, 0,1024);
  int tmpLen=0;
  int i=0;
  while(!fin.eof())
  {
	if(tmpLen<(len/1024)*1024) //首先按照1024的单位传
	{
		fin.read(c, 1024);
		send(sock,c,1024,0);
		Sleep(1); //休息,为了降低CPU使用率以及照顾带宽
		tmpLen+=1024;
	}else //如果剩余的小于等于1024了,单独send剩余的字节
	{
		fin.read(c,len-(len/1024)*1024);
		send(sock,c,len-(len/1024)*1024,0);
		break;
	}
  }
  fin.close();

    在C++里用socket建立的请求,没有使用HTTP协议,可以选择TCP或者UDP协议,默认用TCP。我在测试中使用WireShark监测传输的数据时,在HTTP相关协议中没有看到数据,原因就在于此,Java版请求的就可以检测到。

 

分享到:
评论

相关推荐

    .NET 作为客户端调用WEBAPI RESTFUL服务端以及如何开发RESTFUL服务端用于客户端调用

    本篇文章将详细探讨.NET作为客户端调用WebAPI RESTful服务端的方法,以及如何开发RESTFUL服务端以供客户端调用。 首先,让我们了解一下客户端如何使用.NET调用WebAPI RESTful服务端。这通常涉及以下几个步骤: 1. ...

    C# 一个简单的 Restful 服务端和 Restful 客户端 Demo

    - `Restful-Service-And-Restful-Client-master`可能包含了服务端和客户端的源代码。服务端通常包括控制器类、模型类和Startup配置等,客户端可能包含主程序类和使用HttpClient发送请求的相关代码。 6. **测试和...

    WebServices服务端和客户端DEMO

    服务端会提供WSDL文件,客户端根据该文件生成相应的客户端代码,实现对服务的调用。 总结来说,"WebServices服务端和客户端DEMO"涵盖的内容广泛,包括Spring Boot的使用、Apache CXF的集成、服务端Web Services的...

    当当网——客户端——服务端

    标题 "当当网——客户端——服务端" 暗示了我们要探讨的是关于当当网的客户端和服务端架构以及它们之间的交互。当当网是中国知名的在线图书、电子商品零售平台,其客户端通常指的是用户使用的应用程序,如手机APP或...

    C#服务端RestFul Service-经验案例.doc

    C#服务端RestFul Service开发经验案例 本文档介绍了如何使用C#语言创建服务端RestFul Service接口,并提供了详细的代码说明,方便用户学习和深入掌握。该经验案例主要讲解了如何使用RestFul数据访问方式将装备软件...

    c# 服务端调用RestFul Service的方法

    ### C# 服务端调用 RestFul Service 的方法 #### 概述 本文档将详细介绍如何使用 C# 创建和调用 RESTful 接口,包括 RESTful 的基本概念、如何构建 RESTful 风格的 API、服务端的具体实现步骤以及客户端如何调用...

    大神的Restful Web Service 详细介绍

    大神的Restful Web Service 详细介绍,Objectives By the end of this class, you should be able to: Give a working definition of RESTful Web Services actions, Enable a RESTful user in the SM operator ...

    Java Restful Web 源代码,Java Restful Web 源代码

    Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web...

    RESTful Web Service实现转账

    综上所述,实现RESTful Web Service进行转账业务涉及到资源的定义、事务处理以保证数据一致性,以及并发控制以应对高并发场景。通过合理设计API接口,结合事务管理和并发控制策略,我们可以构建出高效且可靠的转账...

    服务端与客户端

    在这里,SDK可能包含了服务端和客户端通信所需的接口定义、库文件、示例代码以及相关的开发文档。 在创建SDK服务端与客户端程序时,一般会涉及以下几个关键知识点: 1. **通信协议**:服务端与客户端之间的通信...

    java利用 xfire实现 webservices 服务端与客户端

    本篇文章将深入探讨如何利用XFire在服务端和客户端之间建立Web服务通信。 一、Web服务基础 Web服务是一种基于标准的,能够跨越不同操作系统、编程语言和网络环境的通信方式。它们通常使用SOAP(Simple Object ...

    《Java RESTful Web Service实战》PDF版本下载.txt

    《Java RESTful Web Service实战》PDF版本下载

    restful服务端及客户端开发[参照].pdf

    RESTful服务端主要是通过创建Web服务接口,客户端则通过调用这些接口与服务端进行通信。以下是关于RESTful服务端及客户端开发的一些关键知识点: 1. **HTTP方法**: - **GET**:用于获取资源,通常用于查询操作,...

    基于C++&Qt实现的在线点餐系统(客户端+服务端——.zip

    常见的服务端架构可能包括RESTful API设计,确保与客户端的通信简洁、高效。 在实际开发过程中,开发者还需要考虑错误处理、异常捕获、性能优化、用户体验等因素。此外,良好的代码组织结构和文档也是项目成功的...

    JAX-RS方式的RESTful Web Service开发

    **JAX-RS方式的RESTful Web Service开发详解** RESTful Web Service是一种基于HTTP协议的、无状态的、客户端-服务器交互模式,它利用HTTP方法(GET、POST、PUT、DELETE等)来实现对资源的操作。JAX-RS是Java API ...

    RESTful Web Service Demo

    在"RESTful Web Service Demo"项目中,我们将探讨如何使用Java语言来创建这样的服务,并提供CURD(Create、Read、Update、Delete)操作。 首先,理解RESTful架构的关键概念: 1. 资源(Resource):在REST中,一切...

    2018最新谷歌浏览器RESTful Web Service离线版包含definitions.json

    标题中的“2018最新谷歌浏览器RESTful Web Service离线版”指的是一个适用于谷歌浏览器的、用于开发和测试RESTful Web服务的工具,该工具的离线版本。RESTful Web Service是一种基于HTTP协议的软件架构风格,用于...

    cxf简单实例 服务端与客户端

    1. 生成客户端代理:CXF提供了工具(如wsdl2java或JAXB)可以从服务端的WSDL(Web Service Description Language)文件生成客户端所需的Java类。 2. 初始化客户端:使用生成的Java类,初始化客户端代理对象,并设置...

    基于android的智能订餐系统(服务端+客户端+数据库).zip

    其次,"SmartDiningService"则是服务端的实现,这部分可能基于Java的Spring Boot框架或者Node.js的Express框架,通过RESTful API与客户端进行数据交互。服务端主要负责处理来自客户端的请求,如验证用户身份、处理...

Global site tag (gtag.js) - Google Analytics