zoukankan      html  css  js  c++  java
  • (转)利用libcurl获取新浪股票接口, ubuntu和openwrt实验成功(三)

    1.  利用 CURLOPT_WRITEFUNCTION 设置回调函数, 利用 CURLOPT_WRITEDATA 获取数据指针 

    官网文档如下

    CALLBACK OPTIONS

     

    CURLOPT_WRITEFUNCTION

    Pass a pointer to a function that matches the following prototype: size_t function( char *ptr, size_t size, size_t nmemb, void *userdata); This function gets called by libcurl as soon as there is data received that needs to be saved. The size of the data pointed to by ptr is size multiplied with nmemb, it will not be zero terminated. Return the number of bytes actually taken care of. If that amount differs from the amount passed to your function, it'll signal an error to the library. This will abort the transfer and return CURLE_WRITE_ERROR.

    From 7.18.0, the function can return CURL_WRITEFUNC_PAUSE which then will cause writing to this connection to become paused. See curl_easy_pause(3) for further details.

    This function may be called with zero bytes data if the transferred file is empty.

    Set this option to NULL to get the internal default function. The internal default function will write the data to the FILE * given with CURLOPT_WRITEDATA.

    Set the userdata argument with the CURLOPT_WRITEDATA option.

    The callback function will be passed as much data as possible in all invokes, but you cannot possibly make any assumptions. It may be one byte, it may be thousands. The maximum amount of body data that can be passed to the write callback is defined in the curl.h header file: CURL_MAX_WRITE_SIZE (the usual default is 16K). If you however have CURLOPT_HEADER set, which sends header data to the write callback, you can get up to CURL_MAX_HTTP_HEADER bytes of header data passed into it. This usually means 100K.

    CURLOPT_WRITEDATA

    Data pointer to pass to the file write function. If you use the CURLOPT_WRITEFUNCTION option, this is the pointer you'll get as input. If you don't use a callback, you must pass a 'FILE *' (cast to 'void *') as libcurl will pass this to fwrite() when writing data. By default, the value of this parameter is unspecified.

    The internal CURLOPT_WRITEFUNCTION will write the data to the FILE * given with this option, or to stdout if this option hasn't been set.

    If you're using libcurl as a win32 DLL, you MUST use the CURLOPT_WRITEFUNCTION if you set this option or you will experience crashes.

    This option is also known with the older name CURLOPT_FILE, the name CURLOPT_WRITEDATA was introduced in 7.9.7.


    2. 完整代码如下:

    点击(此处)折叠或打开

    1. /*------------------------------------------------------------------------------------------
    2. 名称: http_sina_curl_callbak.c
    3. 功能: 利用libcurl的回调机制实现sina股票接口. http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
    4. http://hq.sinajs.cn/list=sz150013
    5. http://hq.sinajs.cn/list=sh601318
    6. #libcurl的调试信息
    7. * About to connect() to hq.sinajs.cn port 80 (#0)
    8. * Trying 219.142.78.242...
    9. * connected
    10. * Connected to hq.sinajs.cn (219.142.78.242) port 80 (#0)
    11. > GET /list=sz150001 HTTP/1.1
    12. Host: hq.sinajs.cn
    13. Accept: * *
    14. < HTTP/1.1 200 OK
    15. < Cache-Control: no-cache
    16. < Content-Length: 250
    17. < Connection: Keep-Alive
    18. < Content-Type: application/x-javascript; charset=GBK
    19. <
    20. * Connection #0 to host hq.sinajs.cn left intact
    21. * Closing connection #0
    22. #运行结果:
    23. root@OpenWrt:/xutest# ./http_sina_stock
    24. sz150001: dq = 0.724, jg = 0.730, jd = 0.722, jk = 0.729
    25. sz150013: dq = 0.886, jg = 0.893, jd = 0.885, jk = 0.889
    26. sz150100: dq = 0.981, jg = 0.982, jd = 0.979, jk = 0.980
    27. sz150152: dq = 0.964, jg = 0.967, jd = 0.964, jk = 0.965
    28. sz150018: dq = 0.958, jg = 0.960, jd = 0.957, jk = 0.960
    29. root@OpenWrt:/xutest#
    30. -------------------------------------------------------------------------------------------*/
    31. #include <stdio.h>
    32. #include <stdlib.h>
    33. #include <string.h>
    34. #include <curl/curl.h>
    35. #include <assert.h>
    36. #define HTTP_GET "GET"
    37. #define HTTP_PUT "PUT"
    38. #define HTTP_HEAD "HEAD"
    39. #define HTTP_POST "POST"
    40. #define HTTP_DELETE "DELETE"
    41. #define HTTP_RET_OK "HTTP/1.1 200 OK "
    42. #define SINA_HOST "hq.sinajs.cn"
    43. #define SINA_PORT 80
    44. #define ARRAY_COUNT(x) (sizeof(x) / sizeof(x[0]))
    45. typedef struct {
    46.     float price_dq;    //当前价, 取拼音的首字母
    47.     float price_zs;    //昨收价
    48.     float price_jk;    //今开价
    49.     float price_jg;    //今高价
    50.     float price_jd;    //今低价
    51. } stock_info_t;
    52. #define DBG //printf
    53. #define CURL_DBG (0)    //1=开启curl的调试
    54. //-----------------------------------------------------------------------------------------
    55. static void delay_ms(int msec)
    56. {
    57.     struct timeval timeout;
    58.     memset(&timeout, 0, sizeof(struct timeval));
    59.     timeout.tv_sec    = msec / 1000;
    60.     timeout.tv_usec    = (msec % 1000) * 1000;
    61.     select(0, NULL, NULL, NULL, &timeout);
    62. }
    63. size_t callback_get_head(void *ptr, size_t size, size_t nmemb, void *userp)
    64. {
    65.     strcat(userp, ptr);
    66.     return size * nmemb; //必须返回这个大小, 否则只回调一次
    67. }
    68. static char connect_cloud(char *pc_ret, const char *host_addr, const int portno,
    69.     const char *pc_method, struct curl_slist *http_headers)
    70. {
    71.     CURL *curl;
    72.     CURLcode res = CURLE_GOT_NOTHING;
    73.   assert((pc_ret != NULL) && (host_addr != NULL) && (pc_method != NULL));
    74.   //curl_global_init(CURL_GLOBAL_DEFAULT);
    75.   curl = curl_easy_init();
    76.   if (!curl)    {
    77.       fprintf(stderr, "--- curl init Error! ");
    78.       return 0;
    79.   }
    80.   curl_easy_setopt(curl, CURLOPT_URL, host_addr);
    81.   curl_easy_setopt(curl, CURL_HTTP_VERSION_1_1, 1L);    //HTTP 1.1
    82.   curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);     //设置超时, 单位为秒.
    83.     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);     //屏蔽其它信号, makes libcurl NOT ask the system to ignore SIGPIPE signals
    84.     curl_easy_setopt(curl, CURLOPT_HEADER, 1L);         //下载数据包括HTTP头部, The default value for this parameter is 0.
    85.     //curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);    //The default value for this parameter is 1
    86. #if (CURL_DBG == 1)
    87.   curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);    //调试用: 显示交互明细,
    88.     //curl_easy_setopt(curl, CURLOPT_HEADER, 1L);    //调试用: 只显示头行的返回
    89. #endif
    90. #if 1
    91.     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, pc_method);
    92.     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_get_head); //下载数据的回调函数
    93.     curl_easy_setopt(curl, CURLOPT_WRITEDATA, pc_ret);                                //下载数据的指针
    94.     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_headers);    //多行的HTTP头部
    95. #endif
    96.   res = curl_easy_perform(curl);
    97.   if(res != CURLE_OK)
    98.       fprintf(stderr, "curl_easy_perform() failed: %s ", curl_easy_strerror(res));
    99.     curl_easy_cleanup(curl);
    100.   return 1;
    101. }
    102. int sina_get_stock(char *pc_ret, const char *pc_stockid)
    103. {
    104.     char pc_url[200], ret;
    105.     //组织请求头部, 自动末尾添加' '
    106.     struct curl_slist *http_headers = NULL;
    107.     http_headers = curl_slist_append(http_headers, "Accept: */*");
    108.     //http_headers = curl_slist_append(http_headers, "Connection: Close");
    109.     //发送请求, 再判断返回值
    110.     //url = hq.sinajs.cn/list=sz150013
    111.     sprintf(pc_url, "%s/list=%s", SINA_HOST, pc_stockid);
    112.     ret = connect_cloud(pc_ret, pc_url, SINA_PORT, HTTP_GET, http_headers);
    113.     //DBG("cloud ret = %s ", pc_ret);
    114.     //释放 http_headers资源
    115.     curl_slist_free_all(http_headers);
    116.     return(ret);
    117. }
    118. #if 0
    119. /*字符串不同含义的数据用逗号隔开了,按照程序员的思路,顺序号从0开始。
    120. 0:”大秦铁路”,股票名字;
    121. 1:”27.55″,今日开盘价;
    122. 2:”27.25″,昨日收盘价;
    123. 3:”26.91″,当前价格;
    124. 4:”27.55″,今日最高价;
    125. 5:”26.20″,今日最低价;
    126. 6:”26.91″,竞买价,即“买一”报价;
    127. 7:”26.92″,竞卖价,即“卖一”报价;
    128. 8:”22114263″,成交的股票数,由于股票交易以一百股为基本单位,所以在使用时,通常把该值除以一百;
    129. 9:”589824680″,成交金额,单位为“元”,为了一目了然,通常以“万元”为成交金额的单位,所以通常把该值除以一万;
    130. 10:”4695″,“买一”申请4695股,即47手;
    131. 11:”26.91″,“买一”报价;
    132. 12:”57590″,“买二”
    133. 13:”26.90″,“买二”
    134. 14:”14700″,“买三”
    135. 15:”26.89″,“买三”
    136. 16:”14300″,“买四”
    137. 17:”26.88″,“买四”
    138. 18:”15100″,“买五”
    139. 19:”26.87″,“买五”
    140. 20:”3100″,“卖一”申报3100股,即31手;
    141. 21:”26.92″,“卖一”报价
    142. (22, 23), (24, 25), (26,27), (28, 29)分别为“卖二”至“卖四的情况”
    143. 30:”2008-01-11″,日期;
    144. 31:”15:05:32″,时间;*/
    145. #endif
    146. void stock_parse(stock_info_t *stock, const char *pc_data)
    147. {
    148.     char *pc_str, *pc_str1;
    149.     int i;
    150.     assert((stock != NULL) &&(pc_data != NULL));
    151.     //DBG("data = %s ", pc_data);
    152.     pc_str = strstr(pc_data, HTTP_RET_OK);
    153.     if (pc_str) {
    154.         pc_str += strlen(HTTP_RET_OK);
    155.         pc_str = strstr(pc_str, " ");
    156.         pc_str += 4;
    157.         DBG("valid str = %s ", pc_str);
    158.         //解析数据, var hq_str_sz150013="???B,0.899,0.906,0.897,0.903,0.895,0.897,0.898,9739979,8751058.780,2200,0.897,143548,0.896,572900,0.895,625300,0.894,167300,0.893,9800,0.898,60000,0.899,362300,0.900,162500,0.901,217000,0.902,2013-11-06,10:38:44,00";
    159.         pc_str = strchr(pc_str, ',');
    160.         pc_str ++;
    161.         for (i=0; i<5; i++) {
    162.             pc_str1 = strchr(pc_str, ',');
    163.             if (pc_str1) {
    164.                 *pc_str1 = '';
    165.                 switch(i) {
    166.                     case 0: stock->price_jk = atof(pc_str); break;    //今开
    167.                     case 1: stock->price_zs = atof(pc_str); break;    //昨收
    168.                     case 2: stock->price_dq = atof(pc_str); break;    //当前
    169.                     case 3: stock->price_jg = atof(pc_str); break;    //今高
    170.                     case 4: stock->price_jd = atof(pc_str); break;    //今低
    171.                 }
    172.                 pc_str = pc_str1 + 1;    //指向下个有效数据
    173.             }
    174.             else break;
    175.         }
    176.     }
    177. }
    178. //-------------------------------------------------------------------------------
    179. int main(void)
    180. {
    181.     char pc_ret[1000];
    182.     int i, max;
    183.     stock_info_t stock;
    184.     char *stock_array[] = {"sz150001", "sz150013", "sz150100", "sz150152", "sz150018"};    //改成自己的
    185.     max = ARRAY_COUNT(stock_array);
    186.     for(i=0; i<max; i++) {
    187.         memset(pc_ret, 0x00, sizeof(pc_ret));
    188.         sina_get_stock(pc_ret, stock_array[i]);
    189.         DBG("sina ret OK = %s ", pc_ret);
    190.         stock_parse(&stock, pc_ret);
    191.         printf("%s: dq = %.3f, jg = %.3f, jd = %.3f, jk = %.3f ",
    192.                 stock_array[i], stock.price_dq, stock.price_jg, stock.price_jd ,stock.price_jk);
    193.     }
    194.     return 1;
    195. }


    3. Makefile: 

    点击(此处)折叠或打开

    1. OPENWRT = 1
    2. ifeq ($(OPENWRT), 1)
    3.     CC = ~/OpenWrt-SDK-ar71xx-for-linux-i486-gcc-4.6-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc
    4.     CFLAGS += -I ~/openwrt-lib/include -L ~/openwrt-lib/lib
    5.     LFLAGS += -lcurl -lcrypto -lz -lssl
    6. else
    7.     CC = gcc
    8.     LFLAGS += -lcurl
    9. endif
    10. CFLAGS += -Wall -O2
    11. #CFLAGS += -g
    12. #可执行文件名和相关的obj文件
    13. APP_BINARY = http_sina_stock
    14. SRCS += http_sina_curl_callback.c
    15. OBJS = $(SRCS:.c=.o)
    16. all: APP_FILE
    17. APP_FILE: $(OBJS)
    18.     $(CC) $(CFLAGS) $(OBJS) -o $(APP_BINARY) $(LFLAGS)
    19. .PHONY: clean
    20. clean:
    21.     @echo "cleanning project"
    22.     $(RM) *.a $(OBJS) *~ *.so *.lo $(APP_BINARY)
    23.     @echo "clean completed"


    4. openwrt下运行结果如下
    root@OpenWrt:/xutest# ./http_sina_stock
    sz150001: dq = 0.724, jg = 0.730, jd = 0.722, jk = 0.729
    sz150013: dq = 0.886, jg = 0.893, jd = 0.885, jk = 0.889
    sz150100: dq = 0.981, jg = 0.982, jd = 0.979, jk = 0.980
    sz150152: dq = 0.964, jg = 0.967, jd = 0.964, jk = 0.965
    sz150018: dq = 0.958, jg = 0.960, jd = 0.957, jk = 0.960

    root@OpenWrt:/xutest#

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    大多云盘都挤兑在了企业级市场
    115能做到100个亿(2016年05月31日),2013营收两亿元
    Dropbox 有哪些鲜为人知的使用技巧?
    Qt 添加外部库文件(四种方法)
    百度全新的ARM架构服务器,一个2U机箱装6台,每台4个3T硬盘,每个机箱共72TB
    EntityFramework中支持BulkInsert扩展
    基于A2DFramework的事件机制实现
    事件机制与消息机制的架构设计区别
    .net平台下socket异步通讯(代码实例)
  • 原文地址:https://www.cnblogs.com/alljoyn/p/4739992.html
Copyright © 2011-2022 走看看