(轉)利用libcurl和國內著名的兩個物聯網雲端通訊的例程, ubuntu和openwrt下調試成功(四)

1. libcurl 的参考文档如下

CURLOPT_HEADERFUNCTION

Pass a pointer to a function that matches the following prototype: size_t function( void *ptr, size_t size, size_t nmemb, void *userdata);. This function gets called by libcurl as soon as it has received header data. The header callback will be called once for each header and only complete header lines are passed on to the callback. Parsing headers is very easy using this. The size of the data pointed to by ptr is sizemultiplied with nmemb. Do not assume that the header line is zero terminated! The pointer named userdata is the one you set with the CURLOPT_WRITEHEADER option. The callback function must 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 CURL_WRITE_ERROR.

A complete HTTP header that is passed to this function can be up to CURL_MAX_HTTP_HEADER (100K) bytes.

If this option is not set, or if it is set to NULL, but CURLOPT_HEADERDATA (CURLOPT_WRITEHEADER) is set to anything but NULL, the function used to accept response data will be used instead. That is, it will be the function specified with CURLOPT_WRITEFUNCTION, or if it is not specified or NULL - the default, stream-writing function.

It's important to note that the callback will be invoked for the headers of all responses received after initiating a request and not just the final response. This includes all responses which occur during authentication negotiation. If you need to operate on only the headers from the final response, you will need to collect headers in the callback yourself and use HTTP status lines, for example, to delimit response boundaries.

When a server sends a chunked encoded transfer, it may contain a trailer. That trailer is identical to a HTTP header and if such a trailer is received it is passed to the application using this callback as well. There are several ways to detect it being a trailer and not an ordinary header: 1) it comes after the response-body. 2) it comes after the final header line (CR LF) 3) a Trailer: header among the regular response-headers mention what header(s) to expect in the trailer.

For non-HTTP protocols like FTP, POP3, IMAP and SMTP this function will get called with the server responses to the commands that libcurl sends.

CURLOPT_WRITEHEADER

(This option is also known as CURLOPT_HEADERDATA) Pass a pointer to be used to write the header part of the received data to. If you don't use CURLOPT_WRITEFUNCTION or CURLOPT_HEADERFUNCTIONto take care of the writing, this must be a valid FILE * as the internal default will then be a plain fwrite(). See also the CURLOPT_HEADERFUNCTION option above on how to set a custom get-all-headers callback.

2. 完整code如下

点击(此处)折叠或打开

  1. /*------------------------------------------------------------------------------------------
  2. 名称: http_cloud_curl_callbak.c
  3. 利用libcurl的API的回调机制实现云端通讯. http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
  4. CURLOPT_HEADERFUNCTION, CURLOPT_HEADERDATA: 只处理HTTP头部数据,处理与下载数据回调的处理相同.
  5.     sina的股票接口因为无HTTP头部返回因此不能应用此.
  6. -------------------------------------------------------------------------------------------*/
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <curl/curl.h>
  11. #include <assert.h>
  12. #include "../http_cloud.h"
  13. #define CURL_HEADER (1)    //0=利用 CURLOPT_WRITEFUNCTION, 1=利用 CURLOPT_HEADERFUNCTION
  14. #define DBG printf
  15. #define CURL_DBG (0)    //1=开启curl的调试
  16. //-----------------------------------------------------------------------------------------
  17. static void get_local_time(char *pc_str)
  18. {
  19.     time_t now;
  20.     struct tm *timenow;
  21.     assert(pc_str != NULL);
  22.     time(&now);
  23.     timenow = localtime(&now);
  24.     sprintf(pc_str, "%04d-%02d-%02dT%02d:%02d:%02d", timenow->tm_year+1900, timenow->tm_mon+1, timenow->tm_mday,
  25.                     timenow->tm_hour, timenow->tm_min, timenow->tm_sec);
  26. }
  27. size_t callback_get_head(void *ptr, size_t size, size_t nmemb, void *userp)
  28. {
  29.     DBG("ptr = %s, userp = %s\n", ptr, userp);
  30.     strcat(userp, ptr);
  31.     return size * nmemb; //必须返回这个大小, 否则只回调一次
  32. }
  33. static char connect_cloud(char *pc_ret, const char *host_addr, const int portno,
  34.         const char *pc_method, struct curl_slist *http_headers)
  35. {
  36.     CURL *curl;
  37.     CURLcode res = CURLE_GOT_NOTHING;
  38.   assert((pc_ret != NULL) && (host_addr != NULL) && (http_headers != NULL) && (pc_method != NULL));
  39.   //curl_global_init(CURL_GLOBAL_DEFAULT);
  40.   curl = curl_easy_init();
  41.   if (!curl)    {
  42.       fprintf(stderr, " curl init Error!\n");
  43.       return 0;
  44.   }
  45.   curl_easy_setopt(curl, CURLOPT_URL, host_addr);
  46.   curl_easy_setopt(curl, CURL_HTTP_VERSION_1_1, 1L);    //HTTP 1.1
  47.   curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);     //设置超时, 单位为秒
  48.     //curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);     //屏蔽其它信号, makes libcurl NOT ask the system to ignore SIGPIPE signals
  49. #if (CURL_DBG == 1)
  50.   curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);    //调试用: 显示交互明细,
  51.     //curl_easy_setopt(curl, CURLOPT_HEADER, 1L);    //调试用: 只显示头行的返回
  52. #endif
  53. #if 1
  54.     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, pc_method);
  55. #if (CURL_HEADER == 0)
  56.     curl_easy_setopt(curl, CURLOPT_HEADER, 1);         //下载数据包括HTTP头部, The default value for this parameter is 0.
  57.     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_get_head); //下载数据的回调函数
  58.     curl_easy_setopt(curl, CURLOPT_WRITEDATA, pc_ret);                                //下载数据的指针
  59. #else
  60.     curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, callback_get_head); //头部数据的回调函数
  61.     curl_easy_setopt(curl, CURLOPT_HEADERDATA, pc_ret);                                //头部数据的指针
  62. #endif
  63.     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_headers);    //多行的HTTP头部
  64. #endif
  65.   res = curl_easy_perform(curl);
  66.   if(res != CURLE_OK)
  67.       fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
  68.     curl_easy_cleanup(curl);
  69.   return 1;
  70. }
  71. #if (YEELINK == 1)
  72. int yeelink_create_data(const int device_id, const int sensor_id, const float device_value)
  73. {
  74.     char pc_ret[500], request[1024], pc_json[100], pc_time[30], pc_host_file[100], pc_header[100], pc_url[200], ret;
  75.     int len;
  76.     sprintf(pc_host_file, "v1.0/device/%d/sensor/%d/datapoints", device_id, sensor_id);
  77.     sprintf(pc_header, "U-ApiKey: %s", YEELINK_API_KEY);
  78.     get_local_time(pc_time);
  79.     sprintf(pc_json, "{\"timestamp\":\"%s\",\"value\":%.2f}", pc_time, device_value);
  80.     len = strlen(pc_json);
  81.     //sprintf(request, "POST /%s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\n%s\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection: Close\r\n\r\n%s\r\n",
  82.     //    pc_host_file, YEELINK_HOST, pc_header, len, pc_json);
  83.     //DBG("request = %s\n", request);
  84.     //组织请求头部, 自动末尾添加'\r\n'
  85.     struct curl_slist *http_headers = NULL;
  86.     //sprintf(request, "POST /%s HTTP/1.1", pc_host_file);
  87.     //http_headers = curl_slist_append(http_headers, request);    //此部分在url中体现
  88.     sprintf(request, "Host: %s", YEELINK_HOST);
  89.     http_headers = curl_slist_append(http_headers, request);
  90.     sprintf(request, "%s", pc_header);
  91.     http_headers = curl_slist_append(http_headers, request);
  92.     sprintf(request, "%s", "Accept: */*");
  93.     http_headers = curl_slist_append(http_headers, request);
  94.     sprintf(request, "Content-Length: %d", len);
  95.     http_headers = curl_slist_append(http_headers, request);
  96.     sprintf(request, "%s", "Content-Type: application/x-www-form-urlencoded");
  97.     http_headers = curl_slist_append(http_headers, request);
  98.     sprintf(request, "%s", "Connection: Close");
  99.     http_headers = curl_slist_append(http_headers, request);
  100.     sprintf(request, "\r\n%s", pc_json);
  101.     http_headers = curl_slist_append(http_headers, request);
  102. #if 0
  103.     struct curl_slist *tmp = http_headers;
  104.     printf("HTTP request = ");
  105.     while(tmp) {
  106.         printf("%s\n", tmp->data);
  107.         tmp = tmp->next;
  108.     }
  109. #endif
  110.     //发送请求, 再判断返回值
  111.     //url = api.yeelink.net/v1.0/device/391/sensor/497/datapoints
  112.     sprintf(pc_url, "%s/%s", YEELINK_HOST, pc_host_file);
  113.     ret = connect_cloud(pc_ret, pc_url, YEELINK_PORT, HTTP_POST, http_headers);
  114.     //释放 http_headers资源
  115.     curl_slist_free_all(http_headers);
  116.     DBG("yeelini ret = %s\n", pc_ret);
  117.     return(ret);
  118. }
  119. #endif
  120. #if (LEWEI50 == 1)
  121. //curl --request POST http://www.lewei50.com/api/V1/Gateway/UpdateSensors/01 --data "[{\"Name\":\"T1\",\"Value\":\"23.08\"}]" --header "userkey:36be8ff22f794f1e8a0bee6eef237"
  122. int lewei50_create_data(const char *device_id, const float device_value)
  123. {
  124.     char pc_ret[500], request[1024], pc_json[100], pc_header[100], pc_url[200], *pc_data, ret;
  125.     int len;
  126.     assert(device_id != NULL);
  127.     sprintf(pc_header, "userkey: %s", LEWEI50_USER_KEY);
  128.     sprintf(pc_json, "[{\"Name\":\"%s\",\"Value\":\"%.2f\"}]", device_id, device_value);
  129.     len = strlen(pc_json);
  130.     //sprintf(request, "POST /%s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\n%s\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection: Close\r\n\r\n%s\r\n",
  131.     //    LEWEI50_HOST_FILE, LEWEI50_HOST, pc_header, len, pc_json);
  132.     //DBG("request = %s\n", request);
  133.     //组织请求头部, 自动末尾添加'\r\n'
  134.     struct curl_slist *http_headers = NULL;
  135.     //sprintf(request, "POST /%s HTTP/1.1", pc_host_file);
  136.     //http_headers = curl_slist_append(http_headers, request);    //此部分在url中体现
  137.     sprintf(request, "Host: %s", LEWEI50_HOST);
  138.     http_headers = curl_slist_append(http_headers, request);
  139.     sprintf(request, "%s", pc_header);
  140.     http_headers = curl_slist_append(http_headers, request);
  141.     sprintf(request, "%s", "Accept: */*");
  142.     http_headers = curl_slist_append(http_headers, request);
  143.     sprintf(request, "Content-Length: %d", len);
  144.     http_headers = curl_slist_append(http_headers, request);
  145.     sprintf(request, "%s", "Content-Type: application/x-www-form-urlencoded");
  146.     http_headers = curl_slist_append(http_headers, request);
  147.     sprintf(request, "%s", "Connection: Close");
  148.     http_headers = curl_slist_append(http_headers, request);
  149.     sprintf(request, "\r\n%s", pc_json);
  150.     http_headers = curl_slist_append(http_headers, request);
  151.     //发送请求, 再判断返回值
  152.     //url = www.lewei50.com/api/V1/gateway/UpdateSensors/01
  153.     sprintf(pc_url, "%s/%s", LEWEI50_HOST, LEWEI50_HOST_FILE);
  154.     ret = connect_cloud(pc_ret, pc_url, LEWEI50_PORT, HTTP_POST, http_headers);
  155.     //释放 http_headers资源
  156.     curl_slist_free_all(http_headers);
  157.     //{"Successful":true,"Message":"Successful. "}, 模式不同此返回数据的位置也不同.
  158.     DBG("lewei50 ret = %s\n", pc_ret);
  159.     ret = 0;
  160.     pc_data = strstr(pc_ret, HTTP_RET_OK);
  161.     if (pc_data) {
  162.         pc_data += strlen(HTTP_RET_OK);
  163.         //只返回最后的 json数据
  164.         pc_data = strstr(pc_data, "\r\n\r\n");
  165.         if (pc_data) {
  166.             pc_data += 4;
  167.             ret = 1;
  168.             DBG("lewei50 data = %s\n", pc_data);
  169.         }
  170.     }
  171.     return(ret);
  172. }
  173. #endif
  174. //-------------------------------------------------------------------
  175. int main(void)
  176. {
  177.     float f_value = 15.02;
  178.     int i_tmp;
  179.     time_t t;
  180.   srand((unsigned)time(&t));    //初始化随机种子, 否则随机数不随机
  181.     i_tmp = rand();
  182.     i_tmp -= (i_tmp >> 4 << 4);
  183.   f_value += i_tmp;
  184. #if (YEELINK == 1)
  185.     yeelink_create_data(YEELINK_DEVICE_ID, YEELINK_SENSOR_ID, f_value);
  186. #endif
  187. #if (LEWEI50 == 1)
  188.     lewei50_create_data(LEWEI50_DEVICE_ID, f_value);
  189. #endif
  190.     return 1;
  191. }



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_cloud
  14. SRCS += http_cloud_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. 运行结果如下
[email protected]:~/1-wire/http_cloud/libcurl$ ./http_cloud
ptr = HTTP/1.1 200 OK
, userp = 
ptr = Server: nginx/1.1.19
, userp = HTTP/1.1 200 OK

ptr = Date: Mon, 25 Nov 2013 01:29:37 GMT
, userp = HTTP/1.1 200 OK
Server: nginx/1.1.19

ptr = Content-Type: text/html
, userp = HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Mon, 25 Nov 2013 01:29:37 GMT

ptr = Transfer-Encoding: chunked
, userp = HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: text/html

ptr = Connection: close
, userp = HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: text/html
Transfer-Encoding: chunked

ptr = X-Powered-By: PHP/5.3.10-1ubuntu3.6
, userp = HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close

ptr = Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
, userp = HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6

ptr = P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
, userp = HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/

ptr = 
, userp = HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

yeelini ret = HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

ptr = HTTP/1.1 200 OK
, userp = onnection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

ptr = Date: Mon, 25 Nov 2013 01:29:37 GMT
, userp = onnection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

HTTP/1.1 200 OK

ptr = Content-Type: application/json; charset=utf-8
, userp = onnection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

HTTP/1.1 200 OK
Date: Mon, 25 Nov 2013 01:29:37 GMT

ptr = Content-Length: 44
, userp = onnection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

HTTP/1.1 200 OK
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: application/json; charset=utf-8

ptr = Connection: close
, userp = onnection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

HTTP/1.1 200 OK
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 44

ptr = Cache-Control: private
, userp = onnection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

HTTP/1.1 200 OK
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 44
Connection: close

ptr = Set-Cookie: SERVERID=a4a5b2bbca16d8c8b2ba6d5b6e55f36e13853429771385342977;Path=/
, userp = onnection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

HTTP/1.1 200 OK
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 44
Connection: close
Cache-Control: private

ptr = 
, userp = onnection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

HTTP/1.1 200 OK
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 44
Connection: close
Cache-Control: private
Set-Cookie: SERVERID=a4a5b2bbca16d8c8b2ba6d5b6e55f36e13853429771385342977;Path=/

{"Successful":true,"Message":"Successful. "}lewei50 ret = onnection: close
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: CAKEPHP=kgqv6b4rnbbtn1h1ndda514936; expires=Tue, 03-Dec-2013 09:29:37 GMT; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"

HTTP/1.1 200 OK
Date: Mon, 25 Nov 2013 01:29:37 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 44
Connection: close
Cache-Control: private
Set-Cookie: SERVERID=a4a5b2bbca16d8c8b2ba6d5b6e55f36e13853429771385342977;Path=/

lewei50 data = 

[email protected]:~/1-wire/http_cloud/libcurl$ 

更多相关文章
一周排行
  • 本文主要讲讲ethtool工具的使用,ethtool是Linux中操作网卡的工具. - 查看eth0的属性: ethtool eth0 - 修改eth0网卡的最大出口速度为1000Mb/s ethtool -s et ...
  • 因客户网络除80端口外,其它端口都被关闭,所以产品中的WebSocket服务必须改为80端口,今天处理好了,记录并给大家分享下. 1.服务器綁定两个IP地址,如分别为IP1.IP2. 2.设置IIS听监听其中一个IP
  • dp[i][j] := 前i个数和为j的情况(mod p) dp[i][j] 分两种情况 1.不选取第i个数 -> dp[i][j] = dp[i-1][j]                           ...
  • CodeUnit Note   This feature is documented in the Navision Application Server Technical White Paper. Codeuni
  • 


    		    12個有趣的HTML5實例
    上一周,未来的Web有了自己的logo.无论你喜不喜欢,HTML5来了并且将成为新的标准. ...
  • 在windows下常年使用UltraEdit来查看log,现在突然切换到ubuntu下,系统自带的Text Editor相当不适应:只有自己安装了. 首先,需要下载安装包,可以去:http://www.ultraed ...
  • 主要花费时间的事情: 1:安装配套的服务器,安装操作系统,安装数据库,配置远程访问等等,一般会耗费1天时间,甚至2天时间,若手头安装盘不齐全,需要耗费更多时间. 2:远程传输安装文件.特别是开发环境等等,上传到服务器 ...
  • mvc查看路由信息的插件,可以使用vs的nuget获取,或者http://www.nuget.org/packages/routedebugger/ 安装之后会在web.config生成配置节点.value:true
  • 1.效率肯定是delegate比nsnotification高. 2. delegate方法比notification更加直接,最典型的特征是,delegate方法往往需要关注返回值, 也就是delegate方法的结 ...
  • 这题首先要注意的是两个字符串,Interleave得到一个新的字符串,原来字符串中的字符的顺序是不会改变的. 试想,如果枚举s1和s2所能组成的所有字符串,那将是很恐怖的.因为两个字串中的顺序不变,如果能将之类比Mi