send() 调用仅适用于套接字中的 telnet

Posted

技术标签:

【中文标题】send() 调用仅适用于套接字中的 telnet【英文标题】:send() call only works for telnet in socket 【发布时间】:2021-03-31 17:44:50 【问题描述】:

我正在使用带有 c++ 的 Windows 套接字。在接下来的通话中,我试图向刚刚连接的套接字回复一条消息。

我尝试使用 C++ 中的虚拟客户端进行连接。它会连接,但 recv() 不会收到任何东西。

然后我尝试使用 telnet,它立即工作,正如我想要的那样。

SOCKET s = accept(ls, (sockaddr*)&clientSin, &s_len);

            if (s == INVALID_SOCKET) 
                cerr << "Error in accept call: " << WSAGetLastError();
            
            else 
                cout << "Connection accepted at , socket no. :" << s << endl;
                //adding to list of incoming sockets
                inactiveList.push_back(s);
                //send message to client requesting credentials
                char buff[10];
                
                // the character 'x' is a code to the client to provide the server with the credentials
                buff[0] = 'x';
                buff[1] = '\0';
                //send(s, buff, 2, 0);
                if (send(s, "From Vic: ", 10, 0) == INVALID_SOCKET)
                
                    int errorcode = WSAGetLastError();
                    cerr << "send to client failed: " << errorcode << endl;
                    closesocket(s);
                    continue;
                
                Sleep(1000);
                if (send(s, "From Vic: ", 10, 0) == INVALID_SOCKET)
                
                    int errorcode = WSAGetLastError();
                    cerr << "send to client failed: " << errorcode << endl;
                    closesocket(s);
                    continue;
                
                
            

recv 码是:

tnb = 0;
    while ((nb = recv(s, &buff[tnb], LINESZ - tnb, 0)) > 0)
    
        tnb += nb;
    
    /* If there was an error on the read, report it. */
    if (nb < 0)
    
        printf("recv failed: %d\n", WSAGetLastError());
        return 1;
    
    if (tnb == 0)
    
        printf("Disconnect on recv");
    
    /* Make the response NULL terminated and display it.  Using C output */
    printf("tnb = %d\n", tnb);
    buff[tnb] = '\0';
    puts(buff);

【问题讨论】:

您的send 代码可能没问题。请出示您的recv 代码。 与您的问题无关。失败的send 调用不会返回 INVALID_SOCKET,而是返回 SOCKET_ERROR。他们可能都是一样的。 你应该在你的 recv 循环中明确地检查tnb &gt;= LINESZ 是否发生了中断。在 Windows 上,长度是有符号的,但在其他任何地方,recv 的 len 参数都是无符号的。 另外,在打印之前不要忘记 null 终止 buff。否则,您可能会打印出比该行实际收到的更多的风险。 我的精神力量表明 LINESZ 比你实际发送的要大得多。因此,它只是永远停留在循环中,等待更多数据。 【参考方案1】:

把我所有的cmets变成一个答案。

我怀疑你的 recv 循环会永远持续下去,因为你没有发送足够的数据来让它跳出循环。

改变这个:

while ((nb = recv(s, &buff[tnb], LINESZ - tnb, 0)) > 0)

    tnb += nb;

对此:(请注意,我为数组 buff 分配了 +1)

char buff[LINESZ+1]; // +1 for null terminator
buff[0] = '\0';
tnb = 0;
while (tnb < LINESZ)

    nb = recv(s, &buff[tnb], LINESZ-tnb, 0);
    if (nb < 0)
    
        printf("Error on socket: %d\n", (int)WSAGetLastError());
        break;
    
    else if (nb == 0)
    
        printf("Remote socket closed\n");
        break;
    

    printf("Received: %d bytes\n", (int)nb);

    tnb += nb;
    buff[tnb] = '\0'; // null terminate the end of the buffer so it will print reliably

【讨论】:

这行得通,但是有没有一种方法可以在不关闭套接字的情况下跳出循环。我的服务器发送消息,但客户端处于循环状态,即使没有更多消息,客户端也会继续监听。 您需要将其构建到您自己的协议中。在消息之间添加您自己的分隔符。例如,扫描您收到的缓冲区并查找'\n' char

以上是关于send() 调用仅适用于套接字中的 telnet的主要内容,如果未能解决你的问题,请参考以下文章

Rhino Mocks 存根和模拟仅适用于接口?

在 UDP 套接字上使用 write()/read()?

c TCP中的套接字我如何测试连接?

FxCop 中的自定义规则仅适用于由特定类型的方法调用的方法

Firebase Api Key 仅适用于 iOS

.send() 和 .sink() 似乎不再适用于 Xcode 11 Beta 5 中的 PassthroughSubject