C Socket快速批量发送消息时客户端合并显示问题求助
TCP Socket消息合并显示的原因解析
问题现象
服务器通过循环快速向客户端发送多条消息时,客户端将所有消息合并为一个字符串显示;在每次write后添加sleep(1),客户端则能正常分条显示各消息。
无sleep的服务器代码
int nombreDeJoueurs = joueurs + robots; int taille; for(i = 1; i<= nombreDeJoueurs; i++){ sprintf(saisie,"Le joueur %d a %d têtes de boeufs", i, vie[i]); for (j = 1; j <= joueurs; j++){ taille = write(pollfds[j].fd,saisie,strlen(saisie)); } }
对应客户端输出
Le joueur 1 a 1 têtes de boeufsLe joueur 2 a 0 têtes de boeufsLe joueur 3 a 0 têtes de boeufsLe joueur 4 a 0 têtes de boeufs
带sleep的服务器代码
int nombreDeJoueurs = joueurs + robots; int taille; for(i = 1; i<= nombreDeJoueurs; i++){ sprintf(saisie,"Le joueur %d a %d têtes de boeufs", i, vie[i]); for (j = 1; j <= joueurs; j++){ taille = write(pollfds[j].fd,saisie,strlen(saisie)); sleep(1); } }
对应客户端输出
Le joueur 1 a 1 têtes de boeufs
Le joueur 2 a 0 têtes de boeufs
Le joueur 3 a 0 têtes de boeufs
Le joueur 4 a 0 têtes de boeufs
原因解释
这是TCP协议的字节流特性引发的「粘包」现象,核心逻辑如下:
- TCP是面向字节流的传输协议,它不会为应用层的消息自动添加边界标记。操作系统为了提升网络传输效率,会通过Nagle算法将多次小的
write操作合并成一个较大的数据包发送——当服务器快速连续调用write时,这些小数据块会被操作系统的发送缓冲区合并,一次性传输给客户端。 - 客户端的
read操作仅从接收缓冲区读取字节,无法区分这些字节对应多少个应用层消息,因此会把收到的所有字节一次性取出,表现为消息合并显示。 - 添加
sleep(1)后,两次write的间隔足够长,操作系统会判定这是独立的发送操作,不会合并缓冲区数据,客户端就能分条接收并显示每条消息。
内容的提问来源于stack exchange,提问作者Momo LaTorpie
相关产品推荐
相关产品推荐

