Linux Socket recv send 重复多次接受发送

StoneBreakee 2015-05-28 05:41:41
敲了一下linux程序设计上的例子,多客户/服务器的例子
我测试的时候用一个客户端发送‘A' 然后服务器接收后向客户端发送'B' (客户端 服务器端都是我的虚拟机)
可是我发现服务器在发送‘B'之后 还会再发送两次,求大神指教这是为什么?
代码如下
服务端 server5.c

int main(int argc,char *argv[])
{
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
memset(&server_address,0,sizeof(server_address));
memset(&client_address,0,sizeof(client_address));
int result;
fd_set readfds, testfds;
int maxfd;

//define a server socket --> bind -- >listen
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
//bind
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8888);
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
bind(server_sockfd,(struct sockaddr *)&server_address,sizeof(server_address));
//listen
listen(server_sockfd,5);

//set fd_set
FD_ZERO(&readfds);
FD_SET(server_sockfd,&readfds);
maxfd = server_sockfd + 1;

while(1)
{
char ch;
int fd,i;
int nread;
testfds = readfds;
printf("server waiting...\n");

result = select(FD_SETSIZE, &testfds, NULL, NULL, NULL);
if(result < 1)
{
printf("server5\n");
exit(EXIT_FAILURE);
}

for( fd = 0; fd < maxfd; fd++)
{
if(FD_ISSET(fd,&testfds))
{
if(fd == server_sockfd)
{
memset(&client_address,0,sizeof(client_address));
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address,&client_len);
maxfd = (maxfd > client_sockfd)?maxfd:client_sockfd+1;
FD_SET(client_sockfd,&readfds);
printf("adding client on fd %d\n\n",client_sockfd);
}
else
{
printf("fd %d\n",fd);
recv(fd,&ch,1,0);
printf("recv from client : %c\n",ch);
sleep(5);
ch++;
send(fd,&ch,1,0);
printf("send to client : %c\n\n",ch);
}
}
}
}
}

客户端 client3.c
 
int main(int argc,char *argv[])
{
int sockfd;
int len;
struct sockaddr_in address;
memset(&address,0,sizeof(address));
int result;
char ch = 'A';

sockfd = socket(AF_INET,SOCK_STREAM,0);

address.sin_family = AF_INET;
address.sin_port = htons(8888);
address.sin_addr.s_addr = inet_addr("127.0.0.1");
len = sizeof(address);

connect(sockfd,(struct sockaddr *)&address,len);

write(sockfd,&ch,1);
read(sockfd,&ch,1);
printf("char from server = %c \n",ch);
close(sockfd);
return 0;
}


运行结果
客户端
lyj@ubuntu:~/linux/20150528$ ./client
char from server = B
lyj@ubuntu:~/linux/20150528$

服务器端
lyj@ubuntu:~/linux/20150528$ ./server
server waiting...
adding client on fd 4

server waiting...
fd 4
recv from client : A
send to client : B
(怎样才能让下面的不发送呢?)
server waiting...
fd 4
recv from client : B
send to client : C

server waiting...
fd 4
recv from client : C
lyj@ubuntu:~/linux/20150528$
...全文
1034 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiqiang01234 2015-06-02
  • 打赏
  • 举报
回复
linux中的select里的坑不小心就掉进去了,比如第一参数的含义 nfds is the highest-numbered file descriptor in any of the three sets, plus 1 即最大fd加1 linux里有效率更高的poll或者epoll,为何不用呢?
StoneBreakee 2015-06-02
  • 打赏
  • 举报
回复
查到了,如果活动不是发生在服务器套接字上,那肯定是客户的活动。如果接收到的活动是close,就说明客户已经离开。 需要在服务器端代码的第58行加上

ioctl(fd,FIONREAD,&nread);
if(nread == 0)
{
    close(fd);
    FD_CLR(FD,&readfds);
}
else
{
//原服务器代码58-64行
}
dooX8086 2015-05-28
  • 打赏
  • 举报
回复
为什么会多"发送"两次产生的原因简单,但要说明这个过程有点复杂。 要知道 stdin stdout stderr 的 fd 是 0 1 2 而代码中有 for( fd = 0; fd < maxfd; fd++) ... .... ... 楼主搞错了几处 1) 搞错 select 的参数 select(FD_SETSIZE, &testfds, NULL, NULL, NULL); 这个 FD_SETSIZE 应该是 maxfd, 这个参数是说明在 FD_SET 中的 fd 的范围, 而不是个数 2) 搞错 fd 应该有一个记录所有 fd 的数组...每当有新的 fd ,就把fd 记录到数组中, fd 个数++ 如 fds[MAX_NUM]; fd_count; // fd 个数统计 select(maxfd, &testfds, NULL, NULL, NULL); for( i = 0; i < fd_count; ++i) { if(FD_ISSET(fds[i],&testfds)) { ... 楼主再查查资料吧
赵4老师 2015-05-28
  • 打赏
  • 举报
回复
不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊! http://bbs.csdn.net/topics/380167545

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧