简体   繁体   English

Winsock2,BitCoin Select()返回数据读取,Recv()返回0字节

[英]Winsock2, BitCoin Select() returns data to read, Recv() returns 0 bytes

I made a connection to BitCoin node via WinSock2.我通过 WinSock2 连接到比特币节点。 I sent the proper "getaddr" message and then the server responds, the replied data are ready to read, because Select() notifies this, but when I call Recv() there are 0 bytes read.我发送了正确的“getaddr”消息,然后服务器响应,回复的数据已准备好读取,因为 Select() 通知了这一点,但是当我调用 Recv() 时,读取了 0 个字节。

My code is working OK on localhost test server.我的代码在本地主机测试服务器上运行正常。 The incomplete "getaddr" message (less than 24 bytes) is NOT replied by BitCoin node, only proper message, but I can't read the reply with Recv(). BitCoin 节点不回复不完整的“getaddr”消息(小于 24 字节),只有正确的消息,但我无法使用 Recv() 读取回复。 After returning 0 bytes, the Select() still returns there are data to read.返回 0 字节后,Select() 仍然返回有数据可读。

My code is divided into DLL which uses Winsock2 and the main() function.我的代码分为使用 Winsock2 的 DLL 和 main() function。

Here are key fragments:以下是关键片段:

struct CMessageHeader
{
    uint32_t magic;
    char command[12];
    uint32_t payload;
    uint32_t checksum;
};

CSocket *sock = new CSocket();
int actual; /* Actually read/written bytes */

sock->connect("109.173.41.43", 8333);

CMessageHeader msg = { 0xf9beb4d9, "getaddr\0\0\0\0", 0, 0x5df6e0e2 }, rcv = { 0 };

actual = sock->send((const char *)&msg, sizeof(msg));

actual = sock->select(2, 0); /* Select read with 2 seconds waiting time */

actual = sock->receive((char *)&rcv, sizeof(rcv));

The key fragment of DLL code: DLL代码的关键片段:

int CSocket::receive(char *buf, int len)
{
    int actual;

    if ((actual = ::recv(sock, buf, len, 0)) == SOCKET_ERROR) {
        std::ostringstream s;

        s << "Nie mozna odebrac " << len << " bajtow.";
        throw(CError(s));
   }
   return(actual);
}

If select() reports the socket is readable, and then recv() returns 0 afterwards, that means the peer gracefully closed the connection on their end (ie, sent a FIN packet to you), so you need to close your socket.如果select()报告套接字可读,然后recv()之后返回 0,这意味着对等端优雅地关闭了他们端的连接(即,向您发送了一个FIN数据包),因此您需要关闭您的套接字。

On a side note, recv() can return fewer bytes than requested, so your receive() function should call recv() in a loop until all of the expected bytes have actually been received, or an error occurs (same with send() , too).附带说明一下, recv()可以返回比请求更少的字节,因此您的receive() function 应该在循环中调用recv()直到实际收到所有预期的字节,或者发生错误(与send() , 也)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM