简单的 Winsock 应用程式设计(3)
在前两期的文章中,笔者介绍了如何在 Winsock 环境下建立主从架构的 TCP Socket,以及如何利用 Socket 来收送资料;今天,我们接著来看一看如何利用 Winsock 所提供的函式来取得一些基本的网路资料,包括我们本身主机的名称是什麽、系统主动指定给我们的 Socket 的 IP 位址及 port number、我们的 Socket 所连接的对方是谁、如何查得某些主机的 IP 位址或名称、以及某些 well-known 服务(如 ftp、telnet 等)所用的 port number 是哪一个等等。
今天我们使用的展示程式是笔者以前所撰写的一个针对 Winsock 1.1 的 46 个函式做测试或教学用的程式,有兴趣了解 46 个函式该如何呼叫的读者,可用 anonymous ftp 方式到 「tpts1.seed.net.tw」 的 「UPLOAD/WINKING/JNLIN」目录下取得此程式的执行档及原始程式码,档名为 hello.*。读者们也可利用 hello 程式来模拟 Server 或 Client 程式,以验证我们所做的动作。
【如何知道我们所使用的 local 主机名称】
通常我们都会帮我们自己所使用的这台主机设定一个名称;在程式中,我们也可以透过 Winsock 所提供的一个称为 gethostname() 的函式来取得这一个主机名称。
◎ gethostname():获取目前使用者使用的 local host 的名称。
格式: int PASCAL FAR gethostname( char FAR *name, int namelen );
参数: name 用来存放 local host 名称的暂存区
namelen name 的大小
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来获取 local host 的名称。
在程式中我们呼叫的方法如下:
gethostname( (char FAR *) hname, sizeof(hname) )
读者们如果使用过 Trumpet Winsock 的话,可能知道 Trumpet 的环境设定中 并没有让我们设定 local host 名称的栏位,所以在执行一些 Public Domain 的 Winsock 应用程式(如 ws_ping、wintalk)时,在呼叫 gethostname() 时会产生错误;解决的方法是在 Trumpet 的 「hosts」 档中加上您的主机 IP 位址及名称,那麽呼叫这个函式时就不会再产生错误了。
【如何得知系统主动指定给我们的 IP 位址及 port number】
以前的文章中,笔者曾提到 Client 端的 TCP Socket 在呼叫 connect() 函式去连接 Server 端之前,可以呼叫 bind() 函式来指定 Client 端 Socket 所用的 IP 位址及 port number;但是一般而言,我们 Client 端并不需要呼叫 bind() 来指定特定的 IP 位址及 port number 的,而是交由系统主动帮我们的 Socket 设定 IP 位址及 port number (呼叫 connect() 函式时)。但是我们如何得知系统指定了什麽 IP 位址及 port number 给我们呢?这就要借助 getsockname() 这个函式了。
◎ getsockname():获取 Socket 的 Local 位址及 port number 资料。
格式: int PASCAL FAR getsockname( SOCKET s, struct sockaddr FAR *name, int FAR *namelen );
参数: s Socket 的识别码
name 存放此 Socket 的 Local 位址的暂存区
namelen name 的长度
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式是用来取得已设定位址或已连接之 Socket 的本端位址资料。若是此Socket 被设定为 INADDR_ANY,则需等真正建立连接成功後才会传回正确的位址。
在程式中呼叫的方法为:
struct sockaddr_in sa;
int salen = sizeof(sa);
getsockname( sd, (struct sockaddr FAR *)&sa