c ++自己的套接字服务器和客户端重置连接,在8条消息之后出现错误10054和10053

时间:2017-08-22 18:23:30

标签: c++ winapi network-programming winsock2

我有一个使用winsock2的简单阻塞服务器/客户端应用程序,运行简单的异步clientHandler。我们的想法是将一个开放的连接作为机器人应用程序的keepalive标志。

套接字(客户端和服务器)的初始化并在它们之间建立连接工作正常,但是在接收到8条消息之后,接收到的那些关闭了连接(错误10053),导致发送方出现错误10054.此时它没有如果我手动发送所有消息(例如每分钟1次)或自动发送消息,则无关紧要。如果对方在消息之间进行回复并不重要,结果总是相同的。

消息由两部分组成,标题包含元信息(id,command,payloadLength,以字节为单位)和acutal payload(如果有)。令人费解的部分是:我需要发送比sizeof()更多的1个字节,否则对方不起作用。

到目前为止,我试过了:

  • 循环读取部分消息
  • 在读取/写入套接字
  • 之前查看select()的输出
  • 删除多个客户端处理程序和任何回调
  • 在相同和不同的计算机上的客户端/服务器上运行
  • 使用wireshark查看原始数据

在收件人设置RST标志的邮件限制之前,一切都看起来不错。客户端和服务器的输入/输出缓冲区设置为65kb,我的消息甚至没有接近。此外,当我每封邮件发送大量数据集(50kb)时也会发生这种情况。 8个消息后,连接就会消失。

我认为错误在套接字的配置中显而易见,但是我无法弄清楚在哪里,所以任何帮助或提示都非常适合,因为错误10054是非常暧昧的,没有很多帮助。< / p>

以下是配置服务器/客户端和接收/发送消息的一些代码段。为了便于阅读,我不在此处添加任何错误检查:

//Server

//Init
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);

struct sockaddr_in config;
config.sin_family = AF_INET;
config.sin_addr.s_addr = INADDR_ANY;
config.sin_port = htons(8080);

Socket m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//set server to a state where it accepts incoming connections
bind(m_sock, (sockaddr *)&config, sizeof(sockaddr_in));
listen(m_sock, 100);

int c = sizeof(struct sockaddr_in);
//block until new client connects
Socket m_client = accept(m_sock, (sockaddr*)client, &c));

//handling and awaiting the client messages would have happend asyncronously with the m_client pointers swapped etc.
//receive data
struct msgHeader{
    short id;
    short command;
    short payloadLength;
}


msgHeader* head = new msgHeader;
int error = 0;
do {
        err = recv(*client, (char*)head, headerSize, SD_RECEIVE);

        if (err == headerSize)
        {
            if (head->payloadLength > 0)
            {

                char* payload = new char[head->payloadLength]{0};

                err = recv(*client, payload, head->payloadLength, SD_RECEIVE); // SERVER DIES HERE!!
                if (err == head->payloadLength)
                {
          // callback is happening here
                }
        else
        {
          // error occured
        }
            }
        }
    } while (err > 0);

 delete head;
 closesocket(m_sock);
 WSACleanup();

至于客户:

WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa));


m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

m_serverConfig.sin_addr.s_addr = inet_addr("127.0.0.1");
m_serverConfig.sin_family = AF_INET;
m_serverConfig.sin_port = htons("8080");    
connect(m_sock, (struct sockaddr *)&m_serverConfig, sizeof(sockaddr_in));

std::string msg = "Hello from client";
msgHeader head{ 23, 0, msg.size() };

while(true)
{

    send(m_sock, (char*)&head, sizeof(msgHeader) + 1, SD_SEND); //this +1 offset irretates me since I'm trying to send raw data. sizeof returns 6 which is ok only if I send 7 bytes the server receives 6 thus the complete header.
    send(m_sock, msg.c_str(), msg.size() + 1, SD_SEND));  // CLIENT DIES HERE AFTER THE 8th iteration!!
}

//closesocket()... wsacleanup etc...

如果您需要整个代码,我会公开回购并发布链接。

到目前为止,感谢并希望有人有一个工作建议,在哪里寻找错误。

编辑: 客户端和服务器的代码+编译它所需的一切(阁楼项目)可以在这里找到: Code

1 个答案:

答案 0 :(得分:0)

我在这段代码中看到了很多错误,其中最少的错误是错误/错误处理不足。

尝试更多类似的内容。

服务器:

WSADATA wsa;
int res = WSAStartup(MAKEWORD(2, 2), &wsa);
if (res != 0) {
    // error handling ...
}

SOCKET m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_sock == INVALID_SOCKET) {
    // error handling ...
}

struct sockaddr_in config = {0};
config.sin_family = AF_INET;
config.sin_addr.s_addr = INADDR_ANY;
config.sin_port = htons(8080);

if (bind(m_sock, (sockaddr *)&config, sizeof(config)) == SOCKET_ERROR) {
    // error handling ...
}

if (listen(m_sock, 100) == SOCKET_ERROR) {
    // error handling ...
}

struct sockaddr_in client = {0};
int c = sizeof(client);

SOCKET m_client = accept(m_sock, (sockaddr*)&client, &c);
if (m_client == INVALID_SOCKET) {
    // error handling...
}

...

#pragma pack(push, 1) // or your compiler's equivalent
struct msgHeader {
    short id;
    short command;
    short payloadLength;
};
#pragma pack(pop)

int recvAll(SOCKET s, void *buf, int buflen)
{
    int res = recv(s, buf, buflen, MSG_WAITALL);
    if ((res != SOCKET_ERROR) || (WSAGetLastError() != WSAEOPNOTSUPP)) {
        return res;
    }
    char *pbuf = (char*) buf;
    int len = buflen;
    while (len > 0) {
        res = recv(s, buf, len, 0);
        if (res <= 0) {
            return res;
        }
        pbuf += res;
        len -= res;
    }
    return buflen;
}

msgHeader head;
std::vector<char> payload;
int res;

do {
    res = recvAll(*client, &head, sizeof(head));
    if (res <= 0) {
        if (res == SOCKET_ERROR) {
            // error handling ...
        } else {
            // client disconnected
        }
        break;
    }

    head.id = htons(head.id);
    head.command = htons(head.command);
    head.payloadLength = htons(head.payloadLength);

    if (head.payloadLength > 0)
    {
        payload.resize(head.payloadLength);

        res = recvAll(*client, &payload[0], head.payloadLength);
        if (res <= 0) {
            if (res == SOCKET_ERROR) {
                // error handling ...
            } else {
                // client disconnected
            }
            break;
        }
    }

    // callback happens here ...
    callback(&head, payload.data());

    payload.clear();
}
while (true);

closesocket(*client);

...

closesocket(m_sock);
WSACleanup();

客户端:

#pragma pack(push, 1) // or your compiler's equivalent
struct msgHeader {
    short id;
    short command;
    short payloadLength;
};
#pragma pack(pop)

bool sendAll(SOCKET s, const void *buf, int buflen)
{
    const char *pbuf = (const char*) buf;

    while (buflen > 0) {
        int res = send(s, pbuf, buflen, 0);
        if (res == SOCKET_ERROR) {
            return false;
        }
        pbuf += res;
        len -= res;
    }

    return true;
}

...

WSADATA wsa;
int res = WSAStartup(MAKEWORD(2, 2), &wsa);
if (res != 0) {
    // error handling...
}

m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_sock == INVALID_SOCKET) {
    // error handling...
}

m_serverConfig.sin_addr.s_addr = inet_addr("127.0.0.1");
m_serverConfig.sin_family = AF_INET;
m_serverConfig.sin_port = htons("8080");    

if (connect(m_sock, (struct sockaddr *)&m_serverConfig, sizeof(m_serverConfig)) == SOCKET_ERROR) {
    // error handling...
}

std::string msg = "Hello from client";
const msgHeader head{ htons(23), 0, htons(msg.size()) };

do {
    if (!sendAll(m_sock, &head, sizeof(head))) {
        // error handling...
        break;
    }

    if (!sendAll(m_sock, msg.c_str(), msg.size())) {
        // error handling...
        break;
    }
}
while (true);

closesocket(m_sock);
WSACleanup();