青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 37, comments - 55, trackbacks - 0, articles - 0
  C++博客 ::  :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

在應(yīng)用中,Client端 使用了 MFC 的  CAsyncSocket 跟 Server 通信
 
          Client                                    Server
CAsyncSocket::Send()           -->           |
CAsyncSocket::OnReceive()    <--           |
 
Client 使用 Send() 向 Server 端發(fā)送報(bào)文,Sever 端返回報(bào)文時(shí),會(huì)觸發(fā) OnReceive() 事件,告訴我們有數(shù)據(jù)到達(dá)了
 
接收 Server 數(shù)據(jù)包的實(shí)現(xiàn)代碼如下:

class CClientSocket : public CAsyncSocket
{
private:
    CBytesBuff m_buff;   
// CBytesBuff  封裝了緩沖區(qū)的操作
}
;
 
#define RECV_BUFFER_SIZE 1024
 
void CClientSocket::OnReceive(int nErrorCode)     
{
    
char szBuff[RECV_BUFFER_SIZE] = {0};    // 接收數(shù)據(jù)的緩沖區(qū)
    
    
int nRead = 0;                                      // 真正接收數(shù)據(jù)的大小
    nRead = Receive(szBuff, sizeof(szBuff) );  // 接收數(shù)據(jù)
   
    
switch (nRead)
    
{
    
case 0// 接收數(shù)據(jù)的長(zhǎng)度返回0, 表示 Socket 已經(jīng)斷開(kāi)
        {
            Close();
            Notify_UI_SOCKET_CLOSE( ::WSAGetLastError() );
        }
;
        
break;
 
    
case SOCKET_ERROR: // 出錯(cuò)
       {
            
int nErrCode = ::WSAGetLastError();
 
            
if ( nErrCode  != WSAEWOULDBLOCK) 
           
{
               Close();
               Notify_UI_SOCKET_CLOSE( nErrCode );
           }

      }

      
break;
 
    
default// 正常情況
        {
            m_buff.append(szBuff, nRead);
 
            
while( m_buff.getDataSize() <= 0 )
            
{
                
// handleData() 返回已經(jīng)處理的數(shù)據(jù)長(zhǎng)度, 然后從 m_buff 中移刪已經(jīng)處理的數(shù)據(jù)
                
// 直至 m_buff 中沒(méi)有數(shù)據(jù)
                
// handleData() 函數(shù)只有處理完 
                int nHandledLen = handleData(m_buff.getData(), m_buff.getSize());
                m_buff.popData(nHandledLen);
            }

        }


    }
// switch

    CAsyncSocket::OnReceive(nErrorCode);
}
   


我總以為上段的代碼可以正常地運(yùn)行,但事與愿違
 
當(dāng) Client端在處理 Server端 數(shù)據(jù)時(shí),有時(shí)在 handleData() 里調(diào)用了一個(gè) MessageBox() 時(shí),就會(huì)連續(xù)彈出兩個(gè) MessageBox
經(jīng)過(guò)檢查,
 
在 handleData() 中處理某一個(gè)報(bào)文時(shí)調(diào)用 MessageBox() 時(shí),如果 MessageBox() 不返回,那么 handleData() 自然也不會(huì)返回
這里后面的 m_buff.popData(nHandledLen); 語(yǔ)句也無(wú)法執(zhí)行到, 那么數(shù)據(jù)永遠(yuǎn)在 m_buff 里無(wú)法移刪除,
如果這時(shí) Server端 又再返回一個(gè) 數(shù)據(jù)包 ,
CAsyncSocket 又會(huì)觸發(fā) OnReceive(),{請(qǐng)記住,這時(shí)上一個(gè) 數(shù)據(jù)包 還在 m_buff 里}
所以 當(dāng)執(zhí)行到   int nHandledLen = handleData(m_buff.getData(), m_buff.getSize()); 時(shí)
又會(huì)彈出一個(gè) MessageBox();
 
導(dǎo)致的異常有
1、調(diào)用 MessageBox() 的那段處理 數(shù)據(jù)包的 代碼會(huì)被執(zhí)行兩次
2、m_buff.popData(nHandledLen); 這句代碼同樣會(huì)執(zhí)行兩次導(dǎo)致數(shù)據(jù)解析出錯(cuò)
 

在我的應(yīng)用中,只允許處理完一個(gè) 數(shù)據(jù)包后才能處理下一個(gè) 數(shù)據(jù)包

火星人都知道,當(dāng)有數(shù)據(jù)到達(dá)時(shí),CAsynSocket 是采用消息的方式來(lái)通知的

BOOL CAsyncSocket::AsyncSelect(long lEvent)
{
 ASSERT(m_hSocket 
!= INVALID_SOCKET);

 _AFX_SOCK_THREAD_STATE
* pState = _afxSockThreadState;
 ASSERT(pState
->m_hSocketWindow != NULL);

 
return WSAAsyncSelect(m_hSocket, pState->m_hSocketWindow,
  WM_SOCKET_NOTIFY, lEvent) 
!= SOCKET_ERROR;
}


從 CAsyncSocket 的實(shí)現(xiàn)來(lái)看,每一條線程 CAsyncSocket 都會(huì)創(chuàng)建一個(gè){隱形窗口},當(dāng)有網(wǎng)絡(luò)事件時(shí),
會(huì)向這個(gè)窗口發(fā)送  WM_SOCKET_NOTIFY 消息

BEGIN_MESSAGE_MAP(CSocketWnd, CWnd)
    
//{{AFX_MSG_MAP(CWnd)
    ON_MESSAGE(WM_SOCKET_NOTIFY, OnSocketNotify)
    ON_MESSAGE(WM_SOCKET_DEAD, OnSocketDead)
    
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

 

LRESULT CSocketWnd::OnSocketNotify(WPARAM wParam, LPARAM lParam)
{
    CSocket::AuxQueueAdd(WM_SOCKET_NOTIFY, wParam, lParam);
    CSocket::ProcessAuxQueue();
    
return 0L;
}

請(qǐng)注意:上面的 CSocket 并非是 class CSocket : public CAsyncSocket, 而是另一個(gè)在MFC框架內(nèi)部的一個(gè)封裝.

結(jié)論是: CAsyncSocket::OnConnect(), CAsyncSocket::OnRecive()...... 這些函數(shù)是在  WM_SOCKET_NOTIFY 的消息響應(yīng)
函數(shù)里調(diào)用的

Google到的東西
AfxMessageBox()、MessageBox() 并不會(huì)阻塞消息隊(duì)列

具體為什么 AfxMessageBox()、MessageBox() 不會(huì)阻塞到消息隊(duì)列,需要再詳細(xì)查找相關(guān)資料
-- AfxMessageBox()、MessageBox() 會(huì)造成代碼的阻塞(因?yàn)槿绻?nbsp; MessageBox() 不返回,是不會(huì)執(zhí)行到 MessageBox() 之后的代碼)
    但它們并不會(huì)造成線程消息隊(duì)列的阻塞
   
    Google 到一些資料說(shuō)的是,AfxMessageBox() 和 MessageBox() 會(huì)把主窗體Enable 并且 會(huì)有另一個(gè)消息循環(huán),
    雖然原來(lái)窗體的消息循環(huán)的 DispatchMessage() 沒(méi)有返回,但由于 AfxMessageBox() 和 MessageBox() 又有另一個(gè)消息循環(huán)
    所以,新的消息又會(huì)被響應(yīng)到

    作了一個(gè)簡(jiǎn)單的試驗(yàn), 寫(xiě)一個(gè) Client 和 一個(gè) Server
    Client 在收到  Server 端的數(shù)據(jù)時(shí)就顯示一個(gè) MessageBox(),Server 向 Client 端發(fā)送兩次數(shù)據(jù)
    Client 端在第二次收到數(shù)據(jù)時(shí),設(shè)置斷點(diǎn),查看堆棧
   

CTestMFCSocketClientDlg::show() line 178
CClientSocket::OnReceive(
int 0) line 61
CAsyncSocket::DoCallBack(unsigned 
int 3876long 1) line 530
CSocket::ProcessAuxQueue() line 
823
CSocketWnd::OnSocketNotify(unsigned 
int 3876long 1) line 1127
CWnd::OnWndMsg(unsigned 
int 883, unsigned int 3876long 1long * 0x0012e56c) line 1826 + 17 bytes
CWnd::WindowProc(unsigned 
int 883, unsigned int 3876long 1) line 1596 + 30 bytes
AfxCallWndProc(CWnd 
* 0x00374d20 {CSocketWnd hWnd=0x00110c92}, HWND__ * 0x00110c92, unsigned int 883, unsigned int 3876long 1) line 215 + 26 bytes
AfxWndProc(HWND__ 
* 0x00110c92, unsigned int 883, unsigned int 3876long 1) line 379
AfxWndProcBase(HWND__ 
* 0x00110c92, unsigned int 883, unsigned int 3876long 1) line 220 + 21 bytes
USER32
! 77d48734()
USER32
! 77d48816()
USER32
! 77d489cd()
USER32
! 77d48a10()
USER32
! 77d5e2b9()
USER32
! 77d561c6()
USER32
! 77d6a92e()
USER32
! 77d6a294()
USER32
! 77d95fbb()
USER32
! 77d96060()
USER32
! 77d80577()
USER32
! 77d8052f()
CWinApp::DoMessageBox(
const char * 0x004153e4 `string', unsigned int 48, unsigned int 0) line 113 + 25 bytes
AfxMessageBox(const char * 0x004153e4 `string', unsigned int 0, unsigned int 0) line 131 + 26 bytes
CTestMFCSocketClientDlg::show() line 179
CClientSocket::OnReceive(
int 0) line 61
CAsyncSocket::DoCallBack(unsigned 
int 3876long 1) line 530
CSocket::ProcessAuxQueue() line 
823
CSocketWnd::OnSocketNotify(unsigned 
int 3876long 1) line 1127
CWnd::OnWndMsg(unsigned 
int 883, unsigned int 3876long 1long * 0x0012f074) line 1826 + 17 bytes
CWnd::WindowProc(unsigned 
int 883, unsigned int 3876long 1) line 1596 + 30 bytes
AfxCallWndProc(CWnd 
* 0x00374d20 {CSocketWnd hWnd=0x00110c92}, HWND__ * 0x00110c92, unsigned int 883, unsigned int 3876long 1) line 215 + 26 bytes
AfxWndProc(HWND__ 
* 0x00110c92, unsigned int 883, unsigned int 3876long 1) line 379
AfxWndProcBase(HWND__ 
* 0x00110c92, unsigned int 883, unsigned int 3876long 1) line 220 + 21 bytes
USER32
! 77d48734()
USER32
! 77d48816()
USER32
! 77d489cd()
USER32
! 77d48a10()
USER32
! 77d5e2b9()
USER32
! 77d561c6()
USER32
! 77d6a92e()
USER32
! 77d6a294()
USER32
! 77d95fbb()
USER32
! 77d96060()
USER32
! 77d80577()
USER32
! 77d8052f()
CWinApp::DoMessageBox(
const char * 0x004153e4 `string', unsigned int 48, unsigned int 0) line 113 + 25 bytes
AfxMessageBox(const char * 0x004153e4 `string', unsigned int 0, unsigned int 0) line 131 + 26 bytes
CTestMFCSocketClientDlg::show() line 179
CClientSocket::OnReceive(
int 0) line 61
CAsyncSocket::DoCallBack(unsigned 
int 3876long 1) line 530
CSocket::ProcessAuxQueue() line 
823
CSocketWnd::OnSocketNotify(unsigned 
int 3876long 1) line 1127
CWnd::OnWndMsg(unsigned 
int 883, unsigned int 3876long 1long * 0x0012fb7c) line 1826 + 17 bytes
CWnd::WindowProc(unsigned 
int 883, unsigned int 3876long 1) line 1596 + 30 bytes
AfxCallWndProc(CWnd 
* 0x00374d20 {CSocketWnd hWnd=0x00110c92}, HWND__ * 0x00110c92, unsigned int 883, unsigned int 3876long 1) line 215 + 26 bytes
AfxWndProc(HWND__ 
* 0x00110c92, unsigned int 883, unsigned int 3876long 1) line 379
AfxWndProcBase(HWND__ 
* 0x00110c92, unsigned int 883, unsigned int 3876long 1) line 220 + 21 bytes
USER32
! 77d48734()
USER32
! 77d48816()
USER32
! 77d489cd()
USER32
! 77d496c7()
CWinThread::PumpMessage() line 
853
CWnd::RunModalLoop(unsigned 
long 4) line 3489 + 19 bytes
CDialog::DoModal() line 
539 + 12 bytes
CTestMFCSocketClientApp::InitInstance() line 
65 + 8 bytes
AfxWinMain(HINSTANCE__ 
* 0x00400000, HINSTANCE__ * 0x00000000char * 0x00141f3dint 1) line 39 + 11 bytes
WinMain(HINSTANCE__ 
* 0x00400000, HINSTANCE__ * 0x00000000char * 0x00141f3dint 1) line 30
WinMainCRTStartup() line 
330 + 54 bytes
KERNEL32
! 7c816fd7()

從堆棧的情況來(lái)看,AfxMessageBox() 里面確實(shí)存在另一個(gè)消息循環(huán)在處理消息。
但還未從 Microsoft 的MSDN上找到相關(guān)的官方資料來(lái)證實(shí)這一點(diǎn)。
未解決

所以一切清楚了,原因是即使 AfxMessageBox() 不返回,也不會(huì)影響到 OnRecive() 的調(diào)用

目前想到的解決方法有兩個(gè),大概思路如下
第一種:想辦法在{第二個(gè)消息循環(huán)}中過(guò)濾掉 CAsynSocket 的 WM_SOCKET_NOTIFY 消息,并將這些過(guò)濾掉的消息存放在一個(gè)隊(duì)列,等{第二個(gè)消息循環(huán)}結(jié)束后,再把剛剛保存在隊(duì)列里的消息放回消息隊(duì)列里,讓第一個(gè)消息循環(huán)去處理

第二種:在 CAsynSocket 的 OnRecive() 里開(kāi)線程,然后通過(guò)線程鎖來(lái)保證,在未處理完{Server端發(fā)送過(guò)來(lái)的報(bào)文}時(shí),如果Server端有新的報(bào)文過(guò)來(lái),會(huì)阻塞在線程里

Feedback

# re: CAsyncSocket 的 OnReceive()[未登錄](méi)  回復(fù)  更多評(píng)論   

2008-09-10 19:53 by 漂舟
用UI消息提示錯(cuò)誤正確,但不要用彈出式窗口。

# re: CAsyncSocket 的 OnReceive()  回復(fù)  更多評(píng)論   

2008-09-10 22:13 by 沒(méi)畫(huà)完的畫(huà)
@漂舟

用UI消息提示錯(cuò)誤正確,但不要用彈出式窗口。

樓上,你說(shuō)的“用UI消息提示錯(cuò)誤正確”是什么意思?

# re: CAsyncSocket 的 OnReceive()[未登錄](méi)  回復(fù)  更多評(píng)論   

2008-09-10 22:44 by 漂舟
事務(wù)失敗的消息,用戶有可能需要知道,
所以必須在UI上有所提示、或顯示,或暫時(shí)放入隊(duì)列,用戶查看時(shí),可顯示,
即這個(gè)思路我認(rèn)為是相當(dāng)正確的,
在UI上作提示,這個(gè)過(guò)程最好是異步操作,
除非是確定能迅速完成,才用同步。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            狠狠色丁香婷婷综合久久片| 亚洲一区欧美| 久久久噜噜噜久噜久久| 国内伊人久久久久久网站视频| 久久久久一区二区三区| 亚洲尤物在线| 亚洲在线观看视频| 久久精品视频网| 国产婷婷色综合av蜜臀av | 日韩网站在线| 亚洲国产一区二区视频| 欧美wwwwww| 久久精品国产99精品国产亚洲性色| 国产麻豆精品theporn| 久久国产黑丝| 国产最新精品精品你懂的| 欧美寡妇偷汉性猛交| 最新亚洲一区| 一区二区三区欧美| 国产一区二区在线免费观看 | 国产精品第一区| 伊大人香蕉综合8在线视| 久久嫩草精品久久久精品| 老司机免费视频久久| 亚洲精品影视| 亚洲尤物影院| 亚洲欧洲在线播放| 亚洲一区二区久久| 亚洲电影免费观看高清完整版| 亚洲人成在线免费观看| 国产精品视频内| 欧美激情小视频| 国产精品极品美女粉嫩高清在线| 老巨人导航500精品| 欧美天堂在线观看| 免费日韩av片| 国产精一区二区三区| 亚洲国产精品一区| 国产夜色精品一区二区av| 亚洲乱码精品一二三四区日韩在线| 国产情侣一区| 一本色道久久综合亚洲精品婷婷| 国产一区二区三区av电影| 亚洲毛片av在线| 亚洲欧洲精品成人久久奇米网| 亚洲欧美另类久久久精品2019| 夜夜嗨av一区二区三区网页| 久久久久国产精品麻豆ai换脸| 亚洲综合三区| 欧美日韩视频免费播放| 欧美激情性爽国产精品17p| 国产在线观看一区| 亚洲欧美在线视频观看| 在线一区观看| 欧美另类变人与禽xxxxx| 免费欧美高清视频| 激情亚洲网站| 久久精品国内一区二区三区| 欧美一区二区免费| 国产精品免费网站| 中文在线资源观看视频网站免费不卡| 日韩写真在线| 欧美激情一区二区三区在线| 欧美顶级艳妇交换群宴| 亚洲国产成人精品久久| 久久久久国产一区二区三区四区| 久久久国产成人精品| 国产欧美一区二区三区在线老狼 | 亚洲一区二区三区乱码aⅴ| 欧美理论电影网| 国产午夜亚洲精品理论片色戒| 亚洲视频一区二区| 亚洲欧美综合精品久久成人 | 久久久久久久高潮| 宅男噜噜噜66国产日韩在线观看| 亚洲视频一区| 欧美视频中文一区二区三区在线观看| 亚洲成色777777女色窝| 亚洲午夜女主播在线直播| 亚洲婷婷综合久久一本伊一区| 欧美人牲a欧美精品| 亚洲美女黄色| 亚洲欧美日韩成人高清在线一区| 亚洲影音先锋| 免费日韩精品中文字幕视频在线| 欧美亚洲视频在线看网址| 久久成人精品视频| 精品99视频| 麻豆av福利av久久av| 亚洲国产精品久久久久婷婷老年| 亚洲美女色禁图| 国产精品www.| 欧美夜福利tv在线| 欧美激情一区| 亚洲欧美激情在线视频| 黄色成人91| 欧美日韩亚洲一区二区三区在线观看| 在线中文字幕不卡| 久久尤物视频| 中文网丁香综合网| 韩国一区电影| 欧美区一区二区三区| 欧美一区二区视频网站| 亚洲黄色视屏| 久久久国产精品亚洲一区| 亚洲视频在线观看免费| 亚洲字幕一区二区| 蜜桃av久久久亚洲精品| 欧美专区亚洲专区| 一色屋精品视频在线观看网站| 久久久精品一区二区三区| 欧美一区二区三区在线看| 樱桃成人精品视频在线播放| 欧美va天堂| 欧美激情第3页| 亚洲网在线观看| 午夜精品在线看| 黄色日韩精品| 亚洲高清中文字幕| 欧美片第一页| 久久免费午夜影院| 欧美国产日韩一区二区| 亚洲大胆人体视频| 亚洲欧洲综合另类| 欧美一区二区三区视频在线观看| 亚洲一区二区三区乱码aⅴ| 欧美激情在线免费观看| 欧美99在线视频观看| 亚洲午夜成aⅴ人片| 欧美国产三区| 欧美一区二区视频免费观看| 毛片一区二区| 亚洲国产午夜| 久久综合伊人77777麻豆| 亚洲一区久久久| 亚洲伦伦在线| 亚洲黄页一区| 在线观看国产欧美| 国产精品香蕉在线观看| 欧美体内she精视频在线观看| 美女国产精品| 久久综合九色综合欧美狠狠| 久久精品91久久香蕉加勒比| 小辣椒精品导航| 午夜精品久久久久久99热软件| 亚洲视频欧洲视频| 国产亚洲成人一区| 欧美日韩国产丝袜另类| 亚洲视频1区2区| 一区二区三区四区国产精品| 日韩视频精品| 夜夜嗨av一区二区三区四季av| 日韩一级裸体免费视频| 亚洲人精品午夜在线观看| 欧美肥婆在线| 亚洲国产精品国自产拍av秋霞 | 欧美成人国产| 欧美黄网免费在线观看| 欧美人与性禽动交情品| 欧美日韩在线视频首页| 欧美激情亚洲国产| 亚洲黄网站黄| 一道本一区二区| 亚洲欧美中文字幕| 久久精品国产亚洲aⅴ| 玖玖国产精品视频| 欧美精品一卡| 国产精品乱人伦一区二区| 国产日韩免费| 亚洲欧洲偷拍精品| 亚洲欧美视频在线观看| 91久久精品视频| 加勒比av一区二区| 欧美黄在线观看| 乱中年女人伦av一区二区| 米奇777在线欧美播放| 欧美精品久久一区| 国产精品高潮呻吟久久| 国内自拍一区| 99国产欧美久久久精品| 性欧美8khd高清极品| 欧美黄色一区| 亚洲一区二区三区精品在线| 久久一区二区三区四区| 欧美三区美女| 亚洲国产精品黑人久久久| 亚洲午夜女主播在线直播| 久久av资源网站| 亚洲韩日在线| 午夜精品视频在线| 欧美国产在线电影| 国产一区二区三区在线观看视频| 亚洲精品网址在线观看| 久久av一区二区三区漫画| 韩国精品主播一区二区在线观看| 一区二区三区高清在线| 欧美99久久| 日韩视频不卡中文| 日韩视频在线一区二区三区| 欧美一区二区三区在|