Re: [問題] select read & write同一fd
看板C_and_CPP (C/C++)作者StubbornLin (Victor)時間16年前 (2009/07/31 12:52)推噓4(4推 0噓 11→)留言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
07/31 13:51, 1F
→
07/31 13:52, , 2F
07/31 13:52, 2F
→
07/31 13:52, , 3F
07/31 13:52, 3F
→
07/31 13:53, , 4F
07/31 13:53, 4F
推
07/31 13:55, , 5F
07/31 13:55, 5F
→
07/31 13:56, , 6F
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
07/31 14:28, 9F
→
07/31 14:29, , 10F
07/31 14:29, 10F
→
07/31 15:07, , 11F
07/31 15:07, 11F
推
07/31 16:01, , 12F
07/31 16:01, 12F
推
08/01 09:51, , 13F
08/01 09:51, 13F
→
08/01 12:32, , 14F
08/01 12:32, 14F
→
08/01 12:32, , 15F
08/01 12:32, 15F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 3 之 3 篇):
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章