鱼C论坛

 找回密码
 立即注册
查看: 488|回复: 9

[已解决]一个聊天程序,为什么我的代码运行到这就中止了。

[复制链接]
发表于 2023-7-8 21:10:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
BOOL CChatDlg::OnInitDialog()
{
        CDialog::OnInitDialog();

        // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
        //  执行此操作
        SetIcon(m_hIcon, TRUE);                        // 设置大图标
        SetIcon(m_hIcon, FALSE);                // 设置小图标

        // TODO:  在此添加额外的初始化代码
        InitSocket();
        RECVPARAM *pRevcParam = new RECVPARAM;
        pRevcParam->socket = m_Socket;
        pRevcParam->hwnd = m_hWnd;
        HANDLE hThread = CreateThread(NULL, 0, RecvProc, (LPVOID)pRevcParam, 0, NULL);
        CloseHandle(hThread);
        return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}


DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter)
{
        SOCKET socket = ((RECVPARAM*)lpParameter)->socket;
        HWND hwnd = ((RECVPARAM*)lpParameter)->hwnd;

        SOCKADDR_IN addrFrom;
        int len = sizeof(SOCKADDR);

        char recvBuf[200];
        char tempBuf[300];
        int retVal;
        while (TRUE)
        {
                retVal = recvfrom(socket, recvBuf, 200, 0, (SOCKADDR*)&addrFrom, &len);                        //运行不下去了
                if (SOCKET_ERROR == retVal)
                {
                        break;
                }
                sprintf(tempBuf, "%s说:%s", inet_ntoa(addrFrom.sin_addr), recvBuf);
                ::PostMessage(hwnd, WM_RECVDATA, 0, (LPARAM)tempBuf);
        }
        return 0;
}
最佳答案
2023-7-10 21:35:23
cumulonimbus 发表于 2023-7-10 21:13
不是这样的,是在程序开始运行时就发生的,代码到那就不往下运行了,而是直接跳出,生成对话框程序

可 ...

了解您的问题。如果在运行时代码直接跳出,并且没有执行RecvProc函数的循环,那么可能的原因是在CreateThread创建线程时发生了问题。在这种情况下,我们需要检查CreateThread的返回值以获取更多信息。

以下是如何检查CreateThread的返回值:
  1. HANDLE hThread = CreateThread(NULL, 0, RecvProc, (LPVOID)pRevcParam, 0, NULL);
  2. if (hThread == NULL) {
  3.     DWORD dwError = GetLastError();
  4.     // 这里可以输出或记录错误码,以便进一步分析
  5. } else {
  6.     CloseHandle(hThread);
  7. }
复制代码

如果CreateThread返回NULL,那么代表线程创建失败。您可以检查GetLastError()函数的返回值以获取更多关于失败原因的信息。

另外,您也可以尝试使用C++标准库中的std::thread来替换CreateThread。这将使代码更具可移植性,并减少与Win32 API相关的潜在问题。以下是使用std::thread的示例:
  1. #include <thread>

  2. // ...其他代码...

  3. void CChatDlg::RecvProc(RECVPARAM* pRevcParam) {
  4.     // ...和原来的RecvProc函数一样...
  5. }

  6. // ...其他代码...

  7. BOOL CChatDlg::OnInitDialog() {
  8.     // ...其他初始化代码...

  9.     std::thread recvThread(&CChatDlg::RecvProc, this, pRevcParam);
  10.     recvThread.detach(); // 与主线程分离,允许子线程独立运行

  11.     return TRUE;
  12. }
复制代码

请注意,使用std::thread可能需要对代码进行一些调整,例如将RecvProc的签名从DWORD WINAPI RecvProc(LPVOID)更改为void RecvProc(RECVPARAM*)。

如果这些建议仍无法解决问题,请提供更多的代码和上下文,以便我能更好地理解您的问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-7-8 21:11:17 | 显示全部楼层
我看到您提供了一段C++代码,这是一个聊天程序的一部分。根据您的描述,代码在某个地方中止了。我会尝试帮助您找到可能的问题。

首先,我为代码排版以便更容易阅读:
  1. BOOL CChatDlg::OnInitDialog() {
  2.     CDialog::OnInitDialog();
  3.     SetIcon(m_hIcon, TRUE);
  4.     SetIcon(m_hIcon, FALSE);
  5.     InitSocket();
  6.     RECVPARAM *pRevcParam = new RECVPARAM;
  7.     pRevcParam->socket = m_Socket;
  8.     pRevcParam->hwnd = m_hWnd;
  9.     HANDLE hThread = CreateThread(NULL, 0, RecvProc, (LPVOID)pRevcParam, 0, NULL);
  10.     CloseHandle(hThread);
  11.     return TRUE;
  12. }
  13. DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter) {
  14.     SOCKET socket = ((RECVPARAM*)lpParameter)->socket;
  15.     HWND hwnd = ((RECVPARAM*)lpParameter)->hwnd;
  16.     SOCKADDR_IN addrFrom;
  17.     int len = sizeof(SOCKADDR);
  18.     char recvBuf[200];
  19.     char tempBuf[300];
  20.     int retVal;
  21.     while (TRUE) {
  22.         retVal = recvfrom(socket, recvBuf, 200, 0, (SOCKADDR*)&addrFrom, &len);
  23.         if (SOCKET_ERROR == retVal) {
  24.             break;
  25.         }
  26.         sprintf(tempBuf, "%s说:%s", inet_ntoa(addrFrom.sin_addr), recvBuf);
  27.         ::PostMessage(hwnd, WM_RECVDATA, 0, (LPARAM)tempBuf);
  28.     }
  29.     return 0;
  30. }
复制代码

代码中有一个可能的问题是在 RecvProc 函数的 recvfrom 调用。如果 recvfrom 返回 SOCKET_ERROR ,这意味着在接收数据时发生了错误。这可能导致代码"运行不下去了",也就是您所描述的问题。但是,在这种情况下,代码应该会跳出循环并正常结束线程。

一个可能的原因是 WSAGetLastError() 返回的错误码。在调试过程中,您可以在 recvfrom 调用失败时检查此错误码:
  1. if (SOCKET_ERROR == retVal) {
  2.     int errCode = WSAGetLastError();
  3.     // 这里可以输出或记录错误码,以便进一步分析
  4.     break;
  5. }
复制代码

检查 WSAGetLastError() 返回的错误码可以帮助您找到问题的根本原因。这可能是由于初始化Winsock库的问题、套接字创建问题、套接字选项设置问题等。

请注意,我无法看到您的完整代码,包括 InitSocket() 函数和 RECVPARAM 结构的定义。因此,这里的建议可能无法解决您的问题。如果您需要进一步的帮助,请提供更多的上下文或代码,以便我能更好地理解您的问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-8 21:12:25 | 显示全部楼层
你的代码运行到  recvfrom  函数处时可能会因为几个原因停止运行:

1. 网络问题:如果没有网络连接或者网络连接不稳定, recvfrom  函数可能会因为无法从指定的socket接收数据而阻塞或失败。

2. 阻塞式socket:默认情况下,Windows sockets是阻塞的。这意味着 recvfrom 函数会阻塞,直到它接收到一些数据。如果没有任何数据发送到这个socket,那么这个函数可能会无限期地阻塞。你可能需要查看socket是否已经准备好接收数据,或者设置socket为非阻塞模式。

3. 错误的socket句柄:如果你传给 recvfrom 的socket句柄无效(例如,它已经被关闭),那么这个函数将返回SOCKET_ERROR。

4. 缓冲区溢出:在 recvBuf 定义为200字节,如果从socket接收的数据大于这个大小,可能会导致溢出问题。这不一定会导致程序停止,但可能会引发其他问题,如未定义的行为或数据损坏。

你可以使用  WSAGetLastError  函数来获取具体的错误信息。此函数会返回上一次socket操作失败的原因。可以帮助你了解为什么  recvfrom  函数失败。

例如:

  1. retVal = recvfrom(socket, recvBuf, 200, 0, (SOCKADDR*)&addrFrom, &len);
  2. if (SOCKET_ERROR == retVal)
  3. {
  4.     int error_code = WSAGetLastError();
  5.     printf("recvfrom failed with error code : %d\n", error_code);
  6.     break;
  7. }
复制代码

这样你就可以得到更具体的错误代码,然后查阅相关资料进行解决。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2023-7-9 07:01:37 | 显示全部楼层
根据你提供的代码片段,有几个可能导致程序中止的原因:

1. `InitSocket()` 函数:在 `CChatDlg::OnInitDialog()` 函数中调用了 `InitSocket()` 函数。如果 `InitSocket()` 函数存在问题,可能导致后续的代码无法正常执行。请确保 `InitSocket()` 函数正确初始化了网络套接字,并没有引发任何错误。

2. `CreateThread()` 函数:在 `CChatDlg::OnInitDialog()` 函数中创建了一个线程,调用了 `RecvProc` 函数作为线程函数。如果在创建线程时出现问题,可能导致程序中止。请确保 `CreateThread()` 函数成功创建了线程,并返回了有效的句柄。

3. `RecvProc` 函数:`RecvProc` 函数是作为线程函数在独立线程中执行的。如果在 `recvfrom()` 函数调用时发生错误,可能导致函数中止。请确保网络套接字正确设置,并且能够接收到数据。

在调试这段代码时,你可以尝试以下几个步骤来定位问题:

1. 确保网络套接字的初始化(`InitSocket()`)正确执行,并且没有返回错误代码。你可以检查相关的初始化代码,例如创建套接字、绑定地址等。

2. 检查线程的创建(`CreateThread()`)是否成功,并返回了有效的句柄。你可以在创建线程后,检查 `hThread` 的值是否为有效句柄。

3. 检查 `RecvProc` 函数中的 `recvfrom()` 调用是否正确,并且能够接收到数据。你可以添加调试输出或日志语句,观察程序是否能够进入 `RecvProc` 函数,并在调用 `recvfrom()` 时接收到数据。

4. 检查是否有其他可能导致程序中止的因素。例如,确保程序的消息循环正常运行,正确处理消息等。

如果问题仍然存在,建议提供更多详细的错误信息、调试输出或完整的代码,以便更好地帮助你解决问题。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-10 21:13:04 | 显示全部楼层
陶远航 发表于 2023-7-8 21:11
我看到您提供了一段C++代码,这是一个聊天程序的一部分。根据您的描述,代码在某个地方中止了。我会尝试帮 ...

不是这样的,是在程序开始运行时就发生的,代码到那就不往下运行了,而是直接跳出,生成对话框程序

可惜我上传不了附件。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-10 21:13:41 | 显示全部楼层
isdkz 发表于 2023-7-8 21:12
你的代码运行到  recvfrom  函数处时可能会因为几个原因停止运行:

1. 网络问题:如果没有网络连接或者 ...

不是这样的,是在程序开始运行时就发生的,代码到那就不往下运行了,而是直接跳出,生成对话框程序

可惜我上传不了附件。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-10 21:15:01 | 显示全部楼层
编程追风梦 发表于 2023-7-9 07:01
根据你提供的代码片段,有几个可能导致程序中止的原因:

1. `InitSocket()` 函数:在 `CChatDlg::OnInit ...

不是这样的,是在程序开始运行时就发生的,代码到那就不往下运行了,而是直接跳出,生成对话框程序

可惜我上传不了附件。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-10 21:35:23 | 显示全部楼层    本楼为最佳答案   
cumulonimbus 发表于 2023-7-10 21:13
不是这样的,是在程序开始运行时就发生的,代码到那就不往下运行了,而是直接跳出,生成对话框程序

可 ...

了解您的问题。如果在运行时代码直接跳出,并且没有执行RecvProc函数的循环,那么可能的原因是在CreateThread创建线程时发生了问题。在这种情况下,我们需要检查CreateThread的返回值以获取更多信息。

以下是如何检查CreateThread的返回值:
  1. HANDLE hThread = CreateThread(NULL, 0, RecvProc, (LPVOID)pRevcParam, 0, NULL);
  2. if (hThread == NULL) {
  3.     DWORD dwError = GetLastError();
  4.     // 这里可以输出或记录错误码,以便进一步分析
  5. } else {
  6.     CloseHandle(hThread);
  7. }
复制代码

如果CreateThread返回NULL,那么代表线程创建失败。您可以检查GetLastError()函数的返回值以获取更多关于失败原因的信息。

另外,您也可以尝试使用C++标准库中的std::thread来替换CreateThread。这将使代码更具可移植性,并减少与Win32 API相关的潜在问题。以下是使用std::thread的示例:
  1. #include <thread>

  2. // ...其他代码...

  3. void CChatDlg::RecvProc(RECVPARAM* pRevcParam) {
  4.     // ...和原来的RecvProc函数一样...
  5. }

  6. // ...其他代码...

  7. BOOL CChatDlg::OnInitDialog() {
  8.     // ...其他初始化代码...

  9.     std::thread recvThread(&CChatDlg::RecvProc, this, pRevcParam);
  10.     recvThread.detach(); // 与主线程分离,允许子线程独立运行

  11.     return TRUE;
  12. }
复制代码

请注意,使用std::thread可能需要对代码进行一些调整,例如将RecvProc的签名从DWORD WINAPI RecvProc(LPVOID)更改为void RecvProc(RECVPARAM*)。

如果这些建议仍无法解决问题,请提供更多的代码和上下文,以便我能更好地理解您的问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-11 13:40:48 | 显示全部楼层
陶远航 发表于 2023-7-10 21:35
了解您的问题。如果在运行时代码直接跳出,并且没有执行RecvProc函数的循环,那么可能的原因是在CreateTh ...

谢谢,很有帮助,我会仔细检查一下的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-11 13:44:18 | 显示全部楼层
cumulonimbus 发表于 2023-7-11 13:40
谢谢,很有帮助,我会仔细检查一下的

嗯嗯,没事
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-27 14:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表