Umar Farooq
Umar Farooq

Reputation: 416

recv() return -1 on peer disconnect for non blocking tcp ip socket

I am using tcp/ip socket and i have read about recv function . So whenever a peer is disconnected recv return 0 as per documentation but on windows it is not returnig zero instead it return -1 and the value in errono is 0 I am unable to understand why it is doing so. The same code is working perfect in linux.

// some headers i used
#ifdef _WIN32
/* See http://stackoverflow.com/questions/12765743/getaddrinfo-on-win32 */
#    ifndef _WIN32_WINNT
#        define _WIN32_WINNT 0x0501 /* Windows XP. */
#    endif
#    include <Ws2tcpip.h>
#    include <winsock2.h>

#    ifdef _MSC_VER
#        pragma comment(lib, "Ws2_32.lib")
#    endif

#    define SHUT_RDWR SD_BOTH
#else
/* Assume that any non-Windows platform uses POSIX-style sockets instead. */
#    include <arpa/inet.h>
#    include <fcntl.h>
#    include <netinet/in.h>
#    include <netinet/tcp.h>
#    include <sys/socket.h>
#    include <unistd.h>

#    define NO_ERROR 0
#    define INVALID_SOCKET -1
#    define SOCKET_ERROR -1
#endif

// MSG_DONTWAIT is not available on some platforms, if it doesn't exist define it as 0
#if !defined(MSG_DONTWAIT)
#    define MSG_DONTWAIT 0
#endif
//

std::vector<std::string> Peer::read(const int length)
{
    static std::vector<char> tempRecvBuf(2 * 1000000);
    tempRecvBuf.clear();
    int recv = ::recv(m_socket.resource(), &tempRecvBuf[0], length, MSG_DONTWAIT);

    if (recv == SOCKET_ERROR ) {
        if (errno == WSAECONNRESET) {
            return {};
        }
        else {
            return {};
    }

    if (recv == 0) {
        // Connection is no longer valid, remote has been disconnected
        m_connected = false;
        this->m_master->events()->onPeerDisconnect()->trigger(this);
        this->m_master->peers()->remove(this);
        return {};
    }

Upvotes: 1

Views: 406

Answers (1)

Andreas Wenzel
Andreas Wenzel

Reputation: 24726

According to this page of the Microsoft Windows Sockets documentation, the function recv will return 0 on graceful shutdown and SOCKET_ERROR (which is probably defined as -1) on an error (including an abortive shutdown). As stated in the documentation, you must call WSAGetLastError to obtain the error code. It is not stored in errno.

This behavior differs from the POSIX version of the function, which does set errno when an error occurs.

Upvotes: 4

Related Questions