windows与linux平台使用的socket均继承自Berkeley socket(rfc3493),他们都支持select I/O模型,均支持使用getaddrinfo与getnameinfo实现协议无关编程。但存在细微差别,主要有:
另外,如果绑定本机回环地址,windows下sendto函数可以通过,linux下sendto回报错:errno=22, Invalid arguement。一般情况下均绑定通配地址。
移植实例:
把linux下面的一个http client库libghttp移植到了windows系统下。
实例源码下载:
http://download.csdn.net/detail/earbao/7857789
上面的链接失效了。
重新上传到百度云:http://pan.baidu.com/s/1pJFSByz
#define strcasecmp strcmp
1、修改和添加http_trans.h头部
#ifndef HTTP_TRANS_H #define HTTP_TRANS_H #define PLATFORM_WINDOWS 1 #define PLATFORM_MAC 2 #define PLATFORM_UNIX 3 #if defined(_WIN32) #define PLATFORM PLATFORM_WINDOWS #elif defined(__APPLE__) #define PLATFORM PLATFORM_MAC #else #define PLATFORM PLATFORM_UNIX #endif// 接下来我们来把头文件给加进来。 #if PLATFORM == PLATFORM_WINDOWS #include <winsock2.h> #pragma comment( lib, "wsock32.lib" ) #define socklen_t unsigned int #elif PLATFORM == PLATFORM_MAC || PLATFORM == PLATFORM_UNIX #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #endif2、http_trans.c
/* * http_trans.c -- Functions for doing transport related stuff including * automatically extending buffers and whatnot. * Created: Christopher Blizzard <[email protected]>, 5-Aug-1998 * * Copyright (C) 1998 Free Software Foundation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #if defined(_WIN32) #else #include <sys/time.h> #endif #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include "http_trans.h" #include "http_global.h" static int http_trans_buf_free(http_trans_conn *a_conn); int http_trans_connect(http_trans_conn *a_conn) { #if PLATFORM == PLATFORM_WINDOWS WSADATA WsaData; WSAStartup( MAKEWORD(2,2), &WsaData); #endif if ((a_conn == NULL) || (a_conn->host == NULL)) goto ec; if (a_conn->hostinfo == NULL) { /* look up the name of the proxy if it's there. */ if (a_conn->proxy_host) { if ((a_conn->hostinfo = gethostbyname(a_conn->proxy_host)) == NULL) { a_conn->error_type = http_trans_err_type_host; a_conn->error = h_errno; goto ec; } } else { /* look up the name */ if ((a_conn->hostinfo = gethostbyname(a_conn->host)) == NULL) { a_conn->error_type = http_trans_err_type_host; a_conn->error = h_errno; goto ec; } } /* set up the saddr */ a_conn->saddr.sin_family = AF_INET; /* set the proxy port */ if (a_conn->proxy_host) a_conn->saddr.sin_port = htons(a_conn->proxy_port); else a_conn->saddr.sin_port = htons(a_conn->port); /* copy the name info */ memcpy(&a_conn->saddr.sin_addr.s_addr, a_conn->hostinfo->h_addr_list[0], sizeof(unsigned long)); } #ifdef _WIN32 if ((a_conn->sock = socket(AF_INET, SOCK_STREAM, 0))==INVALID_SOCKET) { a_conn->error_type = http_trans_err_type_errno; a_conn->error = errno; goto ec; } #else /* set up the socket */ if ((a_conn->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { a_conn->error_type = http_trans_err_type_errno; a_conn->error = errno; goto ec; } #endif /* set up the socket */ if (connect(a_conn->sock, (struct sockaddr *)&a_conn->saddr, sizeof(struct sockaddr)) < 0) { a_conn->error_type = http_trans_err_type_errno; a_conn->error = errno; goto ec; } return 0; ec: return -1; } http_trans_conn * http_trans_conn_new(void) { http_trans_conn *l_return = NULL; /* allocate a new connection struct */ l_return = (http_trans_conn *)malloc(sizeof(http_trans_conn)); memset(l_return, 0, sizeof(http_trans_conn)); /* default to 80 */ l_return->port = 80; /* default to 1000 bytes at a time */ l_return->io_buf_chunksize = 1024; /* allocate a new trans buffer */ l_return->io_buf = malloc(l_return->io_buf_chunksize); memset(l_return->io_buf, 0, l_return->io_buf_chunksize); l_return->io_buf_len = l_return->io_buf_chunksize; /* make sure the socket looks like it's closed */ l_return->sock = -1; return l_return; } void http_trans_conn_destroy(http_trans_conn *a_conn) { /* destroy the connection structure. */ if (a_conn == NULL) return; if (a_conn->io_buf) free(a_conn->io_buf); if (a_conn->sock != -1) close(a_conn->sock); free(a_conn); #if PLATFORM == PLATFORM_WINDOWS closesocket(a_conn->sock); WSACleanup(); #endif return; } const char * http_trans_get_host_error(int a_herror) { switch (a_herror) { case HOST_NOT_FOUND: return "Host not found"; case NO_ADDRESS: return "An address is not associated with that host"; case NO_RECOVERY: return "An unrecoverable name server error occured"; case TRY_AGAIN: return "A temporary error occurred on an authoritative name server. Please try again later."; default: return "No error or error not known."; } } int http_trans_append_data_to_buf(http_trans_conn *a_conn, char *a_data, int a_data_len) { if (http_trans_buf_free(a_conn) < a_data_len) { a_conn->io_buf = realloc(a_conn->io_buf, a_conn->io_buf_len + a_data_len); a_conn->io_buf_len += a_data_len; } memcpy(&a_conn->io_buf[a_conn->io_buf_alloc], a_data, a_data_len); a_conn->io_buf_alloc += a_data_len; return 1; } int http_trans_read_into_buf(http_trans_conn *a_conn) { int l_read = 0; int l_bytes_to_read = 0; /* set the length if this is the first time */ if (a_conn->io_buf_io_left == 0) { a_conn->io_buf_io_left = a_conn->io_buf_chunksize; a_conn->io_buf_io_done = 0; } /* make sure there's enough space */ if (http_trans_buf_free(a_conn) < a_conn->io_buf_io_left) { a_conn->io_buf = realloc(a_conn->io_buf, a_conn->io_buf_len + a_conn->io_buf_io_left); a_conn->io_buf_len += a_conn->io_buf_io_left; } /* check to see how much we should try to read */ if (a_conn->io_buf_io_left > a_conn->io_buf_chunksize) l_bytes_to_read = a_conn->io_buf_chunksize; else l_bytes_to_read = a_conn->io_buf_io_left; #ifdef _WIN32 /* read in some data */ if ((a_conn->last_read = l_read = recv(a_conn->sock, &a_conn->io_buf[a_conn->io_buf_alloc], l_bytes_to_read,0)) < 0) { if (errno == EINTR) l_read = 0; else return HTTP_TRANS_ERR; } #else /* read in some data */ if ((a_conn->last_read = l_read = read(a_conn->sock, &a_conn->io_buf[a_conn->io_buf_alloc], l_bytes_to_read)) < 0) { if (errno == EINTR) l_read = 0; else return HTTP_TRANS_ERR; } #endif else if (l_read == 0) return HTTP_TRANS_DONE; /* mark the buffer */ a_conn->io_buf_io_left -= l_read; a_conn->io_buf_io_done += l_read; a_conn->io_buf_alloc += l_read; /* generate the result */ if (a_conn->io_buf_io_left == 0) return HTTP_TRANS_DONE; return HTTP_TRANS_NOT_DONE; } int http_trans_write_buf(http_trans_conn *a_conn) { int l_written = 0; if (a_conn->io_buf_io_left == 0) { a_conn->io_buf_io_left = a_conn->io_buf_alloc; a_conn->io_buf_io_done = 0; } #ifdef _WIN32 /* write out some data */ if ((a_conn->last_read = l_written = send (a_conn->sock, &a_conn->io_buf[a_conn->io_buf_io_done], a_conn->io_buf_io_left,0)) <= 0) { if (errno == EINTR) l_written = 0; else return HTTP_TRANS_ERR; } #else /* write out some data */ if ((a_conn->last_read = l_written = write (a_conn->sock, &a_conn->io_buf[a_conn->io_buf_io_done], a_conn->io_buf_io_left)) <= 0) { if (errno == EINTR) l_written = 0; else return HTTP_TRANS_ERR; } #endif if (l_written == 0) return HTTP_TRANS_DONE; /* advance the counters */ a_conn->io_buf_io_left -= l_written; a_conn->io_buf_io_done += l_written; if (a_conn->io_buf_io_left == 0) return HTTP_TRANS_DONE; return HTTP_TRANS_NOT_DONE; } void http_trans_buf_reset(http_trans_conn *a_conn) { if (a_conn->io_buf) free(a_conn->io_buf); a_conn->io_buf = malloc(a_conn->io_buf_chunksize); memset(a_conn->io_buf, 0, a_conn->io_buf_chunksize); a_conn->io_buf_len = a_conn->io_buf_chunksize; a_conn->io_buf_alloc = 0; a_conn->io_buf_io_done = 0; a_conn->io_buf_io_left = 0; } void http_trans_buf_clip(http_trans_conn *a_conn, char *a_clip_to) { int l_bytes = 0; /* get the number of bytes to clip off of the front */ l_bytes = a_clip_to - a_conn->io_buf; if (l_bytes > 0) { memmove(a_conn->io_buf, a_clip_to, a_conn->io_buf_alloc - l_bytes); a_conn->io_buf_alloc -= l_bytes; } a_conn->io_buf_io_done = 0; a_conn->io_buf_io_left = 0; } char * http_trans_buf_has_patt(char *a_buf, int a_len, char *a_pat, int a_patlen) { int i = 0; for ( ; i <= ( a_len - a_patlen ); i++ ) { if (a_buf[i] == a_pat[0]) { if (memcmp(&a_buf[i], a_pat, a_patlen) == 0) return &a_buf[i]; } } return NULL; } /* static functions */ static int http_trans_buf_free(http_trans_conn *a_conn) { return (a_conn->io_buf_len - a_conn->io_buf_alloc); }
#include "ghttp/ghttp.h" #include <stdio.h> #include <stdlib.h> //异步请求实例 void test001() { char *uri = "http://www.hao123.com"; ghttp_request *request = NULL; ghttp_status status; char *buf; int bytes_read; request = ghttp_request_new(); if(ghttp_set_uri(request, uri) == -1) exit(-1); if(ghttp_set_type(request, ghttp_type_get) == -1) exit(-1); /* NOTE: Set async request */ ghttp_set_sync(request, ghttp_async); ghttp_prepare(request); while(1) { status = ghttp_process(request); if(status == ghttp_error) break; /* NOTE: buf may NULL, notice it */ buf = ghttp_get_body(request); bytes_read = ghttp_get_body_len(request); printf("%d\n %s\n",bytes_read,buf); if(status == ghttp_done) { /* NOTE: Ok, done */ break; } } ghttp_clean(request); ghttp_request_destroy(request); system("pause"); } //同步请求实例 int test002() { char *uri = "http://www.hao123.com"; ghttp_request *request = NULL; ghttp_status status; char *buf; int bytes_read; request = ghttp_request_new(); if(ghttp_set_uri(request, uri) == -1) return (-1); if(ghttp_set_type(request, ghttp_type_get) == -1) return(-1); ghttp_prepare(request); status = ghttp_process(request); if(status == ghttp_error) return(-1); /* OK, done */ printf("Status code -> %d\n", ghttp_status_code(request)); buf = ghttp_get_body(request); printf("%s\n",buf); bytes_read = ghttp_get_body_len(request); ghttp_clean(request); ghttp_request_destroy(request); system("pause"); return 0; } int main(int argc, char *argv[]) { //test002(); test001(); return 0; }