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

沒畫完的畫

喂馬 劈柴 BBQ~
posts - 37, comments - 55, trackbacks - 0, articles - 0
  C++博客 ::  :: 新隨筆 :: 聯系 :: 聚合  :: 管理

CAsyncSocket 的 OnReceive() 第一集

Posted on 2008-09-10 08:48 沒畫完的畫 閱讀(5093) 評論(3)  編輯 收藏 引用 所屬分類: VC

在應用中,Client端 使用了 MFC 的  CAsyncSocket 跟 Server 通信
 
          Client                                    Server
CAsyncSocket::Send()           -->           |
CAsyncSocket::OnReceive()    <--           |
 
Client 使用 Send() 向 Server 端發送報文,Sever 端返回報文時,會觸發 OnReceive() 事件,告訴我們有數據到達了
 
接收 Server 數據包的實現代碼如下:

class CClientSocket : public CAsyncSocket
{
private:
    CBytesBuff m_buff;   
// CBytesBuff  封裝了緩沖區的操作
}
;
 
#define RECV_BUFFER_SIZE 1024
 
void CClientSocket::OnReceive(int nErrorCode)     
{
    
char szBuff[RECV_BUFFER_SIZE] = {0};    // 接收數據的緩沖區
    
    
int nRead = 0;                                      // 真正接收數據的大小
    nRead = Receive(szBuff, sizeof(szBuff) );  // 接收數據
   
    
switch (nRead)
    
{
    
case 0// 接收數據的長度返回0, 表示 Socket 已經斷開
        {
            Close();
            Notify_UI_SOCKET_CLOSE( ::WSAGetLastError() );
        }
;
        
break;
 
    
case SOCKET_ERROR: // 出錯
       {
            
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() 返回已經處理的數據長度, 然后從 m_buff 中移刪已經處理的數據
                
// 直至 m_buff 中沒有數據
                
// handleData() 函數只有處理完 
                int nHandledLen = handleData(m_buff.getData(), m_buff.getSize());
                m_buff.popData(nHandledLen);
            }

        }


    }
// switch

    CAsyncSocket::OnReceive(nErrorCode);
}
   


我總以為上段的代碼可以正常地運行,但事與愿違
 
當 Client端在處理 Server端 數據時,有時在 handleData() 里調用了一個 MessageBox() 時,就會連續彈出兩個 MessageBox
經過檢查,
 
在 handleData() 中處理某一個報文時調用 MessageBox() 時,如果 MessageBox() 不返回,那么 handleData() 自然也不會返回
這里后面的 m_buff.popData(nHandledLen); 語句也無法執行到, 那么數據永遠在 m_buff 里無法移刪除,
如果這時 Server端 又再返回一個 數據包 ,
CAsyncSocket 又會觸發 OnReceive(),{請記住,這時上一個 數據包 還在 m_buff 里}
所以 當執行到   int nHandledLen = handleData(m_buff.getData(), m_buff.getSize()); 時
又會彈出一個 MessageBox();
 
導致的異常有
1、調用 MessageBox() 的那段處理 數據包的 代碼會被執行兩次
2、m_buff.popData(nHandledLen); 這句代碼同樣會執行兩次導致數據解析出錯
 

在我的應用中,只允許處理完一個 數據包后才能處理下一個 數據包

火星人都知道,當有數據到達時,CAsynSocket 是采用消息的方式來通知的

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 的實現來看,每一條線程 CAsyncSocket 都會創建一個{隱形窗口},當有網絡事件時,
會向這個窗口發送  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;
}

請注意:上面的 CSocket 并非是 class CSocket : public CAsyncSocket, 而是另一個在MFC框架內部的一個封裝.

結論是: CAsyncSocket::OnConnect(), CAsyncSocket::OnRecive()...... 這些函數是在  WM_SOCKET_NOTIFY 的消息響應
函數里調用的

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

具體為什么 AfxMessageBox()、MessageBox() 不會阻塞到消息隊列,需要再詳細查找相關資料
-- AfxMessageBox()、MessageBox() 會造成代碼的阻塞(因為如果  MessageBox() 不返回,是不會執行到 MessageBox() 之后的代碼)
    但它們并不會造成線程消息隊列的阻塞
   
    Google 到一些資料說的是,AfxMessageBox() 和 MessageBox() 會把主窗體Enable 并且 會有另一個消息循環,
    雖然原來窗體的消息循環的 DispatchMessage() 沒有返回,但由于 AfxMessageBox() 和 MessageBox() 又有另一個消息循環
    所以,新的消息又會被響應到

    作了一個簡單的試驗, 寫一個 Client 和 一個 Server
    Client 在收到  Server 端的數據時就顯示一個 MessageBox(),Server 向 Client 端發送兩次數據
    Client 端在第二次收到數據時,設置斷點,查看堆棧
   

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()

從堆棧的情況來看,AfxMessageBox() 里面確實存在另一個消息循環在處理消息。
但還未從 Microsoft 的MSDN上找到相關的官方資料來證實這一點。
未解決

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

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

第二種:在 CAsynSocket 的 OnRecive() 里開線程,然后通過線程鎖來保證,在未處理完{Server端發送過來的報文}時,如果Server端有新的報文過來,會阻塞在線程里

Feedback

# re: CAsyncSocket 的 OnReceive()[未登錄]  回復  更多評論   

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

# re: CAsyncSocket 的 OnReceive()  回復  更多評論   

2008-09-10 22:13 by 沒畫完的畫
@漂舟

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

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

# re: CAsyncSocket 的 OnReceive()[未登錄]  回復  更多評論   

2008-09-10 22:44 by 漂舟
事務失敗的消息,用戶有可能需要知道,
所以必須在UI上有所提示、或顯示,或暫時放入隊列,用戶查看時,可顯示,
即這個思路我認為是相當正確的,
在UI上作提示,這個過程最好是異步操作,
除非是確定能迅速完成,才用同步。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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| 久久久久久999| 另类av导航| 在线观看成人小视频| 在线免费观看欧美| 在线观看不卡av| 99在线精品观看| 一本色道久久综合狠狠躁篇怎么玩 | 国产网站欧美日韩免费精品在线观看| 国产精品自拍三区| 国产日韩欧美在线看| 国内欧美视频一区二区| av不卡在线| 亚洲久久视频| 久久久久久自在自线| 欧美三级免费| 亚洲一级高清| 亚洲午夜高清视频| 亚洲国产精品视频一区| 欧美国产精品v| 欧美在线亚洲在线| 国产亚洲欧美一区在线观看| 日韩一二三在线视频播| 欧美高清视频一区二区| 国产酒店精品激情| 亚洲在线视频| 欧美激情国产精品| 国产精品国产精品| 欧美一区二区三区视频免费| 久久综合成人精品亚洲另类欧美| 99精品视频一区| 欧美视频免费看| 亚洲片国产一区一级在线观看| 欧美刺激性大交免费视频| 欧美激情91| 夜夜嗨一区二区三区| 亚洲视频axxx| 国产精品亚洲精品| 欧美一区二区三区电影在线观看| 一区二区高清在线观看| 国产婷婷色一区二区三区在线 | 欧美在线免费播放| 亚洲国产专区校园欧美| 欧美成人一区二区在线| 中文高清一区| 亚洲免费一级电影| 国产一区二区三区久久精品| 亚洲黄色有码视频| 国产精品久久9| 女女同性精品视频| 国产精品播放| 日韩午夜在线| 一本色道久久99精品综合| 久久亚洲精品一区二区| 亚洲另类在线一区| 久久综合伊人77777| 久久综合综合久久综合| 狠狠色伊人亚洲综合成人| 亚洲一区二区三区三| 亚洲免费在线观看视频| 老牛嫩草一区二区三区日本| 中日韩男男gay无套| 欧美一区二区三区视频在线 | 欧美电影在线免费观看网站| 亚洲欧美第一页| 欧美精品自拍| 亚洲电影免费在线| 亚洲伦理在线| 国产亚洲午夜| 久久久www成人免费毛片麻豆| 亚洲午夜精品福利| 欧美视频一区二区三区…| 亚洲午夜精品久久久久久浪潮 | 日韩亚洲综合在线| 欧美精品一区三区| 国产精品99久久久久久人| 亚洲精品一区二区网址| 久久男女视频| 在线视频日韩精品| 久久综合影音| 亚洲日韩欧美视频| 欧美精品在线网站| 亚洲欧美日韩视频一区| 99视频有精品| 欧美.www| 久久国产一二区| 亚洲观看高清完整版在线观看| 亚洲激情不卡| 亚洲性人人天天夜夜摸| 亚洲一区www| 欧美视频精品在线观看| 亚洲欧美日韩精品综合在线观看 | 午夜国产精品视频| 久久久青草青青国产亚洲免观| 国产一区二区三区网站| 欧美在线观看www| 欧美一级黄色录像| 一区二区免费在线视频| 久久中文久久字幕| 日韩视频不卡| 亚洲午夜精品网| 亚洲精品欧美极品| 亚洲精品欧美日韩专区| 国产一区二区av| 亚洲国产成人porn| 亚洲美女毛片| 亚洲级视频在线观看免费1级| 国产伊人精品| 国产欧美不卡| 欧美天堂亚洲电影院在线观看| 欧美激情1区2区| 欧美日韩综合视频| 国产又爽又黄的激情精品视频| 欧美日韩在线不卡一区| 欧美日韩国产天堂| 国产一区亚洲一区| 亚洲国产一区二区a毛片| 亚洲精品一区二区三区福利| 一区二区三区在线高清| 亚洲高清中文字幕| 国产亚洲一区在线| 一本色道久久综合亚洲精品婷婷 | 国产一区二区高清| 亚洲欧美日韩区| 国产精品国产三级欧美二区| 国产精品豆花视频| 亚洲人成在线观看一区二区| 在线精品亚洲一区二区| 欧美a级片网| 99热这里只有精品8| 午夜精品久久| 伊人久久婷婷| 欧美色视频日本高清在线观看| 亚洲砖区区免费| 亚洲成人资源网| 欧美中文字幕视频| 亚洲毛片在线观看| 国产欧美精品日韩区二区麻豆天美| 久久米奇亚洲| 亚洲性色视频| 亚洲欧洲免费视频| 久久人人97超碰精品888| 一本色道久久综合精品竹菊| 国产色爱av资源综合区| 欧美日韩黄色一区二区| 久久先锋资源| 欧美亚洲三区| 亚洲私人影院| 亚洲精品一级| 亚洲第一在线综合在线| 久久久久国产精品午夜一区| 亚洲一区二区网站| 一本久久综合亚洲鲁鲁| 亚洲电影在线观看| 国产欧美一区在线| 欧美日韩在线播放三区| 欧美—级在线免费片| 久久亚洲精品中文字幕冲田杏梨 | 国产精品v一区二区三区| 久久久青草婷婷精品综合日韩 | 久久深夜福利免费观看| 亚洲欧美在线高清| 亚洲素人一区二区| 妖精成人www高清在线观看| 亚洲黄页一区| 亚洲人成77777在线观看网| 欧美顶级少妇做爰| 欧美电影免费观看高清完整版| 狂野欧美性猛交xxxx巴西| 久久国产综合精品| 久久国产主播| 亚洲综合色网站| 一本在线高清不卡dvd| 亚洲乱码国产乱码精品精98午夜| 亚洲第一精品夜夜躁人人躁| 亚洲第一精品久久忘忧草社区| 黄色av日韩| 在线欧美三区| 亚洲精品系列| 亚洲一区二区3| 性欧美办公室18xxxxhd| 亚洲欧美一区二区三区极速播放| 一本久久综合| 亚洲综合色丁香婷婷六月图片| 99在线精品视频在线观看| 夜夜嗨网站十八久久| 亚洲午夜激情网站| 亚洲综合第一| 在线亚洲免费| 一区二区三区在线不卡| 国内精品国产成人| 国内精品久久久久久久影视蜜臀| 国产精品久久久久久久第一福利 | 欧美精彩视频一区二区三区| 欧美成人精品1314www| 欧美高潮视频| 欧美视频在线免费| 国产精品入口麻豆原神| 韩国三级电影一区二区|