二.makeSocket函数
int makeSocket(string host,int port)
{
WSADATA inet_WsaData;//1
WSAStartup(MAKEWORD(2, 0), &inet_WsaData);//1
if (LOBYTE(inet_WsaData.wVersion) != 2 || HIBYTE(inet_WsaData.wVersion) != 0)//1
{
WSACleanup();
return -1;
}
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);//1
struct hostent * hp = ::gethostbyname(host.c_str());//2
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
memcpy(&saddr.sin_addr, hp->h_addr, 4);//3
if (connect(tcp_socket, (const struct sockaddr *)&saddr, sizeof(saddr)) == -1)//1
{
cerr << "error in connect" << endl;
}
return tcp_socket;
}
1 见http://www.cnblogs.com/magicsoar/p/3585129.html windows下的C++ socket服务器(3)中讲解
2 struct hostent * hp = ::gethostbyname(host.c_str());
gethostbyname()返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针
hostent结构体的定义如下
struct hostent {
char FAR * h_name; /* official name of host */
char FAR * FAR * h_aliases; /* alias list */
short h_addrtype; /* host address type */
short h_length; /* length of address */
char FAR * FAR * h_addr_list; /* list of addresses */
#define h_addr h_addr_list[0] /* address, for backward compat */
};
hostent->h_name 表示的是主机的规范名。例如www.baidu.com的规范名其实是www.a.shifen.com。(关于www.a.shifen.com还有一段故事http://www.zhihu.com/question/20100901)
hostent->h_aliases 表示的是主机的别名.www.google.com就是google他自己的别名。有的时候,有的主机可能有好几个别名,这些,其实都是为了易于用户记忆而为自己的网站多取的名字。
hostent->h_addrtype 表示的是主机ip地址的类型,到底是ipv4(AF_INET),还是pv6(AF_INET6)
hostent->h_length 表示的是主机ip地址的长度
hostent->h_addr_list 表示的是主机的ip地址
#define h_addr h_addr_list[0]
3 memcpy(&saddr.sin_addr, hp->h_addr, 4);
由于 hp->h_addr是char*类型,不能直接赋值给saddr.sin_addr
所以我们使用了memcpy函数
函数原型如下
void *memcpy(void *dest, const void *src, size_t n);
从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。