代码之家  ›  专栏  ›  技术社区  ›  JamesSugrue

在我的MFC套接字代码中,CAsyncSocket断言问题和“不正确参数”错误的背后是什么?

  •  5
  • JamesSugrue  · 技术社区  · 7 年前

    我被要求为一个朋友看一些代码。(由于MFC和许多糟糕的代码,我正确地犹豫了一下,但他赢了…)

    这是一个基于对话框的应用程序,使用 CAsyncSocket .

    这个问题表现在一些不间断的debugbreak和其他类似的事情上——MFC也有问题 ENSURE() 宏-检查套接字是否为空。所有这些问题都发生在MFC的深处。

    一些谷歌搜索显示,如果在Vista/XP中使用主题,可能会出现资源泄漏,但我认为这不是问题所在。

    根据我几个小时的调试,代码相当糟糕,但基本上它做了以下工作:

    (当建立连接时,没有问题-仅当没有连接时)

    • 调用Connect(服务器、套接字)(在派生服务器上) CAsyncSocket
    • OnConnect() 我们收到通知,连接未工作/未连接。
    • 如果我们检测到我们未连接(网络) OnConnect() 不好)然后我们打电话 CAsyncSocket::Close() CAsyncSocket::Create() (无参数)然后调用 CAsyncSocket::Connect(server, port)

    Connect() 我以前没有打电话给你 Create() .

    我的第一个真正的问题是:

    • 创建()

    一般性问题:

    • 上面代码的设计到底出了什么问题?

    编辑:

    我修改了代码,使所有路径都通过调用 创建() 然后 .

    我对中的断言仍然有问题 CAsyncSocket::DoCallBack() -下面代码的最后一行是断言:

    void PASCAL CAsyncSocket::DoCallBack(WPARAM wParam, LPARAM lParam)
    {
        if (wParam == 0 && lParam == 0)
            return;
    
        // Has the socket be closed - lookup in dead handle list
        CAsyncSocket* pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, TRUE);
    
        // If yes ignore message
        if (pSocket != NULL)
            return;
    
        pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, FALSE);
        if (pSocket == NULL)
        {
            // Must be in the middle of an Accept call
            pSocket = CAsyncSocket::LookupHandle(INVALID_SOCKET, FALSE);
            ENSURE(pSocket != NULL);
    

    如果我一步一步地完成,那么我会得到一个消息框:“遇到一个不正确的参数”

    DoCallback() )但我已经打过电话了 Close() 在插座上。

    所以它看起来确实像一个MFC问题,除非我应该先退订。

    2 回复  |  直到 6 年前
        1
  •  6
  •   paxdiablo    16 年前

    你的选择真的。如果您认为使用另一个套接字实现会更幸运,那么就这样做。

    也许 要想一想,错误并不都在他们的终点。

    也许如果你花时间去理解MFC模型,你会得到“啊哈”的时刻,并更好地理解它。我不是Winsock的粉丝——我更习惯于UNIX世界,在这个世界中,同步是一种方式,如果需要异步类型的behavor,您只需运行单独的进程/线程。

    我怀疑CAsyncSocket仍然受到MFC是单线程模型(就GUI而言)这一事实的阻碍,尽管Windows已经有相当长一段时间具有真正的先发制人线程。[我可能错了,我已经有一段时间没有直接使用Win32了]。


    更新:

    根据你的更新,你说你在做什么,我相当肯定你不允许在创建之前连接。引用 http://msdn.microsoft.com/en-us/library/3d46645f(VS.80).aspx

    至于原因,我认为这增加了额外的复杂性,因为Windows需要在事件泵送环境中执行异步套接字,因为它们无法阻止主GUI线程。

    在UNIXy环境中,要么没有事件线程(正常进程),要么网络操作只是手动分配给另一个线程(在GUI应用程序中)。

    select() 或线程/进程]。


    进一步更新:

    如果在套接字对象上有挂起的操作时关闭和/或删除了该套接字对象,则通常会发生该断言(非异常)。在您的情况下,我建议在您关闭它时,它仍在尝试进行连接。

    然后,当连接成功或失败时,将调用回调,并且它无法在表中找到您的套接字。

    这不是MFC问题,这是您朋友的代码违反了合同。如果执行连接(或任何异步操作),则必须

    从内存中,您可以调用 create() OnXXX() 功能)。像所有Win32 GUI一样,消息应该驱动程序(代码运行以响应消息)。这段代码看起来越来越像经典的编码,程序驱动一切——这种方式让你的程序和异步套接字“线程”争夺控制权。

    我已经有很长一段时间没看了,但是你应该能够得到一个CHATSRVR示例程序,它将告诉你如何做。

        2
  •  4
  •   Michael Burr    17 年前

    问题可能是编写的代码很糟糕,很可能与MFC关系不大或根本没有关系。但是,从您的描述中很难说清楚,“我有一个MFC应用程序,它抛出各种调试断言。我应该怎么做?”。

    推荐文章