- 在内网终验证,测试粘包原因
因为我们的数据长度很短,所以不会出现什么问题,
- 我们把数据量加大,然后改为持续发送
- client和server MessageHeader.hpp 修改一下
struct LoginResult : public DataHeader
{
LoginResult()
{
dataLength = sizeof(Login);
cmd = CMD_LOGIN_RESULT;
result = 0; // 0表示正常
}
int result;
char data[1024]; // 多添加一些数据
};
- client 在while里面不停的发送数据
int main()
{
EasyTcpClient client;
client.Connect("127.0.0.1", 8888);
// 启动线程
std::thread t1(cmdThread, &client); // 这里是用来客户端输入命令的完全跟网络通信没有关系
t1.detach();
Login login;
strcpy(login.UserName, "hhhh");
strcpy(login.PassWord, "hhhhmmm");
while (client.isRun())
{
client.OnRun();
client.SendData(&login);
}
client.Close();
printf("已退出\n");
getchar();
return 0;
}
- 为了跟好的看到接收数据的长度,接收数据也稍微修改一下
int RecvData(SOCKET _sock)
{
char szRecv[1024] = {};
int nLen = (int)recv(_sock, szRecv, sizeof(DataHeader), 0);
printf("nLen=%d\n", nLen);
if (nLen <= 0)
{
printf("与服务器断开链接....\n");
return -1;
}
/*
DataHeader* header = (DataHeader*)szRecv;
recv(_sock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
OnNetMsg(header);
return 0;
*/
}
- server 也稍微修改一下
int RecvData(SOCKET _cSock)
{
char szRecv[1024] = {};
int nLen = (int)recv(_cSock, szRecv, sizeof(DataHeader), 0);
printf("nLen=%d\n", nLen);
if (nLen <= 0)
{
printf("client exit...:%d\n", _cSock);
return -1;
}
LoginResult ret;
SendData(_cSock, &ret);
/*
DataHeader* header = (DataHeader*)szRecv;
recv(_cSock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
OnNetMsg(_cSock, header);
*/
return 0;
}
- 在运行的时候就发现运行了一会之后就卡着不动了
这是因为我们发送数据都会优先把数据发送底层的缓冲区里面,
从发送端的发送缓冲区,发送的接收端的接收缓冲区,但是我们每次recv 的数据都是一个DataHeader,
int nLen = (int)recv(_cSock, szRecv, sizeof(DataHeader), 0);
并不是一次性接收的,而且缓冲区里面并不是只有一条数据,而是有多条。
假如我们发送的数据过快,(接收的速度比发送的速度还要慢),这样就会出现溢出的情况,发送端也将会无法发送数据这样就会造成网络阻塞,
我们尽可能的一次性取出缓冲区里面的数据,放在我们代码里面的缓冲区里面,自己定义的一个临时缓冲区
我们建立一个缓冲区,足够大(足够大的意思是根据我们网络传输来定的)
- 修改
int RecvData(SOCKET _sock)
{
// 定义一个足够大的缓冲区
char szRecv[102400] = {};
int nLen = (int)recv(_sock, szRecv, 102400, 0);
....
....
return 0;
}
这样就可以看到一直在正常的收发,但是这样并不是好的解决方法