使用c ++

时间:2016-11-03 22:24:01

标签: c++ sockets winsock

我目前正在学习C ++并试图理解套接字。我之前在C#和Java的高级语言中使用套接字,但在C ++中遇到了问题。

我在https://msdn.microsoft.com/en-us/library/windows/desktop/ms737593(v=vs.85).aspx处看过这个例子。

我所拥有的代码非常有用,除了有一点我不确定。当我编写其他套接字应用程序时,我通常不会收到响应,直到收到新的行字符。

我想也许C ++一次只能添加1个字符并添加到缓冲区,所以当我关闭套接字时,缓冲区将包含收到的所有内容,但它似乎是十六进制值,但是十六进制一个ascii转换器似乎打印乱码而不是套接字数据。

以下是我的代码

const int DEFAULT_BUF_LEN = 525;
    InitialiseLibrary initLibrary("tunnel.conf");
    if (initLibrary.initialise(0))
    {
        cout << "Failed to initialise library" << endl;
    }   

    BitsLibrary bitsLibrary;
    StaticSettings staticSettings(&bitsLibrary, "tunnel.conf");

    //Open a socket connection
    WSAData wsaData;
    int iResult;

    SOCKET listenSocket = INVALID_SOCKET;
    SOCKET clientSocket = INVALID_SOCKET;

    struct addrinfo *result = NULL;
    struct addrinfo hints;

    int iSendResult;
    char recvBuf[DEFAULT_BUF_LEN];
    int recBufLen = DEFAULT_BUF_LEN;

    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0)
    {
        cout << "WSAStartup Failed with error: " << iResult << endl;
        return EXIT_FAILURE;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    iResult = getaddrinfo(NULL, "500", &hints, &result);
    if (iResult != 0)
    {
        cout << "getaddrinfo failed with error: " << iResult << endl;
        return EXIT_FAILURE;
    }

    listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (listenSocket == INVALID_SOCKET)
    {
        cout << "Socket failed with error: " << WSAGetLastError() << endl;
        freeaddrinfo(result);
        WSACleanup();
        return EXIT_FAILURE;
    }

    iResult = ::bind(listenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult != 0)
    {
        cout << "bind failed with error: " << iResult << endl;
        FreeAddrInfo(result);
        closesocket(listenSocket);
        WSACleanup();
        return EXIT_FAILURE;
    }

    freeaddrinfo(result);
    iResult = listen(listenSocket, SOMAXCONN);
    if (iResult == SOCKET_ERROR)
    {
        cout << "Listen failed with error: " << WSAGetLastError() << endl;
        closesocket(listenSocket);
        WSACleanup();
        return EXIT_SUCCESS;
    }
    sockaddr_in clientAddr;
    socklen_t sin_size = sizeof(struct sockaddr_in);
    clientSocket = accept(listenSocket, (struct sockaddr*)&clientAddr, &sin_size);
    send(clientSocket, "welcome", string("welcome").length(),0);
    if (clientSocket == INVALID_SOCKET)
    {
        cout << "accept failed with error: " << WSAGetLastError() << endl;
        closesocket(listenSocket);
        WSACleanup();
        return EXIT_FAILURE;
    }

    closesocket(listenSocket);

    do {
        iResult = recv(clientSocket, recvBuf, recBufLen, 0);
        if (iResult > 0)
        {
            cout << "Bytes received: " << iResult << endl;
            cout << "Received: " << recvBuf << endl;

            iSendResult = send(clientSocket, recvBuf, iResult, 0);
            if (iSendResult == SOCKET_ERROR)
            {
                cout << "send failed with error: " << WSAGetLastError() << endl;
                closesocket(clientSocket);
                WSACleanup();
                return EXIT_FAILURE;
            }
            cout << "Bytes sent " << iSendResult << endl;
        }
        else if (iResult == 0)
        {
            cout << "Connection closing" << endl;
        }
        else
        {
            cout << "Recv failed with error: " << WSAGetLastError() << endl;
            closesocket(clientSocket);
            WSACleanup();
            return EXIT_FAILURE;
        }
    } while (iResult > 0);

    iResult = shutdown(clientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR)
    {
        cout << "shutdown failed with error: " << WSAGetLastError() << endl;
        closesocket(clientSocket);
        WSACleanup();
        return EXIT_FAILURE;
    }
    closesocket(clientSocket);
    WSACleanup();

    cout << "Message was: " << recvBuf << endl;

    return EXIT_SUCCESS;

如果我没有弄错,如果我在C#中这样做并通过telnet连接到我的套接字我可以发送Hello但是应用程序在我发送\r\n或者缓冲区已满。

然而,在我的C ++应用程序中,只要我输入H我的应用程序立即响应打印出recvBuf,其中包含H加上一堆空白字符(显示为cmd中的方块)我假设是数组缓冲区的空白部分,并发送回复。

2 个答案:

答案 0 :(得分:2)

套接字不关心换行符或空值。只有更高级别的流API才能做到这一点。重要的是recv()的返回值。这会告诉您确切地收到了多少字节。超出该计数的缓冲区中的任何内容都无效。

答案 1 :(得分:1)

在流式传输协议中,建立用于确定内容长度的协议非常有用。

例如,客户端可以发送内容长度后跟数据,服务器首先读取内容长度,然后在循环中读取套接字并缓冲数据,直到收到内容长度的字节数。 / p>