各位高手,求救!!在一个线程中使用CAsyncSocket类的对象,为什么不能触发事件???在线等待

openesource 2003-10-30 03:38:28
在一个线程中使用一个CAsyncSocket类的对象,为什么不能触发事件???当我调用Connect函数后,OnConnect()并没有被触发,但是放到线程外调用的话,又没有问题,请教为什么???

各位高手,帮帮忙,在线等待!!!!!!
...全文
214 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
openesource 2003-10-31
  • 打赏
  • 举报
回复
听了大家说了半天,感觉要在一个UI线程下创建CAsyncSocket才有效,但是还是不很明白,各位,想必这样的问题你们以前也经历过,可以给些示例代码吗???
我的邮箱 sunx126@126.com
MilitaryMiniatures 2003-10-31
  • 打赏
  • 举报
回复
呵呵。不知道你这么问是什么意思。
什么叫“还要另外写代码”?
zhouqingyuan 2003-10-31
  • 打赏
  • 举报
回复
up
chenanqiong 2003-10-31
  • 打赏
  • 举报
回复
To:MilitaryMiniatures(++)
佩服!但是小弟要问个肤浅的问题,你的TranslateMessage()和DispatchMessage()两个函数还要另外写代码吗?
MilitaryMiniatures 2003-10-31
  • 打赏
  • 举报
回复
听了大家说了半天,感觉要在一个UI线程下创建CAsyncSocket才有效,但是还是不很明白,各位,想必这样的问题你们以前也经历过,可以给些示例代码吗???
我的邮箱 sunx126@126.com
-------------------------------------------------------------------------------
其实,事情是这样的,你如果要处理CAsyncSocket的事件,说白了,就是要想那几个虚函数被调用,那么创建CAsyncSocket的线程必须包含消息循环,也就是成为你说的UI线程了。
不过,你的程序也不一定要这几个函数被调用啊。
我以前做的一个视频传输的,根本就不处理事件,它在一个线程中运行,一直试图读取数据,或者发送数据。不过这样子效率比较低。
SyDes21 2003-10-31
  • 打赏
  • 举报
回复
基本上被别人说完了.
zlj617 2003-10-31
  • 打赏
  • 举报
回复
To: MilitaryMiniatures(++)
说的和好,说的秒啊!
winter_sui 2003-10-31
  • 打赏
  • 举报
回复
To: MilitaryMiniatures(++)

说得真多,小弟佩服。分析的很透彻,虽然我不懂网络,也没看懂。
lizmei001 2003-10-30
  • 打赏
  • 举报
回复
CAsyncSocket 会自己创建一个隐藏的窗口,在你开的线程中,创建窗口会失败
MilitaryMiniatures 2003-10-30
  • 打赏
  • 举报
回复
对了,你还要通过调用CAsyncSocket::AsyncSelect来表明你想要接受的事件。
MilitaryMiniatures 2003-10-30
  • 打赏
  • 举报
回复
忍不住要说几句。

CAsyncSocket是一个MFC类,它通过虚函数来实现回调。那么,CAsyncSocket何时调用这些虚函数呢?这就决定于这个对象收到的消息的时间。
事实上,在MFC的实现中,对于socket通信,它专门创建了一个高优先级的线程(为表述的方便,我们称之为A线程),该线程一直查询有无socket事件,如果监测到有事件,就给一个线程发消息,这种消息是通过post来实现的。那么,这条消息该发给谁呢?CAsyncSocket不是窗口类,所以不能接受消息。

下面就解释这条消息该发送给谁。
每一个线程,要使用CAsyncSocket(就是说要调用CAsyncSocket::Create),就必须对socket进行初始化,一般的方法时调用AfxSocketInit来实现,这个函数在实现的时候,就创建了一个隐含窗口,也就是说,你不同的线程中,要分别使用CAsyncSocket(也就是要调用CAsyncSocket::Create),那么这个线程中就创建一个隐含的窗口,而且,一个线程只有一个这样的窗口。即使一个线程中用到了多个CAsyncSocket对象,他们也共同使用这一个窗口。那么,这个窗口就可以处理消息了。从而线程A在监测到socket事件的时候,就可以给一个窗口发送消息,而在窗口的消息处理中,就调用了CAsyncSocket::OnReceive/OnSend/OnConnect等虚函数。

接下来,就是要说清楚,MFC怎么实现消息的post。在MFC的A线程监测到socket事件的时候,他要判断出是哪个socket的事件,接着要找到这个socket所对应的窗口(一个窗口中可能对应了多个socket),找到窗口之后,就给这个窗口post消息了。接下来,窗口调用窗口过程处理消息。

接下来,就是窗口的过程。这里必须明确一点,那就是,窗口的过程是属于创建该窗口的线程所有的,也就是说,窗口的过程总是在创建他的线程中执行。而由于CAsyncSocket::OnConnect/OnReceive/OnSend等虚函数,总是在窗口过程中调用的,从而他们也属于创建他们的线程。说白了,就是如果你在线程B初始化了socket(AfxSocketInit),那么就创建了B线程的socket窗口WinB,然后你在该线程中调用了某个CAsyncSocket的Create函数之后,这个socket就和WinB挂钩起来了。然后这个CAsyncSocket的回调函数OnSend/OnReceive/OnConnect等,肯定在线程B中被调用,而不会被线程C调用。也就是相当于CAsyncSocket这个对象,被线程B所拥有。就这个意义上来讲,CAsyncSocket的这种机制,和Windows的窗口过程特别相似,因此MFC在生成代码的时候,CAsyncSocket的派生类中,还保留了消息处理的那些影子(一些注释的东西)。

接下来,线程B为了能够处理该线程中的窗口WinB的消息,就必须有消息循环,如果没有消息循环,再多的事件也不会导致OnReceive的调用。注意,是线程B必须具有消息循环。线程B也就是调用CAsyncSocket::Create的那个线程。

就说这么多,希望有帮助。
chenanqiong 2003-10-30
  • 打赏
  • 举报
回复
CAsyncSocket类用DoCallBack函数处理MFC消息,当一个网络事件发生时,DoCallBack函数按网络事件类型:FD_READ、FD_WRITE、FD_ACCEPT、FD_CONNECT分别调用OnReceive、OnSend、OnAccept、OnConnect函数。
如果你的CAsyncSocket对象在线程中,有可能无法收到MFC消息,所以不能够自动调用OnReceive、OnSend、OnAccept、OnConnect函数等函数了.
Healer 2003-10-30
  • 打赏
  • 举报
回复
你有一个概念不够清晰:)

当Client调用OnConnect函数的时候, Server要用OnAccept去处理这个消息的到来:)

而不是OnConnect();
huanyun 2003-10-30
  • 打赏
  • 举报
回复
WSANETWORKEVENTS we;
int iRet=WSAEnumNetworkEvents(pTelnetCtrl->m_Socket,pTelnetCtrl->m_hSocketEvent,&we);
if(we.lNetworkEvents&FD_READ)
{
pTelnetCtrl->RecvTransData();
// printf("FD_READ\n");
}
if(we.lNetworkEvents&FD_ACCEPT)
{
//printf("accept\n");
//OnAccept();
}
if(we.lNetworkEvents&FD_CLOSE)
{
//printf("Close\n");
//pTelnetCtrl->DisConnect();
pTelnetCtrl->Close();
pTelnetCtrl->m_bThreadAlive = FALSE;
AfxEndThread(100);
}
if(we.lNetworkEvents&FD_CONNECT)
{
//printf("accept\n");
//OnConnect();
}
huanyun 2003-10-30
  • 打赏
  • 举报
回复
难道消息在你创建CAsyncSocket实例的线程中才能接收的
其实有更好的
if((m_hSocketEvent = WSACreateEvent())==WSA_INVALID_EVENT)
{
AfxMessageBox("WSACreateEvent error!!\n");
return FALSE;
}

if(WSAEventSelect(m_Socket,m_hSocketEvent,FD_READ|FD_CLOSE|FD_ACCEPT|FD_CONNECT) == SOCKET_ERROR)
{
AfxMessageBox("Event Select Error,errno[%d]!\n",WSAGetLastError ());
return FALSE;
}
chenshijin 2003-10-30
  • 打赏
  • 举报
回复
应该是消息不能被该线程所捕获!
MilitaryMiniatures 2003-10-30
  • 打赏
  • 举报
回复
注意,CAsyncSocket的OnConnect要被调用,就必须在创建CAsyncSocket的线程中,存在消息循环。
因此,你在Connect函数调用之后,你加上消息循环看看怎么样,比如如下的代码:
MSG msg;
DWORD t1 = ::GetTickCount();
DWORD t2 = t1;
while (t2 - t1 < 5000)//wait 5 seconds
{
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)
{
if (!::AfxGetThread()->PreTranslateMessage(&msg))
{
if (!::TranslateMessage(&msg)) ::DispatchMessage(&msg);
}
}
t2 = ::GetTickCount();
}
...
flagfly 2003-10-30
  • 打赏
  • 举报
回复
感觉线程中就不能触发这些事件

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧