服务器端代码:
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可能有错误,但事实并非如此......
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);
}
问题出在这两行:
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);