當CAsyncSocket遇到多執行緒

2021-09-20 10:28:47 字數 1979 閱讀 5129

用多執行緒方法設計socket程式時,你會發現在跨執行緒使用casyncsocket及其派生類時,會出現程式崩潰。所謂跨執行緒,是指該物件在乙個執行緒中呼叫create/attachhandle/attach函式,然後在另外乙個執行緒中呼叫其他成員函式。下面的例子就是乙個典型的導致崩潰的過程:

casyncsocket socket;

uint thread(lpvoid)

void ctestsdlg::onok()

其中socket物件在主線程中被呼叫,在子執行緒中被關閉。

這個問題的原因可以通過單步跟蹤(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);

pstate->m_pmapdeadsockets->setat((void*)hsocket, (void*)ncount);

pstate->m_hsocketwindow = pwnd->m_hwnd;

pstate->m_pmapsockethandle->setat((void*)hsocket, psocket);

當呼叫close時,我們再次跟蹤,就會發現在killsocket中,下面的函式出現錯誤:

void pascal casyncsocket::killsocket(socket hsocket, casyncsocket* psocket)

else

return null;

}

顯然,這個函式試圖從當前執行緒查詢關於這個 socket的資訊,可是這個資訊放在建立這個socket的執行緒中,因此這種查詢顯然會失敗,最終返回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...