使用方法:
SendAndGet("abc.com", 80, "/index.php", "", "");//GET
SendAndGet("abc.com", 80, "/index.php", "user=abc&pass=123qwe", "");//POST
SendAndGet("abc.com", 80, "/download.php", "", "/download/1.jpg");//GET下载
SendAndGet("abc.com", 80, "/index.php", chr(1)."/record/1,mp3", "");//上传文件并获得服务器返回, chr(1)表示等于1的char。直接用sendFile更简单
.h文件
#pragma once
#include "cocos2d.h"
#ifdef WIN32
//#include <windows.h>
//#include <WinSock.h>
#include <direct.h>
#include <io.h>
#else
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define SOCKET int
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
#include <stdarg.h>
#include <sys/stat.h>
#endif
#ifdef WIN32
#define ACCESS _access
#define MKDIR(a) _mkdir((a))
#else
#define ACCESS access
#define MKDIR(a) mkdir((a),0755)
#endif
USING_NS_CC;
class httpDownSimple : public cocos2d::CCObject {
public:
int type;
std::string url;
const char* serverName;
int nServerPort;
const char* _url;
void go(void *obj);
std::string savePath;
//By Lein,SendAndGet 实现了上传和下载,GET、POST灵活使用
static std::string SendAndGet(const char* server_name, int nServerPort, const char* url, char* data, const char* filePath);
//SendFile 调用的是SendAndGet
static std::string SendFile(const char* server_name, int nServerPort, const char* url, const char* filePath);
};
#pragma once
.ccp
#include "httpDownSimple.h"
#include <thread>
#include <stdlib.h>
#include <string.h>
int strPos(char *strin, char *seprator) {
char *right = strstr(strin, seprator);
if (right == NULL)
return -1;
return strlen(strin) - strlen(right);
}
int CreatDir(const char *pDir)
{
int i = 0;
int iRet;
int iLen;
char* pszDir;
if(NULL == pDir)
{
return 0;
}
pszDir = strdup(pDir);
iLen = strlen(pszDir);
// 创建中间目录
for (i = 0;i < iLen;i ++)
{
if (pszDir[i] == '\\' || pszDir[i] == '/')
{
pszDir[i] = '\0';
if(strlen(pszDir)<1){
pszDir[i] = '/';
continue;
}
//如果不存在,创建
iRet = ACCESS(pszDir,0);
if (iRet != 0)
{
iRet = MKDIR(pszDir);
if (iRet != 0)
{
return -1;
}
}
//支持linux,将所有\换成/
pszDir[i] = '/';
}
}
iRet = MKDIR(pszDir);
free(pszDir);
return iRet;
}
std::string getDir(std::string path) {
int position;
int pos1 = path.find_last_of('/');
int pos2 = path.find_last_of("\\");
if(pos1>pos2)
position = pos1;
else position = pos2;
if(position == -1)
return path;
std::string localPath = path.substr(0,position+1);
return localPath;
}
char * ReadFile(char *pathpic, int &pic_len){
//将图片读取出来
FILE *fp = fopen(pathpic, "rb"); //打开文件
if (!fp){
CCLog("没有找到文件位置:%s", pathpic);
return NULL;
}
fseek(fp, 0, SEEK_END); //一直寻找到文件尾部
pic_len = ftell(fp); //得到图片的长度
rewind(fp); //rewind将文件指针指向开头
char *pic_buf = new char[pic_len + 1]; //开辟一个空间在堆上
memset(pic_buf, 0, pic_len + 1); //清空文件指针
//读取文件内容
fread(pic_buf,sizeof(char),pic_len,fp);
fclose(fp);
return pic_buf;
}
std::string httpDownSimple::SendFile(const char* server_name, int nServerPort, const char* url, const char* filePath){
char data[128];
sprintf(data,"%c%s",1,filePath);
return httpDownSimple::SendAndGet(server_name, nServerPort, url, data, "");
}
/**
* 实现上传,下载,GET
* server_name 服务器ip、域名
* nServerPort 端口
* url
* data post 的数据,如果为空则采用GET,否则POST。data[0] == 1 则表示data是一个文件路径
* filePath 保存的地址 如果为空则不保存返回,否则保存
*/
std::string httpDownSimple::SendAndGet(const char* server_name, int nServerPort, const char* url, char* data, const char* filePath){
CCLog("%s !", server_name);
printf("=============httpDownSimple================");
#ifdef WIN32
WSADATA wsaData;
if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) {
WSACleanup();
return "eWSA";
}
#endif
struct sockaddr_in srv_addr;
SOCKET cli_sock=socket(PF_INET,SOCK_STREAM,0);
if (cli_sock==INVALID_SOCKET)
return "eSOC";
srv_addr.sin_family = AF_INET;
srv_addr.sin_port= ntohs(nServerPort);
// connect to server
#ifdef WIN32
LPHOSTENT lphost = gethostbyname(server_name);
if (lphost != NULL)
srv_addr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
if (connect(cli_sock,(LPSOCKADDR)&srv_addr,sizeof(srv_addr))==SOCKET_ERROR){
CCLog("%s connect failed!", server_name);
return "eCon";
}
#else
struct sockaddr_in addr;
if (inet_aton(server_name, &addr.sin_addr) != 0) {
srv_addr.sin_addr = addr.sin_addr;
} else {
struct hostent *host;
char **alias;
host = gethostbyname(server_name);
if (host == NULL) {
return "eRes";
}else{
for (alias = host->h_addr_list; *alias != NULL; alias++) {
srv_addr.sin_addr = *(struct in_addr *) (*alias);
break;
}
}
}
//srv_addr.sin_addr.s_addr = inet_addr(server_name); // 接收端IP
struct timeval rcvto, sndto;
int tolen = sizeof(struct timeval);
rcvto.tv_sec = 5;
rcvto.tv_usec = 0;
sndto.tv_sec = 5;
sndto.tv_usec = 0;
//发送时限
setsockopt(cli_sock, SOL_SOCKET, SO_SNDTIMEO, &sndto, tolen);
//接收时限
setsockopt(cli_sock, SOL_SOCKET, SO_RCVTIMEO, &rcvto, tolen);
if (connect(cli_sock, (struct sockaddr *) &srv_addr, sizeof(struct sockaddr)) != 0) {
CCLog("%s connect failed android!", server_name);
return "eCon-1";
}
#endif
int dataLen =(int) strlen(data);
int isfile = 0;
if(data[0]==1){
isfile = 1;
CCLog("Will read file [%s].", data+1);
data=ReadFile(data+1, dataLen);//dataLen 会被修改成文件大小
CCLog("The file size=[%d].", dataLen);
}
std::string header("");
//std::string content(""); //文件
//----------------------post头开始--------------------------------
header += dataLen>10?"POST ":"GET ";
header += url;
header += " HTTP/1.1\r\n";
header += "Host: ";
header += server_name;
header += "\r\n";
header += "Connection: Close\r\n";
if(dataLen>10){
CCLog("dataLen=[%d].", dataLen);
char tmp[32];
tmp[0]=0;
sprintf(tmp,"%d",dataLen);
std::string str_cl = tmp;
CCLog("str_cl=[%s].", str_cl.c_str());
//使得$_POST['key']可取得数据,否则只能用$HTTP_RAW_POST_DATA获取数据
if(!isfile)
header += "Content-Type: application/x-www-form-urlencoded\r\n";
header += "Content-Length: ";
header += str_cl;
header += "\r\n\r\n";
//header += data;
}else header += "\r\n";
CCLog("header=[%s].", header.c_str());
//----------------------post头结束-----------------------------------
//发送post头
int retval = (int) send(cli_sock, header.c_str(), header.length(), 0);
if( SOCKET_ERROR == retval )
return "";
if(dataLen>10){
CCLog("Will send %d/%ld body.", dataLen, strlen(data));
int sendCount = 0;
while(sendCount<dataLen){
retval = (int) send(cli_sock, data+sendCount, dataLen-sendCount, 0);
if( SOCKET_ERROR == retval )
return "";
sendCount+=retval;
CCLog("Sending [%d/%d].", sendCount, dataLen);
}
}
//释放内存
delete data;
int buffsize=10240;
char buffer[10240]={0};
int iPos;
int header_end=0;
char hender[] = "\r\n\r\n";
char *p;
std::string result("");
int len = 0;
FILE *fp = NULL;
if(strlen(filePath)>3){
fopen(filePath, "wb+");
if(fp==NULL){
return "eFp";
}
}
std::string tmps;
while( SOCKET_ERROR != retval ){
retval = (int)recv(cli_sock ,buffer,buffsize-1,0);
if(retval > 0) {
if(header_end<1){
iPos = strPos(buffer, hender);
if(iPos!=-1)
{
p = buffer+iPos+4;
len= retval-(iPos+4);
header_end = 1;
buffer[retval]=0;
CCLog("found head, data len=%d,iPos=%d,retval=%d",len,iPos+4,retval);
CCLog("server header=[%s]", buffer);
}else CCLog("in head len=%d",retval);
}else{
CCLog("body got len=%d",len);
len = retval;
p = buffer;
}
if(header_end>0){
if(fp!=NULL)
fwrite(p, len, 1, fp);
else
result += p;
std::chrono::milliseconds timespan(5);// or whatever
std::this_thread::sleep_for(timespan);
}
if(retval<buffsize-1) break;
}else break;
}
#ifdef WIN32
closesocket(cli_sock);
#else
close(cli_sock);
#endif
if(fp==NULL)
return result;
else{
fclose(fp);
return filePath;
}
}