【问题标题】:TCP Server C++ programTCP 服务器 C++ 程序
【发布时间】:2015-06-09 01:07:06
【问题描述】:

我正在为我的班级编写一个简单的 C++ 服务器程序。我们的教授给了我们要遵循的框架代码,以及 cmets 中的说明。我完成了它,它在 Unix 中编译,但我遇到了来自客户端的密码验证问题。它是这样写的,所以它会命中所有可能的选项,但仍然不打印结果。这是程序中的功能。 (如有必要,我可以提供整个功能)。所以我的问题,是我的逻辑有缺陷,还是一些小错误?

//  PURPOSE:  To send 'GOOD_PASSWORD_RESPONSE' to the client over socket file
//  descriptor 'clientFD' and return 'true' if the password 'read()' from
//  'clientFD' matches 'password', or to send 'BAD_PASSWORD_RESPONSE' to
//  the client and return 'false' otherwise.
bool didLogin(int clientFD, const char *password) {
    //  I.  Application validity check:
    printf("Process %d authenticating user . . .\n", getpid());
    fflush(stdout);

    //  II.  See if user successfully logged-in:
    //  II.A.  Obtain user's password:

    char buffer[MAX_LINE];
    size_t size = sizeof(buffer);
    read(clientFD, buffer, size);
    for (int i = 0; i < sizeof(buffer); i++) {
        printf("%c", buffer[i]);
    }
    //  II.B.  Handle when user's password does NOT match:
    if (strncmp(buffer, password, MAX_PASSWORD_LEN) != 0) {
        strncpy(BAD_PASSWORD_RESPONSE, buffer, MAX_LINE);
        printf("Process %d bad password.\n", getpid());

        return (false);
    }

    //  II.C.  If get here then user's password does match:
    strncpy(GOOD_PASSWORD_RESPONSE, buffer, MAX_LINE);
    printf("Process %d good password.\n", getpid());

    //  III.  Finished:

    return (true);
}

【问题讨论】:

  • 关于如何不使用 C++ 的优秀示例;如何不进行身份验证;如果没有适当的初始化/大小参数,如何不使用原始缓冲区;如何不将业务逻辑与协议实现(传输细节)混合。提示:read 的返回值被忽略。那可能不应该发生
  • @sehe 大声笑,“可能不会发生”;它几乎搞砸了一切:)
  • 感谢您的帮助,我知道这不是正确的方法,但我必须严格遵守提供的骨架代码。
  • 能否在代码中留下贬义的cmets来弥补:/

标签: c sockets unix


【解决方案1】:

您的代码存在很多问题。以下是我注意到的前几个:

  1. 您没有使用read() 的返回值。此返回值告诉您实际读取了多少字节。

  2. 您正在使用strncmp() 来比较最大密码长度。如果您匹配的密码短于最大值怎么办?

  3. 您似乎在几个地方混淆了strncpy()destsrc 参数。

【讨论】:

    【解决方案2】:

    您的代码摘录太短,无法全面分析,但我发现了几个可能的问题。

    1) 很明显clientFD 是一个套接字。对于套接字或任何文件描述符上的read() 请求,不能保证读取并返回请求的字节数。您的 read() 调用可能并且实际上可能会返回少于 size 字节。

    2) 您的代码假定read() 将始终返回size 读取的字节数,并将尝试打印每个字节。由于读取的字节可能更少,因此您的代码将读取并尝试打印未初始化的内存。未定义的行为。

    3) 不清楚GOOD_PASSWORD_RESPONSEBAD_PASSWORD_RESPONSE 是什么。您代码中的最后一条语句看起来是错误的。

    【讨论】:

    • .. 以及几乎不可避免地调用 str*() 对未安全地以空值终止的缓冲区(忽略读取返回的结果的副产品)。
    猜你喜欢
    • 1970-01-01
    • 2016-10-02
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多