看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《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