馨荣家园

室主感言:可以走错路,不可不走路,也不可总踩别人脚印走路。

  VC知识库BLOG :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 登录 ::
  51 随笔 :: 5 文章 :: 1327 评论 :: 18 Trackbacks
<2009年6月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

News

阿荣陋室更名为馨荣家园,寓指温馨和繁荣。

留言簿(195)

随笔分类

随笔档案

文章分类

文章档案

相册

友情链接

搜索

最新评论

阅读排行榜

评论排行榜

现象

用多线程方法设计socket程序时,你会发现在跨线程使用CAsyncSocket及其派生类时,会出现程序崩溃。所谓跨线程,是指该对象在一个线程中调用Create/AttachHandle/Attach函数,然后在另外一个线程中调用其他成员函数。下面的例子就是一个典型的导致崩溃的过程:
CAsyncSocket Socket;
UINT Thread(LPVOID)
{
       Socket.Close ();
       return 0;
}
void CTestSDlg::OnOK() 
{
       // TODO: Add extra validation here
       Socket.Create(0);
       AfxBeginThread(Thread,0,0,0,0,0);
}

其中Socket对象在主线程中被调用,在子线程中被关闭。

跟踪分析

这个问题的原因可以通过单步跟踪(F11)的方法来了解。我们在Socket.Create(0)处设断点,跟踪进去会发现下面的函数被调用:

void PASCAL CAsyncSocket::AttachHandle(
          SOCKET hSocket, CAsyncSocket* pSocket, BOOL bDead)
{
    _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
    BOOL bEnable = AfxEnableMemoryTracking(FALSE);
    if (!bDead)
    {
             ASSERT(CAsyncSocket::LookupHandle(hSocket, bDead) == NULL);
             if (pState->m_pmapSocketHandle->IsEmpty())
             {
                  ASSERT(pState->m_pmapDeadSockets->IsEmpty());
                  ASSERT(pState->m_hSocketWindow == NULL);
                  CSocketWnd* pWnd = new CSocketWnd;
                  pWnd->m_hWnd = NULL;
                  if (!pWnd->CreateEx(0, AfxRegisterWndClass(0),
                                   _T("Socket Notification Sink"),
                                 WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL))
                 {
                       TRACE0("Warning: unable to create socket notify window!\n");
                       AfxThrowResourceException();
                 }
                 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
    {
           int nCount;
           if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
                     nCount++;
           else
                     nCount = 1;
           pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
   }
   AfxEnableMemoryTracking(bEnable);
}

在这个函数的开头,首先获得了一个pState的指针指向_afxSockThreadState对象。从名字可以看出,这似乎是一个和线程相关的变量,实际上它是一个宏,定义如下:

#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)
    {
            ASSERT(CAsyncSocket::LookupHandle(hSocket, FALSE) != NULL);

我们在这个ASSERT处设置断点,跟踪进LookupHandle,会发现这个函数定义如下:

CAsyncSocket* PASCAL CAsyncSocket::LookupHandle(SOCKET hSocket, BOOL bDead)
{
     CAsyncSocket* pSocket;
     _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
     if (!bDead)
     {
             pSocket = (CAsyncSocket*)
             pState->m_pmapSocketHandle->GetValueAt((void*)hSocket);
             if (pSocket != NULL)
                  return pSocket;
    }
    else
    {
             pSocket = (CAsyncSocket*)
                  pState->m_pmapDeadSockets->GetValueAt((void*)hSocket);
             if (pSocket != NULL)
                   return pSocket;
    }
    return NULL;
}

显然,这个函数试图从当前线程查询关于这个 socket的信息,可是这个信息放在创建这个socket的线程中,因此这种查询显然会失败,最终返回NULL。

有人会问,既然它是ASSERT出错,是不是Release就没问题了。这只是自欺欺人。ASSERT/VERIFY都是检验一些程序正常运行必须正确的条件。如果ASSERT都失败,在Release中也许不会显现,但是你的程序肯定运行不正确,啥时候出错就不知道了。

如何在多线程之间传递socket

有些特殊情况下,可能需要在不同线程之间传递socket。当然我不建议在使用CAsyncSOcket的时候这么做,因为这增加了出错的风险(尤其当出现拆解包问题时,有人称为粘包,我基本不认同这种称呼)。如果一定要这么做,方法应该是:

  1. 当前拥有这个socket的线程调用Detach方法,这样socket句柄和C++对象及当前线程脱离关系
  2. 当前线程把这个对象传递给另外一个线程
  3. 另外一个线程创建新的CAsyncSocket对象,并调用Attach

上面的例子,我稍微做修改,就不会出错了:

CAsyncSocket Socket;
UINT Thread(LPVOID sock)
{
         Socket.Attach((SOCKET)sock);
         Socket.Close ();
         return 0;
}
void CTestSDlg::OnOK() 
{
         // TODO: Add extra validation here
         Socket.Create(0);
         SOCKET hSocket = Socket.Detach ();
         AfxBeginThread(Thread,(LPVOID)hSocket,0,0,0,0);
}
posted on 2005-12-03 14:08 馨荣家园 阅读(8810) 评论(25)  编辑 收藏

评论

# re: CAsyncSocket对象不能跨线程之分析 2006-02-15 15:42 ocean
很好!

# re: CAsyncSocket对象不能跨线程之分析 2006-03-02 22:55 babazhang
MSDN里给出的是一句不痛不痒的话,CSocket /CAsyncSocket is not thread-safety.  说白了就是数据一旦跟窗口搭上钩后,消息循化就会和子线程有数据竞争,而socket缓冲区是没有采用同步对象保护的,所以就会不安全。

# re: CAsyncSocket对象不能跨线程之分析 2006-03-17 08:08 Shen Fang
很实用,非常感谢搂主

# re: CAsyncSocket对象不能跨线程之分析 2007-01-25 12:10 lele
我用了一下,不能通过,在attach处出错

# re: CAsyncSocket对象不能跨线程之分析 2007-04-12 09:48 libo
说的很好,感谢。

# re: CAsyncSocket对象不能跨线程之分析 2008-01-17 15:28 玻璃小屋

荣哥!!!顶!!

# re: CAsyncSocket对象不能跨线程之分析 2008-04-04 10:31 刘庭洋
十分感谢,我正需要使用CAsyncSocket跨线程操作。

# re: CAsyncSocket对象不能跨线程之分析 2008-05-09 18:09 御龙
你好,,很想跟你交个朋友,能留下你的QQ吗
我QQ:77066419

# re: CAsyncSocket对象不能跨线程之分析 2008-07-30 20:08 heyyouwest12
http://www.mesos-maple.com
http://www.wowgolds.us
http://www.lotro-golds.us
http://www.lotrogolds.eu
http://www.goldsrunescape.com 
http://www.runescapegold.us 
http://www.runescape2gold.net
http://www.ccgolds.com
http://www.cheap-mesos.com

# re: CAsyncSocket对象不能跨线程之分析 2008-08-18 19:43 aayz
感谢

# re: CAsyncSocket对象不能跨线程之分析 2008-08-20 13:32 翻译公司
3Q

# re: CAsyncSocket对象不能跨线程之分析 2008-10-07 10:46 michaelee
我把CAsyncSocket Socket作为CTestSDlg的一个public成员,把Thread函数作为CTestSDlg的一个静态公共成员函数。然后在传递线程参数的时候,把把this指针传给线程函数。
把你的代码修改一下:

UINT  CTestSDlg::Thread(LPVOID param)
{
 CTestSDlg *pDlg = ( CTestSDlg*)param;
       pDlg->Socket.Close ();
       return 0;
}
void CTestSDlg::OnOK() 
{
       // TODO: Add extra validation here
       Socket.Create(0);
       AfxBeginThread(Thread,LPVOID)this,0,0,0,0);
}

这样子会有问题吗,我现在做的东西就是这样子的。
不知道会不会出错。


# re: CAsyncSocket对象不能跨线程之分析 2008-12-05 16:05 wow power leveling
http://www.wow-power-lvl.com
http://www.cheap-powerleveling.com
http://www.wow-power-lvl.com/WoW-Emblem-of-Heroism-Powerleveling.html
http://www.wow-power-lvl.com/Runescape-Gold.html
http://www.wow-power-lvl.com/Runescape-Powerleveling.html

<a href=http://www.wow-power-lvl.com>wow power leveling</a>
<a href=http://www.wow-power-lvl.com>wow powerleveling</a>
<a href=http://www.wow-power-lvl.com>cheap wow power leveling</a>
<a href=http://www.wow-power-lvl.com>world of warcraft power leveling</a>
<a href=http://www.cheap-powerleveling.com>wow power leveling</a>
<a href=http://www.cheap-powerleveling.com>cheap wow power leveling</a>
<a href=http://www.cheap-powerleveling.com>world of warcraft power leveling</a>

<a href=http://www.wow-power-lvl.com/WoW-Emblem-of-Heroism-Powerleveling.html>WoW Emblem of Heroism Farming Powerleveling</a>
<a href=http://www.wow-power-lvl.com/WoW-Emblem-of-Heroism-Powerleveling.html>WoW Emblem of Heroism Farming Powerleveling</a>
<a href=http://www.wow-power-lvl.com/WoW-Emblem-of-Heroism-Powerleveling.html>WoW Emblem of Heroism Powerleveling</a>

# re: CAsyncSocket对象不能跨线程之分析 2009-05-17 05:43 gfdg


[URL=http://www.xinxinjx.com/en/products.asp]flexographic printing machine[/URL][URL=http://www.chinalisheng.cn">http://www.chinalisheng.cn]给袋式包装机[/URL][URL=http://www.chinalisheng.cn">http://www.chinalisheng.cn]立升机械[/URL][url=http://www.hengtongchina.com/news.asp">http://www.hengtongchina.com/news.asp">http://www.hengtongchina.com/news.asp">http://www.hengtongchina.com/news.asp]手挽袋机[/url][url=http://www.hengtongchina.com/news.asp">http://www.hengtongchina.com/news.asp">http://www.hengtongchina.com/news.asp">http://www.hengtongchina.com/news.asp]手挽袋成型机[/url][url=http://www.hengtongchina.com/news.asp">http://www.hengtongchina.com/news.asp">http://www.hengtongchina.com/news.asp">http://www.hengtongchina.com/news.asp]手挽袋糊底机[/url][url=http://www.cnxinda.cn/english/index1.asp">http://www.cnxinda.cn/english/index1.asp">http://www.cnxinda.cn/english/index1.asp">http://www.cnxinda.cn/english/index1.asp]non woven bag making[/url][url=http://www.cnxinda.cn/english/index1.asp">http://www.cnxinda.cn/english/index1.asp">http://www.cnxinda.cn/english/index1.asp">http://www.cnxinda.cn/english/index1.asp]non woven bag making machinery[/url][url=http://www.cnxinda.cn/english/index1.asp">http://www.cnxinda.cn/english/index1.asp">http://www.cnxinda.cn/english/index1.asp">http://www.cnxinda.cn/english/index1.asp]non woven bag making machine[/url][url=http://www.cnxinda.cn/intro.asp">http://www.cnxinda.cn/intro.asp]横切机[/url][url=http://www.cnxinda.cn/intro.asp">http://www.cnxinda.cn/intro.asp]封切机[/url]

# re: CAsyncSocket对象不能跨线程之分析 2009-05-22 22:57 北京翻译公司


# CAsyncSocket对象不能跨线程之分析 (转载)[TrackBack] 2009-06-20 21:39 cutepig
CAsyncSocket对象不能跨线程之分析 http://blog.vckbase.com/arong/archive/2005/12/03/15578.html
cutepig引用了该文章,地址:http://www.cnblogs.com/cutepig/archive/2009/06/20/1507498.html

# www.handbagsl.com 2009-08-17 15:40 JohnVitelli
<a href="http://www.bootsluxury.com/"">http://www.bootsluxury.com/" title="ugg boots"><strong>ugg boots</strong></a>
<a href="http://www.handbagspop.com/"">http://www.handbagspop.com/" title="designer handbags"><strong>designer handbags</strong></a>
<a href="http://www.christianlouboutinmy.com/"">http://www.christianlouboutinmy.com/" title="christian louboutin"><strong>christian louboutin</strong></a>
<a href="https://www.handbagsboots.com/"">https://www.handbagsboots.com/" title="louis vuitton handbags"><strong>louis vuitton handbags</strong></a>
<a href="https://www.handbagsl.com/"">https://www.handbagsl.com/" title="handbags"><strong>handbags</strong></a>
<a href="http://www.bootsluxury.com/"">http://www.bootsluxury.com/" title="ugg store"><strong>ugg store</strong></a>
<a href="http://www.handbagspop.com/"">http://www.handbagspop.com/" title="replica handbags"><strong>replica handbags</strong></a>
<a href="http://www.christianlouboutinmy.com/"">http://www.christianlouboutinmy.com/" title="designer shoes"><strong>designer shoes</strong></a>
<a href="https://www.handbagsboots.com/"">https://www.handbagsboots.com/" title="gucci handbags"><strong>gucci handbags</strong></a>
<a href="https://www.handbagsl.com/"">https://www.handbagsl.com/" title="replica handbags"><strong>replica handbags</strong></a>


# re: CAsyncSocket对象不能跨线程之分析 2009-09-11 14:36 发个


[url=http://www.yfcj.com.cn]股票软件[/url] [url=http://www.yfcj.com.cn/html/dazhihui/]大智慧[/url] [url=http://www.yfcj.com.cn/html/tonghuashun/]同花顺[/url] [url=http://www.yfcj.com.cn/html/chaoguruanjian/]炒股软件[/url] [url=http://www.yfcj.com.cn/html/tongdaxin/]通达信[/url] [url=http://www.yfcj.com.cn/html/qianlonggupiaoruanjian/]钱龙[/url] [url=http://www.yfcj.com.cn/html/zhengquanzhixing/]证券之星[/url] [url=http://www.yfcj.com.cn/html/zhinanzhen/]指南针[/url]

# re: CAsyncSocket对象不能跨线程之分析 2009-09-11 14:36 发个


[url=http://www.yfcj.com.cn]股票软件[/url] [url=http://www.yfcj.com.cn/html/dazhihui/]大智慧[/url] [url=http://www.yfcj.com.cn/html/tonghuashun/]同花顺[/url] [url=http://www.yfcj.com.cn/html/chaoguruanjian/]炒股软件[/url] [url=http://www.yfcj.com.cn/html/tongdaxin/]通达信[/url] [url=http://www.yfcj.com.cn/html/qianlonggupiaoruanjian/]钱龙[/url] [url=http://www.yfcj.com.cn/html/zhengquanzhixing/]证券之星[/url] [url=http://www.yfcj.com.cn/html/zhinanzhen/]指南针[/url]

# re: CAsyncSocket对象不能跨线程之分析 2009-12-14 17:18 nike dunk low
<A href="http://www.wholesaleshoes.net.cn/nike-dunk-low.html">nike dunk low</A> <A href="http://www.wholesaleshoes.net.cn/shox-r4.html">shox r4</A> <A href="http://www.wholesaleshoes.net.cn/adidas-nike-puma.html">adidas nike puma</A> <A href="http://www.wholesaleshoes.net.cn/cheap-puma-shoes.html">cheap puma shoes</A> <A href="http://www.wholesaleshoes.net.cn/wholesale-ugg.html">wholesale ugg</A> <A href="http://www.wholesaleshoes.net.cn/nike-air-max.html">nike air max</A><A href="http://www.thermometermanufacturer.cn/html/en/pressure_gauge_thermometer.html">Pressure Gauge Manufacturer</A> <A href="http://www.thermometermanufacturer.cn/html/en/pressure_gauge_thermometer.html">Thermometer Manufacturer</A><A href="http://www.thermometermanufacturer.cn/html/en/thermowell.html">Thermowell</A><A href=" http://www.bhbzjx.cn/en/products_list.asp">Bag">http://www.bhbzjx.cn/en/products_list.asp">Bag making Machine</A><A href="http://www.guowang.com/en/eabout.html">paper cutting machine</A><A href="http://www.bhbzjx.cn/eproduct.html">plastic machine</A><A href=" http://www.bhbzjx.cn/en/products_list.asp">Bag">http://www.bhbzjx.cn/en/products_list.asp">Bag making Machine</A><A href="http://www.huayihats.com/felthats.html">felt hats</A><A href="http://www.rzdvdcreator.com">avi to dvd</A> <A href="http://www.ball-clay.com/ballclay.html">ball clay</A>

# re: CAsyncSocket对象不能跨线程之分析 2009-12-14 17:18 nike dunk low
<A href="http://www.lvbao8.com.cn/lvbao.html">lv包</A><A href="http://www.lvbao8.com.cn">女包批发</A><A href="http://www.wanyuanbj.com/product.html">制袋机</A><A href="http://www.shang-wang.com/tubuji.htm">涂布机</A><A href="http://www.rafeiyang.com/qizhangzhou.html">气胀轴</A><A href="http://www.boxianji.com.cn">剥线机</A><A href="http://www.boxianji.com.cn/bxj.html">电脑剥线机</A> <A href="http://www.ckfct.com/products.html">母线槽</A> [url=http://www.isens.com.cn/web/pro-dzlp.htm]电子罗盘[/url][url=http://www.isens.com.cn/web/pro-gxdh.htm]惯性导航[/url][url=http://www.isens.com.cn/web/pro-cgq.htm]倾角传感器[/url][url=http://www.isens.com.cn/web/pro-jsdj.htm]加速度计[/url] [url=http://www.zhidaiji.net.cn]织带机[/url]

# re: CAsyncSocket对象不能跨线程之分析 2009-12-14 17:18 beijing escort
shanghai escort <A href="http://www.shanghaiescorts.net.cn">shanghai escort</A><A href="http://www.shanghaiescort.com.cn"> shanghai escort</A><A href=" http://www.shenzhenescort.net.cn">shenzhen escort</A> <A href="http://www.shenzhenescort.net.cn">massage shenzhen</A><A href="http://www.51beijingescort.com.cn">beijing">http://www.51beijingescort.com.cn">beijing escort</A><A href="http://www.51beijingescort.com.cn">beijing">http://www.51beijingescort.com.cn">beijing massage</A><A href="http://www.51beijingescort.com.cn">escort in beijing</A><A href="http://www.beijingescort8.cn">beijing escort </A>

# re: CAsyncSocket对象不能跨线程之分析 2009-12-14 17:22 上海搬家
<A href="http://www.poffilm.com/pof.html">pof</A><A href="http://www.usegps.cn/gps">GPS</A> <A href="http://www.usegps.cn">陀螺仪</A><A href="http://www.usegps.cn">惯性导航</A> <A href="http://www.usegps.cn">倾角传感器</A><A href="http://www.usegps.cn">电子罗盘</A><A href="http://www.usegps.cn">加速度计</A> <A href="http://www.siyinji88.com.cn">丝网印刷机</A><A href="http://www.siyinji88.com.cn">丝印机</A> <A href="http://www.siyinji88.com.cn/guangguji">光固机</A> <A href="http://www.siyinji88.com.cn/guangguji">晒版机</A><A href="http://www.sh28.com.cn/shwlgs.htm">上海物流公司</A> <A href="http://www.bagmakingmachine.net.cn/eabout.html">bag making machine</A> <A href="http://www.bagmakingmachine.net.cn">制袋机</A> <A href="http://www.bagmakingmachine.net.cn/wfbzdj.html">无纺布制袋机</A> <A href="http://www.fastenersinc.cn">紧固件</A> <A href="http://www.fastenersinc.cn">标准件</A><A href="http://www.fastenersinc.cn">螺丝</A><A href="http://www.tian-rui.com.cn">广告灯箱</A><A href="http://www.bhbzjx.cn">制袋机</A><a href="http://hi.baidu.com/google315">google排名</A><A href="http://www.sh28.com.cn">上海搬家</A><A href="http://www.sh28.com.cn">上海搬家公司</A><A href="http://www.sh28.com.cn">上海大众搬家公司</A><A href="http://www.sh28.com.cn">上海大众搬家</A><A href="http://www.sh28.com.cn/about.htm">上海搬场</A><A href="http://www.sh28.com.cn/about.htm">上海搬场公司</A><A href="http://www.021banjiagongsi.com.cn">上海搬家公司</A>

# re: CAsyncSocket对象不能跨线程之分析 2009-12-14 17:22 广州搬家公司
<A href=" http://www.gzbanjia8.com.cn">广州搬家公司</A><A href="http://www.021banjia.com.cn">上海搬家公司</A><A href="http://www.021banjia.com.cn">上海搬家</A><A href=" http://www.gzbanjia8.com.cn">广州搬场公司</A><A href="http://www.cnyouxiang.com/ypsjhf.html">硬盘数据恢复</A><A href="http://www.cnyouxiang.com/ypsjhf.html">杭州数据恢复</A><A href="http://www.nbuico.com/product-list-info-58.html">烘箱</A><A href="http://www.qiming8.com.cn">宝宝起名</A> <A href="http://www.duihanji.net.cn">对焊机</A><A href="http://www.xeortec.com/huishou.html">溶剂回收</A>

# re: CAsyncSocket对象不能跨线程之分析 2010-03-09 12:19 小马_xiao
这样只是 把CSocket 从一个线程搬到令一个线程 ,能实现多线程共享吗

标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]