作者StubbornLin (Victor)
看板C_and_CPP
標題Re: [問題] select read & write同一fd
時間Fri Jul 31 12:52:25 2009
※ 引述《godman362 (青)》之銘言:
: 我想問一下,上述的寫法會不會有問題?
: 因為我不懂select是用什麼去判別資料是否準備好
: 還請各位先進指點一番,謝謝
給你看我很久以前寫的
/**
@brief 更新socket的狀態
@return 是否成功
**/
virtual bool Update(){
fd_set Read;
fd_set Write;
fd_set Except;
FD_ZERO(&Read);
FD_ZERO(&Write);
FD_ZERO(&Except);
FD_SET(m_Socket.getSocket(),&Read);
FD_SET(m_Socket.getSocket(),&Write);
FD_SET(m_Socket.getSocket(),&Except);
timeval TimeOut;
TimeOut.tv_sec = 0;
TimeOut.tv_usec = 0;
int Result;
Result = select(0,&Read,&Write,&Except,&TimeOut);
if(Result == SOCKET_ERROR){
setLastErrorDescription("select failed at Update");
return false;
}
// normal state
if(m_IsListening==false && m_IsConnecting==false){
if(FD_ISSET(m_Socket.getSocket(),&Read)){
int Length = 0;
Result = ioctlsocket(m_Socket.getSocket(),FIONREAD,(unsigned long
*)&Length);
// connection gracefully closed
if(Length == 0){
Close();
m_EventInterface.OnClose(true);
// connection is not be gracefully closeed
}else if(recv(m_Socket.getSocket(),0,0,0) == SOCKET_ERROR){
Close();
m_EventInterface.OnClose(false);
}else{
m_EventInterface.OnReadable(Length);
}
}
// dada can be sent
if(FD_ISSET(m_Socket.getSocket(),&Write)){
m_EventInterface.OnSendable();
}
// error occur
if(FD_ISSET(m_Socket.getSocket(),&Except)){
m_EventInterface.OnExcept();
}
// listening for connection
}else if(m_IsListening){
// there is a new connection
if(FD_ISSET(m_Socket.getSocket(),&Read)){
m_EventInterface.OnAcceptable(m_Socket);
}
// wait for connecting result
}else if(m_IsConnecting){
// successfully connected
if( FD_ISSET( (m_Socket.getSocket()) , (&Write) ) ){
sockaddr_in Address;
memset(&Address,0,sizeof(Address));
int Length = sizeof(SOCKADDR);
Result =
getsockname(m_Socket.getSocket(),(LPSOCKADDR)&Address,&Length);
if(Result == SOCKET_ERROR){
setLastErrorDescription("getsockname failed at Connect");
return false;
}
m_LocalAddress = inet_ntoa(Address.sin_addr);
m_LocalPort = ntohs(Address.sin_port);
m_EventInterface.OnConnect();
m_IsConnecting = false;
}
// connect failed
if(FD_ISSET(m_Socket.getSocket(),&Except)){
m_EventInterface.OnConnectFailed();
m_IsConnecting = false;
}
}
return true;
}
其實select用來判斷socket的事件很簡單
他的概念是這樣,在不同情況下,read、write等等事件各代表不同意思
至於代表什麼意思 這點就需要看文件怎麼寫
像listening時,read事件發生是表示有連線進來了
而像你說的連線時的write,那是表示可以寫資料了
為什麼需要有那個事件,因為socket有輸出用的buffer
你寫資料其實是先放進去,接著socket幫你打包丟出去
而當buffer滿了,他當然不讓你丟
所以連線中的write event是告訴你,outgoing buffer有位置了
可以丟資料了
大至上像這樣,更細節的部份 MSDN裡都有寫得很清楚
什麼時候的event代表什麼意思 該做什麼事
--
哇咧咧 創意投票系統
http://walele.com
易記學 程式設計教學
http://ez2learn.com/
易記學 程式設計討論區
http://forum.ez2learn.com
VICTOR's 個人Blog
http://blog.ez2learn.com/
財報分析王
http://victorlin.serveftp.org/stock/
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.170.171.45
推 godman362:看您的寫法,判斷read或write的部份,是以if..if寫成 07/31 13:51
→ godman362:而不是像我的if..else寫成,是要照您這樣的作法才會判斷 07/31 13:52
→ godman362:到write的部份嗎,因為我實際測過我的方式,是完全沒有 07/31 13:52
→ godman362:write的機會 07/31 13:53
推 godman362:您的作法,變成判斷完是否可read後再行判斷是否可write 07/31 13:55
→ godman362:這樣的作法,我不太清楚跟我用if..else差別在哪邊? 07/31 13:56
→ godman362:而且您的程式碼看過之後,似乎可以達到我想要得效果 07/31 13:57
→ godman362:而我的卻不行,是否可以指教一下是為什麼? 07/31 13:57
→ visor:效率問題 read 跟 write 是可以同時產生的 07/31 14:28
→ visor:而且你也不是只有一個 socket 在運作而已 07/31 14:29
→ StubbornLin:嗯 read write會同時發生 所以不能用else if 07/31 15:07
推 godman362:原來如此,這樣我明白了,感謝兩位的指點 07/31 16:01
推 mcauther:這 種風格 好像 python .. 08/01 09:51
→ StubbornLin:我寫程式喜歡平鋪直述 越白話越好 08/01 12:32
→ StubbornLin:不過寫這個東西時我還不認識python 08/01 12:32