首页
社区
课程
招聘
[讨论]总算领教了一下莫名其妙的MFC,痛苦啊!
发表于: 2009-4-6 06:16 7385

[讨论]总算领教了一下莫名其妙的MFC,痛苦啊!

2009-4-6 06:16
7385
偶尔玩的时候,碰上 CSocket 这个类,碰上 SendTo 这个成员函数,它用无连接方式(即UDP啦)发送数据,就是不管目标地址存不存在,你要发送50字节它就返回50,告诉你发送了50字节;这是我测试过的,我乱填个地址,它返回值也一样是你原来要它发送的字节数;

CSocket 从 CAsyncSocket(导步Socket) 派生,就是这个CAsyncSocket,太深奥了(对我来说),且听我慢慢道来;

首先派生一个类,很简单:

class CMessSocket : public CSocket
{
public:
        virtual void OnReceive(int nErrorCode);
};

void CMessSocket::OnReceive(int nErrorCode)
{
        MessageBox(NULL, "OnRceive被执行", "注意", MB_OK);
        return;
}

就这么多, 然后, 在程序初始化时,同时初始化Socket:

CMessSocket  m_socket;
AfxSocketInit(NULL);
m_socket.Create(4321,SOCK_DGRAM);

也很简单,MFC看上去就是十分简单....

要发送数据? 更简单:

m_socket.SendTo(szSend, 50, 137, "192.168.0.101", 0);

其中 szSend 是存放数据的地方,50个字节, 目标端口是137,地址是192.168.0.101, 最后那个标志参数留0;

====> 其实我想说的都不是这些,感兴趣的都不是这些,而是:

当 SendTo 执行完毕, 它肯定是返回 50,告诉你已经发送了 50 字节,无论地址是否真的存在,那么这样意义何在呢?如果事先已经确定地址存在了又不同;但是, CAsyncSocket 会帮你做这些事,如果目标存在,并成功发送,会调用 OnReceive 函数, 如果目标不存在或发送不成功,它绝不会调用 OnReceive 函数。

我很想知道 CAsyncSocket 是如何判断的,但是从 SendTo 的执行过程里我找不到一丁点的蛛丝马迹,这个 SendTo 最终还是一路地跑去执行 WinSock 的 SendTo;

我正在奇怪 CAsyncSocket 是如何判断的,我又遇到了一个更加黑暗的问题: (看如下代码)

char szBuffer[260];
m_socket.SendTo(szSend, 50, 137, "192.168.0.101", 0);
memset(szBuffer, 0, 260);
wsprintf(szBuffer, "Microsoft");
HWND hWin = ::FindWindow(NULL, "test");
if(hWin == NULL)
     lstrcpy(szBuffer, "无聊的测试");
else
{
        int i = 58;
        wsprintf(szBuffer, "%d", i);
}
::MessageBoxA(NULL, szBuffer, "啦啦啦", MB_OK);
__asm
{
       push eax;
       pop eax;
}
return;

=====> 我刚才说过了,如果目标地址存在并且发送成功,会跳到 OnReceive 里去执行; 现在, 你猜一猜, 上面这段代码, 执行到哪里才会跳到 OnReceive 里去 ????

执行 SendTo 时跳到 OnReceive 里去吗? 错;
SendTo 执行完毕后跳到 OnReceive 里去吗? 错;
执行 SendTo 的下一句的跳到 OnReceive 里去吗? 都不是...

上面这段代码,只有执行 ::MessageBoxA(NULL, szBuffer, "啦啦啦", MB_OK); 这句, 才会跳到 OnReceive 里去!!!

我都傻了... 我太菜了;

当最初的 m_socket.Create(4321,SOCK_DGRAM); 执行时, 这个CAsyncSocket会创建一个线程, 这个线程是高优先级的,问题就出在这个线程上面;但是我调试的时候,一直没有看到这个线程有什么动作,也许是我太菜了;

我真正领教了一下什么叫做MFC,什么叫做异步, 太猛了(对我来说 ^_^);

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
异步本来很强大的~
2009-4-6 07:05
0
雪    币: 962
活跃值: (1681)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
发送完成后 系统会帮你的窗口发一个消息 消息引发OnReceive
2009-4-6 10:35
0
雪    币: 255
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这有什么莫名其妙的,socket有几种模式,可以看《Network Programming for Microsoft Windows》
2009-4-6 12:30
0
雪    币: 156
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
这和mfc有关系吗?

lz不熟悉socket吧
2009-4-6 13:44
0
雪    币: 359
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
一、LZ的SOCKET基础不牢,UDP发送方怎么可能知道是否发送成功?
二、LZ消息循环机制基础不牢,这种异步方法,我方可控制的只有一个线程(多出来的那个线程是为了生成对应的事件,不负责处理),只有一个线程的情况下,怎么可能在处理其他事情的时候开小差,跑去OnReceive?OnReceive只有在“接收事件”被消息循环处理的时刻,才可能被执行,而MessageBox内部就嵌了一个消息循环。
2009-4-6 20:26
0
雪    币: 3
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
楼上说的我觉得还有用; 但是我还想重申一下, 按道理说无连接通信是无法判断是否发送成功的,但是主贴上我已经说过了,如果目标存在并且发送成功,OnReceive才会被调用,否则绝不会被调用; 何解?

二,你说的消息循环机制问题;  就算真的是在处理某个消息的时候把OnReceive当作消息处理函数,那么请问, 谁定义了这个消息就一定是OnReceive来处理?

核心代码好像这样:

class CMessSocket : public CSocket
{
public:
  virtual void OnReceive(int nErrorCode);
};

void CMessSocket::OnReceive(int nErrorCode)
{
  MessageBox(NULL, "OnRceive被执行", "注意", MB_OK);
  return;
}

CMessSocket  m_socket;
AfxSocketInit(NULL);
m_socket.Create(4321,SOCK_DGRAM);
m_socket.SendTo(szSend, 50, 137, "192.168.0.101", 0);
..........
.......

谁定义了某个消息由m_socket.OnReceive来处理? CAsyncSocket ?
2009-4-6 21:33
0
雪    币: 359
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
一、应该是你发送的对方,回应了一个数据包,或者你是自己发给自己,因为你这边有数据可以接收,所以就触发了OnReceive事件。
二、MFC的SOCKET框架里面会创建一个不可视的窗口用于处理SOCKET对应的事件,而这些事件都是在另外一个线程(就是多出来的那个)里面通过发送WM_SOCKET_NOTIFY消息到这个不可视的窗口实现的,而不同的事件,只是WPARAM和LPARAM不同而已。在这个窗口的回调函数里面,在处理WM_SOCKET_NOTIFY消息的部分,它会根据SOCKET句柄找到你的CAsyncSocket对象,然后调用它对应的事件处理函数,比如接收事件就是OnReceive,而OnReceive是一个虚函数,所以就可以调用你自己定义的处理过程。

MFC的框架封装了太多的东西,如果真的了解它的机制,就要步步跟踪研究才行,你觉得它封装的不好,大不了你自己再封装一个好了。不过我觉得就算让我重新封装,可能还是会用MFC的这种方法来,毕竟我想不到更好的方法了……
2009-4-6 23:42
0
雪    币: 255
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
网络的东西就自己调api算了,mfc处理下界面。

现在framework都喜欢封装一切接口,网络、内存、文件、xml都要包,喜不喜欢就看自己了。
2009-4-7 00:14
0
雪    币: 3
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
wzanthony, 你太热心了,你太好人了, 我又学到东西了
2009-4-8 09:10
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
这没什么莫名其妙的,你到底“领教”了MFC的什么?你自已的问题怪MFC, 这才莫名其妙。
2009-4-8 13:12
0
游客
登录 | 注册 方可回帖
返回
//