#include "SH_Datatrans.hpp" #include "dirent.h" #include DataTrans *pDataTrans = DataTrans::instance(); struct DowloadFile { const char *filename; FILE *stream; }; DataTrans::DataTrans() : m_bDebug(false) {} DataTrans::~DataTrans() {} static int OnDebug(CURL *, curl_infotype itype, char *pData, size_t size, void *) { if (itype == CURLINFO_TEXT) { // printf("[TEXT]%s\n", pData); } else if (itype == CURLINFO_HEADER_IN) { print_info("[HEADER_IN]%s\n", pData); } else if (itype == CURLINFO_HEADER_OUT) { print_info("[HEADER_OUT]%s\n", pData); } else if (itype == CURLINFO_DATA_IN) { print_info("[DATA_IN]%s\n", pData); } else if (itype == CURLINFO_DATA_OUT) { print_info("[DATA_OUT]%s\n", pData); } return 0; } static size_t OnWriteData(void *buffer, size_t size, size_t nmemb, void *lpVoid) { std::string *str = dynamic_cast((std::string *)lpVoid); if (NULL == str || NULL == buffer) { return -1; } char *pData = (char *)buffer; str->append(pData, size * nmemb); return nmemb; } static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) { printf("size = %d\n", size); struct DowloadFile *out = (struct DowloadFile *)stream; if (out && !out->stream) { out->stream = fopen(out->filename, "wb"); //打开文件进行写入 if (!out->stream) return -1; } return fwrite(buffer, size, nmemb, out->stream); } int DataTrans::download(char *pFilename, string &strUrl, string &strResponse, bool bDownload) { CURL *curl = NULL; CURLcode res; struct DowloadFile dlfile = {pFilename, //定义下载到本地的文件位置和路径 NULL}; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); //初始化一个curl指针 if (curl) { // curl对象存在的情况下执行的操作 //设置远端地址 curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str()); if (bDownload) { //执行写入文件流操作 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); //当有数据被写入,回调函数被调用, curl_easy_setopt(curl, CURLOPT_WRITEDATA, &dlfile); //设置结构体的指针传递给回调函数 } else { curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse); } curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 8); //连接超时,这个数值如果设置太短可能导致数据请求不到就断开了 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); //接收数据时超时设置,如果10秒内数据未接收完,直接退出 //启用时会汇报所有的信息,存放在STDERR或指定的CURLOPT_STDERR中 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_USERPWD, "SUREN:SUREN"); //写入文件 res = curl_easy_perform(curl); //释放curl对象 curl_easy_cleanup(curl); if (res != CURLE_OK) { cout << stderr << res << endl; return -1; } } printf("strResponse = %s\n", strResponse.c_str()); if (bDownload) { if (dlfile.stream) { //关闭文件流 fclose(dlfile.stream); } } else { } //释放全局curl对象 curl_global_cleanup(); return 0; } //下载文件数据接收函数 size_t writedata2file(void *ptr, size_t size, size_t nmemb, FILE *stream) { size_t written = fwrite(ptr, size, nmemb, stream); return written; } // http POST请求文件下载 int DataTrans::dl_curl_post_req(const string &url, const string &postParams, string &filename) { CURL *curl; FILE *fp; CURLcode res; /* 调用curl_global_init()初始化libcurl */ res = curl_global_init(CURL_GLOBAL_ALL); if (CURLE_OK != res) { printf("init libcurl failed."); curl_global_cleanup(); return -1; } /* 调用curl_easy_init()函数得到 easy interface型指针 */ curl = curl_easy_init(); if (curl) { fp = fopen(filename.c_str(), "wb"); /* 调用curl_easy_setopt()设置传输选项 */ res = curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); if (res != CURLE_OK) { fclose(fp); curl_easy_cleanup(curl); return -1; } /* 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务 */ res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writedata2file); if (res != CURLE_OK) { fclose(fp); curl_easy_cleanup(curl); return -1; } /* 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务 */ res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); if (res != CURLE_OK) { fclose(fp); curl_easy_cleanup(curl); return -1; } res = curl_easy_perform(curl); // 调用curl_easy_perform()函数完成传输任务 fclose(fp); /* Check for errors */ if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); return -1; } /* always cleanup */ curl_easy_cleanup(curl); // 调用curl_easy_cleanup()释放内存 } curl_global_cleanup(); return 0; } int DataTrans::Post(const std::string &strUrl, const std::string &strPost, std::string &strResponse) { CURLcode res; CURL *curl = curl_easy_init(); if (NULL == curl) { return CURLE_FAILED_INIT; } if (m_bDebug) { curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug); } curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str()); curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str()); curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3); res = curl_easy_perform(curl); curl_easy_cleanup(curl); return res; } int DataTrans::Get(const std::string &strUrl, std::string &strResponse) { CURLcode res; CURL *curl = curl_easy_init(); if (NULL == curl) { return CURLE_FAILED_INIT; } if (m_bDebug) { curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug); } curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str()); curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse); /** * 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。 * 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。 */ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3); res = curl_easy_perform(curl); curl_easy_cleanup(curl); return res; } int DataTrans::Posts(const std::string &strUrl, const std::string &strPost, std::string &strResponse, const char *pCaPath) { CURLcode res; CURL *curl = curl_easy_init(); if (NULL == curl) { return CURLE_FAILED_INIT; } if (m_bDebug) { curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug); } curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str()); curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str()); curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); if (NULL == pCaPath) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); } else { //缺省情况就是PEM,所以无需设置,另外支持DER // curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM"); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true); curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath); } curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3); res = curl_easy_perform(curl); curl_easy_cleanup(curl); return res; } int DataTrans::Gets(const std::string &strUrl, std::string &strResponse, const char *pCaPath) { CURLcode res; CURL *curl = curl_easy_init(); if (NULL == curl) { return CURLE_FAILED_INIT; } if (m_bDebug) { curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug); } curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str()); curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); if (NULL == pCaPath) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); } else { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true); curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath); } curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3); res = curl_easy_perform(curl); curl_easy_cleanup(curl); return res; } int DataTrans::upload_file(const std::string &strUrl, const std::string &filename, std::string &response) { CURL *curl; CURLM *multi_handle; int still_running; char res[60]; struct curl_httppost *formpost = NULL; struct curl_httppost *lastptr = NULL; struct curl_slist *headerlist = NULL; static const char buf[] = "Expect:"; curl_global_init(CURL_GLOBAL_ALL); /* Fill in the file upload field. This makes libcurl load data from the given file name when curl_easy_perform() is called. */ /* Fill in the filename field */ curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "filename", CURLFORM_FILE, filename.c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "upload", CURLFORM_END); curl = curl_easy_init(); multi_handle = curl_multi_init(); /* initalize custom header list (stating that Expect: 100-continue is not wanted */ headerlist = curl_slist_append(headerlist, buf); if (curl && multi_handle) { /* what URL that receives this POST */ curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_WRITEDATA, res); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); curl_multi_add_handle(multi_handle, curl); curl_multi_perform(multi_handle, &still_running); do { struct timeval timeout; int rc; fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd = -1; long curl_timeo = -1; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); /* set a suitable timeout to play around with */ timeout.tv_sec = 1; timeout.tv_usec = 0; curl_multi_timeout(multi_handle, &curl_timeo); if (curl_timeo >= 0) { timeout.tv_sec = curl_timeo / 1000; if (timeout.tv_sec > 1) timeout.tv_sec = 1; else timeout.tv_usec = (curl_timeo % 1000) * 1000; } /* get file descriptors from the transfers */ curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); /* In a real-world program you OF COURSE check the return code of the function calls. On success, the value of maxfd is guaranteed to be greater or equal than -1. We call select(maxfd + 1, ...), specially in case of (maxfd == -1), we call select(0, ...), which is basically equal to sleep. */ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); switch (rc) { case -1: break; case 0: default: /* timeout or readable/writable sockets */ print_info("perform!\n"); curl_multi_perform(multi_handle, &still_running); print_info("running: %d!\n", still_running); break; } } while (still_running); curl_multi_cleanup(multi_handle); /* always cleanup */ curl_easy_cleanup(curl); /* then cleanup the formpost chain */ curl_formfree(formpost); /* free slist */ curl_slist_free_all(headerlist); } return 0; } int DataTrans::Send_file_socket(const std::string &filename) { return 0; } int DataTrans::Send_Dir_socket(const char *dirname) { DIR *dirp; std::vector v; std::string temp; struct dirent *dp; dirp = opendir(dirname); while ((dp = readdir(dirp)) != NULL) { if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; v.push_back(std::string(dp->d_name)); } int socketfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in s_add, c_add; unsigned short portnum = 12345; int len; char buffer[BUFFER_SIZE]; FILE *fp; int file_block_length = 0; /* *创建socket */ if (socketfd < 0) { print_error("Socket create error! \n"); return -1; } else { print_info("Socket create success!\n"); } /* *设置地址 */ bzero(&s_add, sizeof(struct sockaddr_in)); s_add.sin_family = AF_INET; s_add.sin_addr.s_addr = inet_addr(GlobalConfig::ServerIP.c_str()); s_add.sin_port = htons(PORT); if (connect(socketfd, (struct sockaddr *)(&s_add), sizeof(struct sockaddr)) < 0) { print_error("Connect failure!\n"); return -1; } else { print_info("Connect Success!\n"); } std::vector::iterator iter; for (iter = v.begin(); iter != v.end(); ++iter) { temp = *iter; cout << temp.c_str() << endl; int file_name_length = (int)strlen(temp.c_str()); if (send(socketfd, (char *)&file_name_length, sizeof(int), 0) < 0) { //发送文件名长度 print_error("Send File_Name_Length Failed!\n"); } else { print_info("Send File_Name_Length Success!\n"); } //发送文件名 if (send(socketfd, temp.c_str(), file_name_length, 0) < 0) { print_error("Send File_Name Failed!\n"); } else { print_info("Send File_Name Success!\n"); } /* *发送文件 */ std::string filename = std::string(dirname + temp); fp = fopen(filename.c_str(), "r"); if (fp == NULL) { print_error("File: %s Not Found!\n", filename.c_str()); } else { bzero(buffer, BUFFER_SIZE); while ((file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0) { print_info("file_block_length = %d\n", file_block_length); /* *把数据写入buffer */ if (send(socketfd, buffer, file_block_length, 0) < 0) { print_error("Send File:%s Failed!\n", filename.c_str()); break; } bzero(buffer, sizeof(buffer)); } fclose(fp); print_info("File: %s Transfer Finished!\n", filename.c_str()); } close(socketfd); return 0; } } void DataTrans::SetDebug(bool bDebug) { m_bDebug = bDebug; }