我们呼叫同步资料库函式时,return 值是一个指到相对资料的暂存区,而这个资料暂存区是由系统所提供的;但是呼叫非同步资料库函式时,我们必须自己准备资料暂存区,并将此暂存区的位址当成参数,传给系统,以便系统用来储存取到的资料。读者们必须特别注意一点:在系统通知资料取得成功或失败前,千万不可将传给系统的资料暂存区删除释放,不然当系统取得资料要写入时,资料区已不见了,会导至当机的。除此之外,资料暂存区的大小一定要够大,才足够让系统用来存放取得的资料。(Winsock 规格中的建议值是MAXGETHOSTSTRUCT 1024 bytes 大小的暂存区,笔者认为太大了,100 byets 差不多就太够了)
呼叫非同步资料库函式时,得到的 return 值是一个代码,此代码代表的就是此项呼叫在系统内的编号;由於是非同步,所以我们在得到答案前,仍可呼叫WSACancelAsyncRequest() 函式来取消原先的呼叫,这个取消的动作就要利用到该代码了。另外,当我们收到结果通知时,wParam 的值也是这个代码;我们此时可以利用WSAGETASYNCERROR(lParam) 来得知资料取得是成功或失败;如果失败的原因是原先传入的暂存区太小的话,我们亦可利用 WSAASYNCGETBUFLEN(lParam) 来得知至少要多大的暂存区才够。
◎ WSAAsyncGetHostByName():利用某一 host 的名称来获取该 host 的资料。(非同步方式)
格式: HANDLE PASCAL FAR WSAAsyncGetHostByName( HWND hWnd, unsigned int wMsg, const char FAR *name, char FAR *buf, int buflen );
参数: hWnd 动作完成後,接受讯息的视窗 handle
wMsg 传回视窗的讯息
name host 名称
buf 存放 hostent 资料的暂存区
buflen buf 的大小
传回值: 成功 - 代表此非同步动作的 handle 代码
失败 - 0 (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式是利用 host 名称来获取其他的资料,如 host 的位址、别名,位址的型态、长度等。使用者呼叫此函式时必须传入要接收资料的视窗 handle、讯息代码、资料的存放位址指标等,以便得到资料时可以通知该视窗来使用资料。呼叫此函式後会马上回到使用者的呼叫点并传回一个 handle 代码,此代码可用来辨别此非同步动作或用来取消此非同步动作。当资料取得後,系统会送一个讯息到使用者指定的视窗。
◎ WSACancelAsyncRequest():取消某一未完成的非同步要求。
格式: int PASCAL FAR WSACancelAsyncRequest( HANDLE hAsyncTaskHandle );
参数:hAsyncTaskHandle 要取消的 task handle 代码
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式是用来取消原先呼叫但尚未完成的WSAAsyncGetXByY(),例如 WSAAsyncGetHostByName(),的动作。参数 hAsyncTaskHandle 即为呼叫WSAAsyncGetXByY() 时传回之代码值。若是原先呼叫之非同步要求已经完成,则无法加以取消。
(图 3)hello 程式呼叫非同步资料库函式
【结语】
笔者已经为各位介绍了大部份 Winsock 应用程式设计时会用到的函式,不知读者中是否已有人开始练习自己写 Winsock 网路程式了吗?下一期,笔者会将剩下的函式都介绍完。再此笔者并期待各位除了使用别人设计的网路软体外,大家也都能自己练习设计出一些不错的网路应用软体,让世界其他国家的人知道台湾也有能人的;愿共勉之。
简单的 Winsock 应用程式设计(4)
笔者在前几期的文章中已经介绍了大部份 Winsock 1.1 所提供的应用程式发展介面;笔者也相信有读者已经开始利用这些 API 来开发自己的网路应用程式了。但是可能仍有部