參考:
一、套接字模式 套接字模式簡單的決定了操作套接字時,winsock函式是如何運轉的。winsock以兩種模式執行i/o操作:阻塞和非阻塞。在阻塞模式下,執行i/0的winsock呼叫(如send和recv)一直到操作完成才返回。 非阻塞模式下,winsock函式會立刻返回
1.阻塞模式 套接字建立時,預設工作在阻塞模式下,列入對recv函式的呼叫會使程式進入等待狀態,知道接收到資料才返回。 阻塞套接字的好處是使用簡單,但是當需要處理多個套接字連線時,就必須建立多個執行緒,即典型的乙個連線使用乙個執行緒的問題。 這給程式設計帶來了許多不便。所以實際開發中使用最多的函式非阻塞模式。
2.非阻塞模式 應用程式可以呼叫ioctlsocket函式顯示地讓套接字工作在非阻塞模式下 u_long ul=1; ioctlsocket(socksrv,fionbio,(u_long*)&ul); //無阻塞 一但套接字被至於非阻塞模式,處理傳送和接收資料或者管理鏈結的winsock呼叫將會立即返回。大多數情況下,呼叫失敗的錯誤**是wsaewouldblock,這意味著請求的操作在呼叫期間沒有完成。例如,如果系統輸入緩衝區中沒有待處理的資料,那麼對recv的呼叫將返回wsaewouldblock。通常,要對相同函式呼叫多次,直到它返回成功為止。 非阻塞呼叫經常以wsaewouldblock出錯**失敗,所以將套接字設定為非阻塞之後,關鍵的問題在於如何確定套接字什麼時候可讀/可寫,也就是說確定網路事件何時發生。如果需要自己不斷呼叫函式去測試的話,程式的效能勢必會受到影響,解決的辦法就是使用widows提供的不同的i/0模型。
windows套接字i/0模型
1.阻塞(blocking)模型
2.選擇(select)模型
3.wsaasyncselect模型
4.wsaeventselect模型
6.完成埠(completion port)模型
思路:初始化乙個socket
建立乙個socket列表用於管理socket
將初步連線的socket放入列表中
用select判斷列表中未處理的socket
win api版本1.
ushort nport = 4567; //
此伺服器監聽的埠號
//建立監聽套節字
socket slisten =::socket(af_inet, sock_stream, ipproto_tcp);
sockaddr_in sin;
sin.sin_family =af_inet;
sin.sin_port =htons(nport);
sin.sin_addr.s_un.s_addr =inaddr_any;
//繫結套節字到本地機器
if(::bind(slisten, (sockaddr*)&sin, sizeof(sin)) ==socket_error)
//進入監聽模式
::listen(slisten, 5);2
.
//select模型處理過程
//1)初始化乙個套節字集合fdsocket,新增監聽套節字句柄到這個集合
fd_set fdsocket; //
所有可用套節字集合
fd_zero(&fdsocket);
fd_set(slisten, &fdsocket);3.
while
(true)
else
}else
else
//(3)連線關閉、重啟或者中斷}}
}}else
}
select函式可以確定乙個或者多個套接字的狀態,如果套接字上沒有發生網路事件,便進入等待狀態,以便執行同步i/o。
int select(
int nfds, //忽略,僅是為了於berkeley套接字相容
fd_set far* readfds, //指向乙個套接字集合,用來檢查其可讀性
fd_set far* writefds, //指向乙個套接字集合,用來檢查其可寫性
fd_set far* exceptfds, //指向乙個套接字集合,用來檢查錯誤
const struct timeval far* timeout //指定此函式等待的最長時間,null為無限大
);函式呼叫成功,返回傳送網路事件的所有套接字數量的總和。如果超過了時間限制,返回0,失敗返回socket_error。
套接字集合
fd_zero(*set) 初始化set為空集合。集合在使用前應該總是清空
fd_clr(s,*set) 從set移除套接字s
fd_isset(s,*set)檢查s是不是set的成員,如果是返回trtue
fd_set(s,*set)新增套接字到集合
//還可以多個client鏈結到server上,顯示連線數量。
//tcp server select
#include #include
#pragma comment(lib, "ws2_32")
intmain()
//進入監聽模式
::listen(slisten, 5
);
//select模型處理過程
//1)初始化乙個套節字集合fdsocket,新增監聽套節字句柄到這個集合
fd_set fdsocket; //
所有可用套節字集合
fd_zero(&fdsocket);
fd_set(slisten, &fdsocket);
while
(true)
else
}else
else
//(3)連線關閉、重啟或者中斷}}
}}else
}wsacleanup();
return0;
}
//測試結果:tcp client select
#include #include
#pragma comment (lib,"ws2_32.lib")
int main(void
)
char sendbuff[100] = ;
sprintf(sendbuff,
"this zhangsan");
send(socksrv, sendbuff, strlen(sendbuff + 1), 0
); closesocket(socksrv);
wsacleanup();
getchar();
return0;
}
Select模型學習
通過呼叫select函式可以確定乙個或多個套接字的狀態,判斷套接字上是否有資料,或 者能否向乙個套接字寫入資料。select模型是最常見的i o模型。使用int select int nfds fd set far readfds fd set far writefds,fd set far exc...
select模型詳解
client客戶端 include include include include include include include include include include include define maxbuf 1024 int main 初始化伺服器端 對方 的位址和埠資訊 bzero...
Select網路模型
mysockt.h pragma once define maxnum 64 include pragma comment lib,ws2 32.lib define um user wm user 1 向視窗發訊息 enum nettype class cmysocket mysocket.cpp...