Re: [問題] select read & write同一fd

看板C_and_CPP (C/C++)作者 (Victor)時間16年前 (2009/07/31 12:52), 編輯推噓4(4011)
留言15則, 4人參與, 最新討論串3/3 (看更多)
※ 引述《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

07/31 13:51, , 1F
看您的寫法,判斷read或write的部份,是以if..if寫成
07/31 13:51, 1F

07/31 13:52, , 2F
而不是像我的if..else寫成,是要照您這樣的作法才會判斷
07/31 13:52, 2F

07/31 13:52, , 3F
到write的部份嗎,因為我實際測過我的方式,是完全沒有
07/31 13:52, 3F

07/31 13:53, , 4F
write的機會
07/31 13:53, 4F

07/31 13:55, , 5F
您的作法,變成判斷完是否可read後再行判斷是否可write
07/31 13:55, 5F

07/31 13:56, , 6F
這樣的作法,我不太清楚跟我用if..else差別在哪邊?
07/31 13:56, 6F

07/31 13:57, , 7F
而且您的程式碼看過之後,似乎可以達到我想要得效果
07/31 13:57, 7F

07/31 13:57, , 8F
而我的卻不行,是否可以指教一下是為什麼?
07/31 13:57, 8F

07/31 14:28, , 9F
效率問題 read 跟 write 是可以同時產生的
07/31 14:28, 9F

07/31 14:29, , 10F
而且你也不是只有一個 socket 在運作而已
07/31 14:29, 10F

07/31 15:07, , 11F
嗯 read write會同時發生 所以不能用else if
07/31 15:07, 11F

07/31 16:01, , 12F
原來如此,這樣我明白了,感謝兩位的指點
07/31 16:01, 12F

08/01 09:51, , 13F
這 種風格 好像 python ..
08/01 09:51, 13F

08/01 12:32, , 14F
我寫程式喜歡平鋪直述 越白話越好
08/01 12:32, 14F

08/01 12:32, , 15F
不過寫這個東西時我還不認識python
08/01 12:32, 15F
文章代碼(AID): #1ASdYB8t (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1ASdYB8t (C_and_CPP)