casyncsocket物件不能跨執行緒之分析
用多執行緒方法設計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()
CAsyncSocket物件不能跨執行緒之分析
原文 用多執行緒方法設計socket程式時,你會發現在跨執行緒使用casyncsocket及其派生類時,會出現程式崩潰。所謂跨執行緒,是指該物件在乙個執行緒中呼叫create attachhandle attach函式,然後在另外乙個執行緒中呼叫其他成員函式。下面的例子就是乙個典型的導致崩潰的過程 ...
CAsyncSocket物件不能跨執行緒之分析
用多執行緒方法設計socket程式時,你會發現在跨執行緒使用casyncsocket及其派生類時,會出現程式崩潰。所謂跨執行緒,是指該物件在乙個執行緒中呼叫create attachhandle attach函式,然後在另外乙個執行緒中呼叫其他成員函式。下面的例子就是乙個典型的導致崩潰的過程 cas...
CAsyncSocket程式設計 MFC
許多時候我們實現網路程式設計使用的是winsock api函式,雖然這些函式使用起來也很方便,很靈活,但是vc 的mfc類庫中提供了casyncsocket這樣乙個套接字類,用它來實現socket程式設計會更方便。server端的程式設計與client端的類似,下面主要介紹他的listen及acce...