cocos2d-x 通过socket实现http下载及断点续传的实现
cocos2d-x 通过socket实现http下载及断点续传的实现
代码未经进一步的整理,可能比较混乱。
首先,2dx的socket库由BSSocket组成。可跨平台,在windows上已验证。

1 #ifndef _NET_BSSOCKET_H_
2 #define _NET_BSSOCKET_H_
3
4 #ifdef WIN32
5 #include <winsock.h>
6 #include <windows.h>
7 typedef int socklen_t;
8 #else
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <netdb.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <arpa/inet.h>
17 typedef int SOCKET;
18
19 //#pragma region define win32 const variable in linux
20 #define INVALID_SOCKET -1
21 #define SOCKET_ERROR -1
22 //#pragma endregion
23 #endif
24
25 #include "pthread/pthread.h"
26 #include <iostream>
27 #include <vector>
28
29 class BSSocket;
30 using namespace std;
31
32 static BSSocket* bsSocket = NULL;
33
34 const int MAX_BSSOCKETMSG_BUFF = 1024 * 64;
35 class BSSocket {
36
37 private:
38
39 static unsigned char socketBuff[MAX_BSSOCKETMSG_BUFF];
40 static unsigned long socketBuffLen;
41
42 bool need_quit;
43 bool isConnected;
44
45 char* connectIp;
46 unsigned int connectPort;
47 // Send socket
48
49 public:
50 int Send(const char* buf, int len, int flags = 0);
51 BSSocket(SOCKET sock = INVALID_SOCKET);
52 static BSSocket* getInstance();
53 void initConnect(const char* ip, unsigned short port);
54
55 ~BSSocket();
56
57 // Create socket object for snd/recv data
58 bool Create(int af, int type, int protocol = 0);
59
60 // Connect socket
61 bool Connect(const char* ip, unsigned short port);
62 bool ConnectSyn(const char* ip, unsigned short port);
63 //#region server
64 // Bind socket
65 bool Bind(unsigned short port);
66
67 // Listen socket
68 bool Listen(int backlog = 5);
69
70 // Accept socket
71 bool Accept(BSSocket& s, char* fromip = NULL);
72 //#endregion
73
74 // Recv socket
75 int Recv(char* buf, int len, int flags = 0);
76
77 // Close socket
78 int Close();
79
80 // Get errno
81 int GetError();
82
83 //#pragma region just for win32
84 // Init winsock DLL
85 static int Init();
86 // Clean winsock DLL
87 static int Clean();
88 //#pragma endregion
89
90
91
92 BSSocket& operator = (SOCKET s);
93
94 operator SOCKET ();
95
96 int m_nRecvBufLen;
97 char m_szRecvBuf[MAX_BSSOCKETMSG_BUFF + 1]; /*接收缓存区*/
98
99 int getFd() { return m_sock; };
100 SOCKET m_sock;
101
102
103 };
104
105 #endif // !_NET_BSSOCKET_H_

及cpp的实现

1 #include "BSSocket.h"
2
3 #ifdef WIN32
4 #pragma comment(lib, "wsock32")
5 #endif
6
7
8 BSSocket::BSSocket(SOCKET sock)
9 :need_quit(false),isConnected(false), connectIp(NULL), connectPort(0)
10 {
11 m_sock = sock;
12 }
13
14 BSSocket::~BSSocket()
15 {
16 }
17
18 int BSSocket::Init()
19 {
20 #ifdef WIN32
21 /*
22 http://msdn.microsoft.com/zh-cn/vstudio/ms741563(en-us,VS.85).aspx
23
24 typedef struct WSAData {
25 WORD wVersion; //winsock version
26 WORD wHighVersion; //The highest version of the Windows Sockets specification that the Ws2_32.dll can support
27 char szDescription[WSADESCRIPTION_LEN+1];
28 char szSystemStatus[WSASYSSTATUS_LEN+1];
29 unsigned short iMaxSockets;
30 unsigned short iMaxUdpDg;
31 char FAR * lpVendorInfo;
32 }WSADATA, *LPWSADATA;
33 */
34 WSADATA wsaData;
35 //#define MAKEWORD(a,b) ((WORD) (((BYTE) (a)) | ((WORD) ((BYTE) (b))) << 8))
36 WORD version = MAKEWORD(2, 0);
37 int ret = WSAStartup(version, &wsaData);//win sock start up
38 if ( ret ) {
39 // cerr << "Initilize winsock error !" << endl;
40 return -1;
41 }
42 #endif
43
44 return 0;
45 }
46 //this is just for windows
47 int BSSocket::Clean()
48 {
49 #ifdef WIN32
50 return (WSACleanup());
51 #endif
52 return 0;
53 }
54
55 BSSocket& BSSocket::operator = (SOCKET s)
56 {
57 m_sock = s;
58 return (*this);
59 }
60
61 BSSocket::operator SOCKET ()
62 {
63 return m_sock;
64 }
65 //create a socket object win/lin is the same
66 // af:
67 bool BSSocket::Create(int af, int type, int protocol)
68 {
69 m_sock = socket(af, type, protocol);
70 std::cout << "the errro info" << GetError();
71 if ( m_sock == INVALID_SOCKET ) {
72 return false;
73 }
74 return true;
75 }
76
77 bool BSSocket::Connect(const char* ip, unsigned short port)
78 {
79 struct sockaddr_in svraddr;
80 svraddr.sin_family = AF_INET;
81 svraddr.sin_addr.s_addr = inet_addr(ip);
82 svraddr.sin_port = htons(port);
83 int ret = connect(m_sock, (struct sockaddr*)&svraddr, sizeof(svraddr));
84 if ( ret == SOCKET_ERROR ) {
85 return false;
86 }
87 std::cout << "you are connected" << std::endl;
88 isConnected = true;
89 return true;
90 }
91
92 bool BSSocket::Bind(unsigned short port)
93 {
94 struct sockaddr_in svraddr;
95 svraddr.sin_family = AF_INET;
96 svraddr.sin_addr.s_addr = INADDR_ANY;
97 svraddr.sin_port = htons(port);
98
99 int opt = 1;
100 if ( setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) < 0 )
101 return false;
102
103 int ret = bind(m_sock, (struct sockaddr*)&svraddr, sizeof(svraddr));
104 if ( ret == SOCKET_ERROR ) {
105 return false;
106 }
107 return true;
108 }
109 //for server
110 bool BSSocket::Listen(int backlog)
111 {
112 int ret = listen(m_sock, backlog);
113 if ( ret == SOCKET_ERROR ) {
114 return false;
115 }
116 return true;
117 }
118
119 bool BSSocket::Accept(BSSocket& s, char* fromip)
120 {
121 struct sockaddr_in cliaddr;
122 socklen_t addrlen = sizeof(cliaddr);
123 SOCKET sock = accept(m_sock, (struct sockaddr*)&cliaddr, &addrlen);
124 if ( sock == SOCKET_ERROR ) {
125 return false;
126 }
127
128 s = sock;
129 if ( fromip != NULL )
130 sprintf(fromip, "%s", inet_ntoa(cliaddr.sin_addr));
131
132 return true;
133 }
134
135 int BSSocket::Send(const char* buf, int len, int flags)
136 {
137 int bytes;
138 int count = 0;
139
140 while ( count < len ) {
141 bytes = send(m_sock, buf + count, len - count, flags);
142 if ( bytes == -1 || bytes == 0 ) {
143 std::cout << "the send errro info" << GetError();
144 return -1;
145 }
146 count += bytes;
147 }
148
149 return count;
150 }
151
152 int BSSocket::Recv(char* buf, int len, int flags)
153 {
154 return (recv(m_sock, buf, len, flags));
155 }
156
157 int BSSocket::Close()
158 {
159 #ifdef WIN32
160 return (closesocket(m_sock));
161 #else
162 return (close(m_sock));
163 #endif
164 }
165
166 int BSSocket::GetError()
167 {
168 #ifdef WIN32
169 return (WSAGetLastError());
170 #else
171 return (errno);
172 #endif
173 }
174
175
176
177 void BSSocket::initConnect( const char* ip, unsigned short port )
178 {
179 connectIp = new char[sizeof(ip)];
180 strcpy(connectIp, ip);
181 connectPort = port;
182 pthread_t initThread;
183 }
184
185
186
187 BSSocket* BSSocket::getInstance()
188 {
189 if(bsSocket == NULL) {
190 bsSocket = new BSSocket;
191 }
192 return bsSocket;
193 }
194
195
196
197 bool BSSocket::ConnectSyn( const char* ip, unsigned short port )
198 {
199 Init();
200 Create(AF_INET, SOCK_STREAM, 0);
201 bool success = Connect(ip, port);
202 std::cout << "connect status is = " << success << std::endl;
203 return success;
204 }

通过ConnectSyn实现连接,若失败则返回false
其次在其基础上封装了一层HttpSocket通过这一层的封装实现对http连接的下载
主要由静态方法

1 bool CHttpSocket::downFile( string strServer, string strObject, int nPort, string saveFile, int from, int to )
2 {
3 CHttpSocket httpSocket;
4 long nLength;
5 const char *pRequestHeader = NULL;
6 pRequestHeader = httpSocket.FormatRequestHeader((char *)strServer.c_str(),(char *)strObject.c_str(),nLength, NULL, NULL, from, to);
7 httpSocket.Connect((char *)strServer.c_str(), nPort);
8 httpSocket.SendRequest();
9 httpSocket.SetTimeout(10000,0);
10 char szValue[100];
11 httpSocket.GetField("Content-Length",szValue,30);
12 int nFileSize = atoi(szValue);
13
14
15 int downFrom = 0, downTo = 0, fileSize;
16 httpSocket.GetField("Content-Range",szValue,100);
17 if(getRange(string(szValue), downFrom, downTo, fileSize)) {
18 int nCompletedSize = 0;
19 int nDownloadSize = downTo - downFrom + 1;
20 ensureFile(saveFile, fileSize);
21 fstream outFile;
22 outFile.open(saveFile.c_str(), ios::out|ios::in|ios::binary);
23 outFile.seekp(downFrom);
24 char pData[8192];
25 int nReceSize = 0;
26 long dwStartTime,dwEndTime;
27 while(nCompletedSize < nDownloadSize)
28 {
29 dwStartTime = GetTickCount();
30 nReceSize = httpSocket.Receive(pData,8192);
31 if(nReceSize == 0)
32 {
33 printf("服务器已经关闭连接.");
34 break;
35 }
36 if(nReceSize == -1)
37 {
38 printf("接收数据超时.");
39 break;
40 }
41 dwEndTime = GetTickCount();
42 outFile.write(pData, nReceSize);
43 nCompletedSize += nReceSize;
44 printf("write count is %d", outFile.gcount());
45 printf("download size is %d, all size is %d", nCompletedSize, nFileSize);
46 }
47 outFile.close();
48 } else {
49 int nCompletedSize = 0;
50 fstream outFile;
51 outFile.open(saveFile.c_str(), ios::out|ios::binary);
52
53 char pData[8192];
54 int nReceSize = 0;
55 long dwStartTime,dwEndTime;
56 while(nCompletedSize < nFileSize)
57 {
58 dwStartTime = GetTickCount();
59 nReceSize = httpSocket.Receive(pData,8192);
60 if(nReceSize == 0)
61 {
62 printf("服务器已经关闭连接.");
63 break;
64 }
65 if(nReceSize == -1)
66 {
67 printf("接收数据超时.");
68 break;
69 }
70 dwEndTime = GetTickCount();
71 outFile.write(pData, nReceSize);
72 nCompletedSize += nReceSize;
73 printf("write count is %d", outFile.gcount());
74 printf("download size is %d, all size is %d", nCompletedSize, nFileSize);
75 }
76 outFile.close();
77 }
78
79 return true;
80 }

其中 getRange(string(szValue), downFrom, downTo, fileSize) 解析http头中是否是断点续传的连接信息。
其中断点续传用C++的fstream用普通的ios::out打开会清除文件内容,所以需要用outFile.open(saveFile.c_str(), ios::out|ios::binary);
而其中如果不设置 ios::binary 这种模式的话,在下载的资源文件中如果碰到\r\n 此时进行写入的话,如果用16进制打开就会发现从0D0A变成了0D0D0A,这样导致了下载的文件与实际的文件相差甚远。
在下载过程中应该在一个临时文件里记录下载的信息,以保证下次打开可断点续传。
调用的方式为
比如下载超级兔子链接 http://dd.pctutu.com/soft/srramdisk.exe 则完整下载的话可调用
CHttpSocket::downFile("dd.pctutu.com", "/soft/srramdisk.exe", 80, "F:/srramdisk.exe");
如果想多次断点续传下载的话可以调用如下
CHttpSocket::downFile("dd.pctutu.com", "/soft/srramdisk.exe", 80, "F:/srramdisk.exe", 0, 10);
0表示最开始的字节位置,10表示结束的字节位置
CHttpSocket::downFile("dd.pctutu.com", "/soft/srramdisk.exe", 80, "F:/srramdisk.exe", 11, 0);
11表示最开始的字节位置,0表示不输入,则默认从起始位置到最后一个位置。
完整源码已上传到 http://download.csdn.net/detail/w273732573/6245965,初版代码,如果有什么不对的话请指证。
cocos2d-x 通过socket实现http下载及断点续传的实现的更多相关文章
- Android开发之多线程下载、断点续传、进度条和文本显示
代码实现了在Android环境下的多线程下载.断点续传.进度条显示和文本显示百分数: import java.io.BufferedReader; import java.io.File; impor ...
- Java开发之多线程下载和断点续传
代码实现了多线程下载和断点续传功能 import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream ...
- java多线程下载和断点续传
java多线程下载和断点续传,示例代码只实现了多线程,断点只做了介绍.但是实际测试结果不是很理想,不知道是哪里出了问题.所以贴上来请高手修正. [Java]代码 import java.io.File ...
- ios 后台下载,断点续传总结
2018年12月05日 16:09:00 weixin_34101784 阅读数:5 https://blog.csdn.net/weixin_34101784/article/details/875 ...
- Azure存储上传下载(断点续传)
最近有一个客户需要将文件系统(VM搭建)迁移到Azure存储上,对于Azure存储这里就不多做介绍,但是该客户由于网络原因下载文件的时候经常出现上传中断,所以想在Azure 存储上实现下载的断点续传. ...
- AFNetworking 下载文件断点续传操作
一:本示例代码包括: 文件下载,写入指定目录 下载进度,回调Progress; 断点续传,下载暂停,继续操作: 二:本项目 适用于 AFNetworking 1.x 版本 #pragma mark 断 ...
- python网络编程-socket上传下载文件(包括md5验证,大数据发送,粘包处理)
ftp server 1) 读取文件名 2)检查文件是否存在 3)打开文件 4)检查文件大小 5)发送文件大小给客户端 6)等客户端确认 7)开始边读边(md5计算)发数据 8)给客户端发md5 ft ...
- python实现socket上传下载文件-进度条显示
在python的socket编程中,可以实现上传下载文件,并且在下载的时候,显示进度条,具体的流程如下图所示: 1. 服务器端代码如下: [root@python 519]# cat server.p ...
- 【FTP】FTP文件上传下载-支持断点续传
Jar包:apache的commons-net包: 支持断点续传 支持进度监控(有时出不来,搞不清原因) 相关知识点 编码格式: UTF-8等; 文件类型: 包括[BINARY_FILE_TYPE(常 ...
随机推荐
- crawler_爬虫分布式设计图收集_01
- oracle_有关表分区_查询
<!--查询ORACLE分区表存在多少个分区--> SELECT * FROM USER_TAB_PARTITIONS WHERE TABLE_NAME='TBL_PAGE'; < ...
- Unix/Linux环境C编程新手教程(41) C语言库函数的文件操作具体解释
上一篇博客我们解说了怎样使用Linux提供的文件操作函数,本文主要解说使用C语言提供的文件操作的库函数. 1.函数介绍 fopen(打开文件) 相关函数 open,fclose 表头文件 #in ...
- 怎样下载并编译Android4.0内核源代码goldfish(图文)
关于怎样下载Android4.0源代码,请查看我的博客内还有一篇文章(相同是图文教程): http://blog.csdn.net/flydream0/article/details/7036156 ...
- ASP.NET MVC应用程序把文字写在图片上
原文:ASP.NET MVC应用程序把文字写在图片上 Insus.NET实现这篇<MVC把随机产生的字符串转换为图片>http://www.cnblogs.com/insus/p/3624 ...
- 如何判断微信内置浏览器(通过User Agent实现)
在进行微信公众账号开发的时候,其中很大一块是微站点的开发,我们需要知道当前的浏览器是微信内置的浏览器,那么如何判断呢? 微信内置浏览器的 User Agent 如何判断微信内置浏览器,首先需要获取微信 ...
- POJ 3928 & HDU 2492 Ping pong(树阵评价倒数)
主题链接: PKU:http://poj.org/problem?id=3928 HDU:http://acm.hdu.edu.cn/showproblem.php?pid=2492 Descript ...
- 运维自动化之SALTSTACK简单入门
运维自动化之SaltStack简单入门 饱食终日而无所事事,是颓也,废也.但看昨日,费九牛二虎之力除一BUG便流连于新番之中,不知东方之既黑,实乃颓颓然而荒废矣.故今日来缀一文以忏昨日之悔. Salt ...
- SAE设置记录:修改config.yaml实现地址重写和修改固定链接
刚搭建完sae博客后闲置下来了,偶尔写两篇文章,最近想整理整理sae,于是开始. 刚新建完博客修改固定链接,可是保存后直接访问出现问题,访问不到文章了,而且我的博客地址前面会出现"1.&qu ...
- artTemplate模板
1.介绍 新一代 javascript 模板引擎. 2.性能(引) 1.性能卓越,执行速度通常是 Mustache 与 tmpl 的 20 多倍(性能测试) 2.支持运行时调试,可精确定位异常模板所在 ...