为什么我从服务器端发送后,发送失败?

问题描述 投票:0回答:2

服务器端代码:

struct LoaderData
{
    uint16_t    RPC_ID;
    char timerCodec[CHAR_SINIR];
    char version[CHAR_SINIR];
    int bAccessDenied;
    int Day;
    int Hour;
};
void SendLoaderData(SOCKET socket, int RPC, const char* hash, const char* version, int bAccessDenied, const char* Name, int t, int s)
{
    LoaderData loader;
   
    loader.RPC_ID = (uint16_t)RPC;

    memcpy(loader.timerCodec, hash, sizeof(loader.timerCodec));
    memcpy(loader.version, version, sizeof(loader.version));
    loader.bAccessDenied = bAccessDenied;
   // memcpy(loader.Name, Name, sizeof(loader.Name));
    loader.Day = t;
    loader.Hour = s;

    printf("RPC: %d, timerCodec: %s, version: %s, accessCheck: %d, day: %d, hour: %d\n", loader.RPC_ID, loader.timerCodec, loader.version, loader.bAccessDenied, loader.Day, loader.Hour);
    if (send(socket, (PCHAR)&loader, sizeof(LoaderData), 0))
        printf("%d sended!\n", RPC);
    else
        printf("%d not sended!\n", RPC);
}
SendLoaderData(new_client.socket, 909, "", "", 3, "", -1, -1);  
SendLoaderData(new_client.socket, 909, "", "", 3, "", -1, -1); // I'm posting it here twice.

客户端代码:

typedef struct LoaderData
{
    uint16_t    RPC_ID;
    char timerCodec[CHAR_SINIR];
    char version[CHAR_SINIR];
    int bAccessDenied;
    int Day;
    int Hour;
};
void control()
{
        LoaderData auth;
    int iResult = recv(client.socket, (PCHAR)&auth, sizeof(LoaderData), 0);
    if (iResult != SOCKET_ERROR)
    {
           printf("RPC: %d, tCodec: %s, version: %s, accesCheck: %d, day: %d, hour: %d, version: %s\n", auth.RPC_ID, auth.timerCodec, auth.version, auth.bAccessDenied, auth.Day, auth.Hour, auth.version);
        }
}

在服务器端,我发送 SendLoaderData 两次,因为第一次发送它已损坏,第二次发送正确。某个地方有一个错误,我无法弄清楚,但我不知道错误在哪里。

result:
RPC: 17500, tCodec: ☺, version: ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠♫, accesCheck: -858993460, day: -858993460, hour: -858993460, version: ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠♫
RPC: 909, tCodec: , version: , accesCheck: 3, day: -1, hour: -1, version:

我以为LoaderData strutch可能有错误,但事实并非如此......

c++ sockets websocket serversocket
2个回答
0
投票

TCP 是一种流协议,它不保留消息边界。您需要循环调用

recv()
直到获得整个结构。

void control()
{
    LoaderData auth;
    size_t msg_size = sizeof(auth);
    size_t total_read = 0;
    PCHAR bufptr = &auth;
    size_t nread;
    while ((nread = recv(client.socket, bufptr, msg_size, 0)) < msg_size) {
        if (nread < 0) {
            perror("recv");
            break;
        } else if (nread == 0) {
            fprintf(stderr, "EOF received before auth read\n");
            break;
        }
        bufptr += nread;
        msg_size -= nread;
    }
    printf("RPC: %d, tCodec: %s, version: %s, accesCheck: %d, day: %d, hour: %d, version: %s\n", auth.RPC_ID, auth.timerCodec, auth.version, auth.bAccessDenied, auth.Day, auth.Hour, auth.version);
}

-1
投票

问题出在这两行:

memcpy(loader.timerCodec, hash, sizeof(loader.timerCodec));
memcpy(loader.version, version, sizeof(loader.version));

如果

hash
version
指向的字符串没有字符串的
timerCodec
version
字段那么大(在本例中它们不是),那么您最终会读到字符串的末尾将字符串放入不属于它们的内存中。

读取字符串的末尾(或更准确地说,在本例中包含字符串的数组),会触发未定义的行为,在您的情况下,这表现为读取垃圾数据。

初始化要发送的结构体为零,然后使用

strncpy
复制字符串。

LoaderData loader = { 0 };

...

strncpy(loader.timerCodec, hash, sizeof(loader.timerCodec)-1);
strncpy(loader.version, version, sizeof(loader.version)-1);
© www.soinside.com 2019 - 2024. All rights reserved.