用多執行緒方法設計socket程式時,你會發現在跨執行緒使用casyncsocket及其派生類時,會出現程式崩潰。所謂跨執行緒,是指該物件在乙個執行緒中呼叫create/attachhandle/attach函式,然後在另外乙個執行緒中呼叫其他成員函式。下面的例子就是乙個典型的導致崩潰的過程:
casyncsocket socket;其中socket物件在主線程中被呼叫,在子執行緒中被關閉。uint thread(lpvoid)
void ctestsdlg::onok()
這個問題的原因可以通過單步跟蹤(f11)的方法來了解。我們在socket.create(0)處設斷點,跟蹤進去會發現下面的函式被呼叫:
void pascal casyncsocket::attachhandle(socket hsocket, casyncsocket* psocket, bool bdead)
assert(pwnd->m_hwnd != null);
assert(cwnd::fromhandlepermanent(pwnd->m_hwnd) == pwnd);
pstate->m_hsocketwindow = pwnd->m_hwnd;
}pstate->m_pmapsockethandle->setat((void*)hsocket, psocket);
}else
afxenablememorytracking(benable);
}
#define _afxsockthreadstate afxgetmodulethreadstate()我們沒有必要去細究這個指標的定義是如何的,只要知道它是和當前執行緒密切關聯的,其他執行緒應該也有類似的指標,只是指向不同的結構。
在這個函式中,casyncsocket建立了乙個視窗,並把如下兩個資訊加入到pstate所管理的結構中:
pstate->m_pmapsockethandle->setat((void*)hsocket, psocket);當呼叫close時,我們再次跟蹤,就會發現在killsocket中,下面的函式出現錯誤:pstate->m_pmapdeadsockets->setat((void*)hsocket, (void*)ncount);
pstate->m_hsocketwindow = pwnd->m_hwnd;
pstate->m_pmapsockethandle->setat((void*)hsocket, psocket);
void pascal casyncsocket::killsocket(socket hsocket, casyncsocket* psocket)顯然,這個函式試圖從當前執行緒查詢關於這個 socket的資訊,可是這個資訊放在建立這個socket的執行緒中,因此這種查詢顯然會失敗,最終返回null。else
return null;
}
有人會問,既然它是assert出錯,是不是release就沒問題了。這只是自欺欺人。assert/verify都是檢驗一些程式正常執行必須正確的條件。如果assert都失敗,在release中也許不會顯現,但是你的程式肯定執行不正確,啥時候出錯就不知道了。
有些特殊情況下,可能需要在不同執行緒之間傳遞socket。當然我不建議在使用casyncsocket的時候這麼做,因為這增加了出錯的風險(尤其當出現拆解包問題時,有人稱為粘包,我基本不認同這種稱呼)。如果一定要這麼做,方法應該是:
當前擁有這個socket的執行緒呼叫detach方法,這樣socket控制代碼和c++物件及當前執行緒脫離關係
當前執行緒把這個物件傳遞給另外乙個執行緒
另外乙個執行緒建立新的casyncsocket物件,並呼叫attach
上面的例子,我稍微做修改,就不會出錯了:
casyncsocket socket;uint thread(lpvoid sock)
void ctestsdlg::onok()
當流氓遇到劫匪
當流氓遇到劫匪 文 寧宇 周五看到六家網際網路公司聯合發表的宣告,抵制流量劫持等違法行為,有人認為這矛頭直指運營商。我對這個領域並不太懂,但也看這其中有很多誤解,還是有必要解釋一下的。首先,從純技術的角度看 流量劫持 客戶原本想訪問a 但是中間有人用技術手段,使實際開啟的是b 這些利用技術手段調整使...
當回車遇到換行
大家在寫文件或者寫 時都經常會用到換行操作,實際上我們都是使用鍵盤上的回車鍵進行換行。那麼,今天的問題來了,在按下回車鍵時系統做了哪些處理?回車鍵盤只是換行嗎?回車和換行是同一回事嗎?但實際並非完全如此。我們再來看看什麼是回車鍵,在打字機上有乙個叫字車的部件,在打字的時候它會根據所打的字元向前移動,...
CAsyncSocket程式設計 MFC
許多時候我們實現網路程式設計使用的是winsock api函式,雖然這些函式使用起來也很方便,很靈活,但是vc 的mfc類庫中提供了casyncsocket這樣乙個套接字類,用它來實現socket程式設計會更方便。server端的程式設計與client端的類似,下面主要介紹他的listen及acce...