在網(wǎng)絡(luò)協(xié)議實(shí)現(xiàn)時(shí),在很多時(shí)候,我方在特定時(shí)刻并不清楚對(duì)方會(huì)進(jìn)行怎樣的操作,是發(fā)送數(shù)據(jù)、發(fā)起連接、關(guān)閉連接還是什么也不做。此時(shí)在程序中我們采用的第一種方法是循環(huán)檢測(cè):
while(TRUE)
{
if(recv()>0)
{
…
}
if(accept()!=SOCK_ERR)
{
…
}
}
當(dāng)然這種方法是可以的,但是必須注意的是最好采用非阻塞模式運(yùn)行recv()、accept(),因?yàn)槿绻亲枞J皆趓ecv()和accept()中會(huì)阻塞,此時(shí)如果正運(yùn)行recv()則無法立即響應(yīng)接受連接,如果正運(yùn)行accept()則無法立即接收數(shù)據(jù)。
實(shí)際上,ZLIP提供了靈活的機(jī)制方便進(jìn)行復(fù)雜的網(wǎng)絡(luò)協(xié)議編程,這些機(jī)制包括:
1. 使用select函數(shù)編程。
2. 使用類MFC回調(diào)機(jī)制。
3. 在us/os-II中使用ZLIP。
這里先介紹第一種:使用select函數(shù)編程。select()提供了同時(shí)檢測(cè)多個(gè)套接字狀態(tài)的機(jī)制,只要其中的一個(gè)套接字發(fā)生了預(yù)期的收到數(shù)據(jù)、接受連接、被關(guān)閉事件后,select()會(huì)立即返回,返回后用戶可以檢測(cè)是哪個(gè)套接字發(fā)生了事件,并做相應(yīng)的處理。實(shí)例程序test_complex_send_recv就是使用select函數(shù)編程的典型例子。使用select()編程有如下的固定模式:
while(TRUE)
{
/* 清空測(cè)試集,準(zhǔn)備開始新的檢測(cè) */
FD_ZERO(&r);
FD_ZERO(&w);
/* 將需要檢測(cè)的套接字放入讀測(cè)試或?qū)憸y(cè)試集中 */
FD_SET(sc[0], &w);
FD_SET(sc[0], &r);
FD_SET(sc[1], &w);
FD_SET(sc[1], &r);
/* 等待相應(yīng)的事件發(fā)生 */
select(0, &r, &w, NULL, NULL);
/* 是否為sc[0]可讀*/
if(FD_ISSET(sc[0], &r))
{
…
}
/* 是否為sc[0]可寫*/
if(FD_ISSET(sc[0], &w))
{
…
}
/* 是否為sc[1]可讀*/
if(FD_ISSET(sc[1], &r))
{
…
}
/* 是否為sc[1]可寫*/
if(FD_ISSET(sc[1], &w))
{
…
}
}