尝试使用C ++中的telnet发送和接收数据但是接收的数据被截断。为什么?

时间:2017-05-17 20:55:10

标签: c++ telnet

我正在使用follow函数使用telnet发送和接收数据。但是收到的数据被截断了几百个字符。为什么会发生这种情况?我该如何解决这个问题?我怀疑,数据没有从另一端“足够快”发送,我的代码认为这是telnet流的结束。如果是这种情况,我怎样才能使接收等待足够长的时间?

std::string sendTelnet(std::string str)
{
    const int default_buflen = 512;
    const char *loopback_address = "127.0.0.1";
    std::string retval;

    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
                    *ptr = NULL,
                    hints;
    char recvbuf[default_buflen];
    int iResult;
    int recvbuflen = default_buflen;

    for(int i=0; i<default_buflen; i++)
    {
        recvbuf[i] = '\0';
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        std::cerr<<"WSAStartup failed with error: " + iResult;
    }

    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(loopback_address, std::to_string((long double)jtagTerminalPort).c_str(), &hints, &result);
    if ( iResult != 0 ) {
        std::cerr<<"getaddrinfo failed with error: " + iResult;
        WSACleanup();
    }

    // Attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            std::cerr<<"socket failed with error: " + WSAGetLastError();
            WSACleanup();
        }

        // Connect to server.
        iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        std::cerr<<"Unable to connect to server!\n";
        WSACleanup();
    }

    // Send an initial buffer
    iResult = send( ConnectSocket, str.c_str(), (int)strlen(str.c_str()), 0 );
    if (iResult == SOCKET_ERROR) {
        std::cerr<<"send failed with error: " + WSAGetLastError();
        closesocket(ConnectSocket);
        WSACleanup();
    }

    //telnet_bytes_sent = iResult;

    // Receive until the peer closes the connection
    do {
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
        {
            //telnet_bytes_received = iResult;
        }
    } while( iResult == 0 );

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        std::cerr<<"shutdown failed with error: " + WSAGetLastError();
        closesocket(ConnectSocket);
        WSACleanup();
    }

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    retval = recvbuf;
    Sleep(100);
    return retval;
}

PS。截断数据的意思是 retval 返回实际通过telnet发送的截断版本。例如,如果从另一端发送的数据是“1,2,3,...,1000”,则在功能结束时, retval 将仅持有“1,2,3,......,300”。

编辑:在应用程序中,我通过telnet发送一些命令并等待响应。然后,我接收响应并相应地运行一些功能。然后我通过telnet发送下一组命令,并等待响应。等等...

2 个答案:

答案 0 :(得分:1)

你的do / while循环条件错误。它应该是while (iResult > 0)。但是你应该将它重写为while循环,以避免双重测试。

答案 1 :(得分:1)

// Receive until the peer closes the connection
do {
    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    if ( iResult > 0 )
    {
        //telnet_bytes_received = iResult;
    }
} while( iResult == 0 );

这是一种非常复杂的方法,可以从套接字中读取512个字节(如果它已被关闭,则永远阻止)。

这应该是这样的:

// Receive until the peer closes the connection
while ((iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0)) > 0)
{
    retval.append(recvbuf, iResult);
}

这将从套接字读取,直到它关闭或发生错误,并且每次都将收到的数据附加到返回字符串。