工作一个星期了,基本都在看别人代码。现在主要看的是Http部分的,不断和服务器交互,不断得到反馈信息或者提交信息。诸如此类,因此为了加深C对Http的处理,还是稍微练习下或者说了解和实验下,俗话说“好记性不如烂笔头”,厉害的人都是靠学习来的。
在Windows下利用C语言进行http请求,向google天气API发送请求获取数据并保存!以下是工程文件:
各个文件代码:
- //> downdata.h
- #ifndef DOWNDATA_H_INCLUDED
- #define DOWNDATA_H_INCLUDED
- #define BUFFSIZE_H 1024
- #ifdef __cpluscplus
- extern "C"
- {
- #endif
- /**
- * @brief 向网络请求资源,返回值存储到当前目录的临时文件whether.txt中.
- * @param pUrl[in] - 请求的URL.
- * @return if get data return true, else if get nothing return false.
- */
- bool WEBQuest(const char * pUrl);
- #ifdef __cpluscplus
- }
- #endif
- #endif // DOWNDATA_H_INCLUDED
- //> downdata.cpp
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- //#include "windows.h"
- #include "winsock2.h"
- #include "downdata.h"
- #include "freeptr.h"
- #pragma comment(lib, "ws2_32.lib") //在某些编译器下,需要添加编译参数到工程设置中,比如CodeBlocks(这样,这行就不需要了).
- //Code::blocks 中新建一个工程, 然后右击工程
- //选择 build options -> Linker setting
- //在Other linker options 中添加: -lwsock32
- /**
- * @brief 为了加深http的理解和数据相关的操作,实现之.
- */
- bool WEBQuest(const char * pUrl)
- {
- #if 1 //no this declaration, socket create failed.
- WSADATA WsaData;
- if (WSAStartup(MAKEWORD(2,2),&WsaData))
- {
- printf("The socket failed");
- return false;
- }
- #endif
- SOCKET sockeId;
- SOCKADDR_IN addr;
- if (-1 == (sockeId = socket(AF_INET, SOCK_STREAM, 0)))
- {
- printf("socket create failed\n");
- return false;
- }
- /// < dest_addr
- addr.sin_addr.S_un.S_addr = inet_addr("74.125.71.105"); /// < googleIP,可以用IP地址查询得到
- addr.sin_family = AF_INET;
- addr.sin_port = htons(80);
- /// < 分离url中的主机地址和相对路径 考虑到内存和性能,下面不是好习惯!
- char *phost = 0;
- char * myurl = (char * ) malloc (BUFFSIZE_H * sizeof(char));
- char * host = (char * ) malloc (BUFFSIZE_H * sizeof(char));
- char * GET = (char * ) malloc (BUFFSIZE_H * sizeof(char));
- char * head =(char * ) malloc(BUFFSIZE_H * sizeof(char));
- memset(myurl, '\0', BUFFSIZE_H);
- memset(host, '\0', BUFFSIZE_H);
- memset(GET, '\0', BUFFSIZE_H);
- memset(head, '\0', BUFFSIZE_H);
- /// < pUrl - www.google.com/ig/api?hl=zh_cn&weather=beijing
- /// < www.google.com - &host
- /// < /ig/api?hl=zh_cn&weather=beijing - &GET
- strcpy(myurl, pUrl);
- for (phost = myurl; *phost != '/' && *phost != '\0'; ++phost);
- if ( (int)(phost - myurl) == strlen(myurl) )
- strcpy(GET, "/");
- else
- strcpy(GET, phost);
- *phost = '\0'; /// < 相当于在www.google.com/的/位置替换为'\0'.
- strcpy(host, myurl); /// < 在www.google.com/的/位置为'\0',因此www.google.com被拷贝到&host.
- printf("%s\n%s\n", host, GET);
- /**
- * 组织发送到web服务器的信息
- * 为何要发送下面的信息connect请参考HTTP协议的约定
- */
- strcat(head, "GET ");
- strcat(head, GET);
- strcat(head, " HTTP/1.1\r\n");
- strcat(head, "host: ");
- strcat(head, host);
- strcat(head, "\r\nConnection: Close\r\n\r\n");
- printf(head);
- if (SOCKET_ERROR == connect(sockeId, (SOCKADDR * )&addr, sizeof(addr)))
- {
- printf("connect failed!\n");
- closesocket(sockeId);
- WSACleanup();
- #if 0
- free(myurl);
- free(host);
- free(GET);
- free(head);
- myurl = NULL;
- host = NULL;
- GET = NULL;
- head = NULL;
- #endif
- freeCharPtr(&myurl, &host, &GET, &head, NULL);
- return false;
- }
- if (SOCKET_ERROR == send(sockeId, head, strlen(head), 0))
- {
- printf("send &header error!\n");
- closesocket(sockeId);
- WSACleanup();
- #if 0
- free(myurl);
- free(host);
- free(GET);
- free(head);
- myurl = NULL;
- host = NULL;
- GET = NULL;
- head = NULL;
- #endif
- freeCharPtr(&myurl, &host, &GET, &head, NULL);
- return false;
- }
- memset(head, '\0', BUFFSIZE_H);
- FILE *fp;
- fp = fopen("whether.xml", "w+");
- if (NULL == fp)
- {
- printf("whether file create failed!\n");
- closesocket(sockeId);
- WSACleanup();
- #if 0
- free(myurl);
- free(host);
- free(GET);
- free(head);
- myurl = NULL;
- host = NULL;
- GET = NULL;
- head = NULL;
- #endif
- freeCharPtr(&myurl, &host, &GET, &head, NULL);
- return false;
- }
- while (recv(sockeId, head, BUFFSIZE_H, 0) > 0)
- {
- fputs(head, fp);
- memset(head, '\0', BUFFSIZE_H);
- }
- #if 0
- free(myurl);
- free(host);
- free(GET);
- free(head);
- myurl = NULL;
- host = NULL;
- GET = NULL;
- head = NULL;
- #endif
- freeCharPtr(&myurl, &host, &GET, &head, NULL);
- closesocket(sockeId);
- WSACleanup();
- return true;
- }
- /// < main.cpp
- #include <iostream> /// < system()
- #include <stdio.h>
- #include "downdata.h"
- using namespace std;
- int main(void )
- {
- if (!WEBQuest("" ))
- {
- return -1;
- }
- printf( "Whether have been writtend to file whether.xml\n" );
- system( "pause");
- return 0;
- }
- //> 关于内存释放,自己封装了一个变参形式的(char **参数)释放函数
- //> freeptr.h
- #ifndef FREEPTR_H
- #define FREEPTR_H
- #ifdef __cpluscplus
- extern "C"
- {
- #endif
- /**
- * @brief 变参形式内存释放
- * param[in] ch - 字符指针
- * param[in] ... - 其他字符指针
- * 接口使用规范:
- *
- */
- void freeCharPtr(char ** ch, ...);
- #ifdef __cpluscplus
- }
- #endif
- #endif
- //> freeptr.cpp
- #include <stdlib.h>
- #include <stdarg.h>
- #include "freeptr.h"
- /**
- * @brief 变参形式内存释放
- */
- void freeCharPtr(char ** ch, ...)
- {
- va_list ap;
- char ** p;
-
- va_start(ap, ch);
- free(*ch);
- *ch = NULL;
- while (p = va_arg(ap, char ** ))
- {
- free(*p);
- *p = NULL;
- }
- }
阅读(13273) | 评论(0) | 转发(0) |