在客户端连接服务器之前,没有调用bind()函数绑定套接字。在成功调用connect()函数后,该套接字被标识为绑定。这说明connect()函数可以实现对套接字的隐式绑定。
客户端在连接服务器之前需要知道它的地址和端口。该地址和端口对客户端来说应该是已知的。该程序中客户端与服务器运行在同一个主机。服务器的端口是5555,它的地址可以通过调用gethostname()和gethostbyname()函数获得。
gethostname()函数用来获得主机的名字,该函数的第一个参数在函数返回时,返回指向字符缓冲区的指针,在该缓冲区内保存了该主机的名字。
以gethostname()函数的返回的主机名字为参数调用gethostbyname()函数,获得一个指向hostent结构的指针。在该结构中保存有主机的地址。
hostent结构用于表示主机的名称和网络地址。由Windows Sockets分配该结构的内存空间。因此,用于应用程序决不能修改该结构或者释放该结构中成员的内存。在客户端程序中使用该结构,获取客户端的网络地址。
hostent结构定义如下。
struct hostent {
char FAR * h_name;
char FAR * FAR * h_aliases;
short h_addrtype;
short h_length;
char FAR * FAR * h_addr_list;
};
q h_name:主机正式名称。
q h_aliases:主机别名。
q h_addrtype:地址类型。
q h_length:地址长度(用字节表示)。
q h_addr_list:主机地址列表。
获得该结构有两种方法。第一种方法。使用gethostname()函数的返回值作为参数调用gethostbyname()函数,示例程序清单如下。
LPHOSTENT hostEntry;
char hostname[NAME_MAX_SIZE];
gethostname(hostname,NAME_MAX_SIZE);
hostEntry = gethostbyname(hostname);
第二种方法。使用inet_add()函数的返回值作为参数调用gethostbyaddr()函数,示例程序清单如下。
LPHOSTENT host
unsigned long addr = inet_addr("172.20.30.55");
host = gethostbyaddr((char*)&addr,sizeof(addr),2);
当连接服务器成功时,修改bConning值为TRUE。当连接失败时,调用ShowErrorMsg()函数显示调用失败的原因,然后调用ExitClient()函数,退出客户端。
客户端连接服务器的程序清单如下。
//获取主机的信息
LPHOSTENT hostEntry;
char hostname[MAX_NUM_BUF];
gethostname(hostname,MAX_NUM_BUF); //获取主机名称
hostEntry = gethostbyname(hostname); //获取主机信息
if(!hostEntry)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
//设置sockaddr_in
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
addrServ.sin_port = htons(SERVERPORT);
//连接服务器
retVal=connect(sHost,(LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
if(SOCKET_ERROR == retVal)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}else{
bConning = TRUE; //连接服务器成功
}