服务器端代码:
dirp=opendir(path);
if(dirp==NULL)
{
strcpy(err,"error:");
strcat(err,strerror(errno));
send(fd,err,sizeof(err),0);
}
else
{
printf("nstream openedn");
while((dp=readdir(dirp))!= NULL)
{
r=send(fd,dp->d_name,100,MSG_MORE);
if(r<0)
perror("nsend:");
printf("n%s",dp->d_name);
}
}
客户:while(recv(mainsocket,lsbuf,100,0)>0)
{
printf("n %s",lsbuf);
bzero(lsbuf,sizeof(lsbuf));
}
服务器端正在打印标准输出中的所有文件名,但在客户端,客户端没有接收到最后一个文件名,程序在此时被阻塞
问题出在send
系统调用上。您使用MSG_MORE
标志调用它,这意味着更多的数据将跟随并且发送等待更多数据而不实际发送。不带此标志发送的最后一个数据块。因此,您的服务器端应该看起来像:
dp = readdir(dirp);
if (dp != NULL)
{
/* each time check whether there are more data */
while((dp_next = readdir(dirp))!= NULL)
{
r = send(fd, dp->d_name, 100, MSG_MORE);
if (r < 0) {
perror("nsend");
}
printf("n%s",dp->d_name);
dp = dp_next;
}
/* send the last or the only record */
r = send(fd, dp->d_name, 100, 0);
if (r < 0) {
perror("nsend");
}
}
解决这个问题的另一种可能是关闭与close(fd)
系统调用的连接。它在关闭连接之前发送缓冲区中的所有数据。这是一个不太干净,但更简单的解决方案。
您的客户端在 lsbuf
之前打印换行符,因此自前一个换行符以来的所有内容都丢失在您的输出缓冲区中。
四个解决方案:
- 使用
printf("%sn", lsbuf);
代替..."n %s"...
- 使用
puts(lsbuf);
,它具有相同的效果,但稍微更合适 - 在客户端循环后使用
fflush(stdout)
来刷新输出缓冲区 - 使用无缓冲输出,详见setvbuf()
请注意,这个问题似乎与网络无关(尽管我将MSG_MORE
替换为0
),它仅仅是输出缓冲的问题。
顺便说一句,我强烈建议发送strlen(dp->d_name) + 1
字节而不是100字节。这样,您就不会发送多余的字节,另一方面,如果您的目录条目碰巧大于100字节,您也不会截断输出。
同样,您的客户端和服务器都不会检查send()
/recv()
是否返回0
,这意味着连接已被远程端关闭。