问个recv函数的问题

uusunny 2008-05-26 08:19:16
想实现通过socket来发送命令,即服务器端每次收到命令处理后继续等待客户端发送来的命令,用了seng、recv函数,这两函数都是阻塞的。
客户端有程序:
......
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1)
{
perror("connect");
exit(1);
}
if ((sendbytes=send(sockfd,buf,6,0))==-1)
{
perror("send");
exit(1);
......
服务器端程序:
if ((new_sock = accept(serv_sock, (struct sockaddr *)&their_addr, &sin_size)) == -1)
{
exit_fatal("accept");
}
......
while(1)
{
......
if((recvbytes = recv(new_sock,buf,6,0))==-1)
{
exit_fatal("recv");
}
......
}
......
但最后测试的结果却是客户端发送一次后,如命令字是AAAAAA,服务器端却会连续的调用recv函数接受到AAAAAA
即最后结果是
AAAAAA
AAAAAA
AAAAAA
AAAAAA
......
怎么会出现这种情况呢,如何修改才能使服务器端收到一个AAAAAA后等待客户端继续发送命令呢。
谢谢
...全文
504 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
gezichong 2008-05-30
  • 打赏
  • 举报
回复
服务器的接受程序的些问题:

while(1)
{
if ((recvbytes = recv(client_fd,buf,15,0))==-1)
{
break;
}
printf("recvbytes= %d\n",recvbytes);
printf("received a connection : %s\n",buf);
}
close(sockfd); //close在while循环外面


根据TCP/IP协议讲:客户端发送完消息后,调用close关掉socket,则向服务器端发一个FIN(原因你这里只有一个socket);而服务器在循环接受,由于每次接受到的都是FIN,则服务器每次都显示接受到了0字节,

正确的程序如下:

while(1)
{
if ((recvbytes = recv(client_fd,buf,15,0))==-1) //-1:说明出错
{
break;
}
if(recvbytes==0)//必须对0进行处理,这里是说明服务器接受到了客户端的关闭socket消息FIN,则服务器也应该关闭socket
{break;}//跳出循环
printf("recvbytes= %d\n",recvbytes);
printf("received a connection : %s\n",buf);
}
close(sockfd);




libingwai 2008-05-28
  • 打赏
  • 举报
回复
用下面的这个RECV函数应该可以,需要指定等待时间
int recvlen(int iSocketID,char *buf,int length){/***接收指定长度数据***/
int nTotalLen;
int nSubLen;
int nShouldLen;
int iRc;
iRc=nTotalLen=nSubLen=nShouldLen=0;
nShouldLen=length;
while(nTotalLen<nShouldLen){
iRc=tcp_waitfor_read(iSocketID,WAITSECONDS);
if(iRc<=0){
printf("%s,%d,等待接收数据错误,errno=%d\n",__FILE__,__LINE__,errno);
return(-1);
}
nSubLen=recv(iSocketID,buf+nTotalLen,nShouldLen-nTotalLen,0);
if(nSubLen<=0){
printf("%s,%d,接收数据错误,errno=%d\n",__FILE__,__LINE__,errno);
return(-1);
}
nTotalLen+=nSubLen;
}
return(0);
}

static int tcp_waitfor_read(int iSocketID,int waitseconds){
fd_set rmask;
struct timeval time_out,*ptr;
int iRc;
FD_ZERO(&rmask);
FD_SET((unsigned int)iSocketID,&rmask);
if(waitseconds>=0){
time_out.tv_sec = waitseconds ;
time_out.tv_usec = 0;
}else{
time_out.tv_sec = 0 ;
time_out.tv_usec = 200000;
}
ptr = &time_out;
iRc=0;
/*循环等待,直到socket空闲可读*/
while(1){
iRc = select(iSocketID+1,&rmask,0,0,ptr);
if(iRc>0){
break;
}else if(iRc==0){
/*超时*/
break;
}else{
if(errno==EINTR)
continue;
else
break;
}
}
return iRc;
}
uusunny 2008-05-27
  • 打赏
  • 举报
回复
[root@(none) mnt]# ./server
socket success,socketfd=3
recvbytes= 12
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
recvbytes= 0
received a connection : /dev/video0
......


这就是运行结果
uusunny 2008-05-27
  • 打赏
  • 举报
回复
我重写了个类似的小程序验证,发现现象一样,代码如下,请高手指教阿
//server:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define SERVPORT 7070
#define BACKLOG 10
int main()
{
struct sockaddr_in server_sockaddr,client_sockaddr;
int sin_size,recvbytes;
int sockfd,client_fd;
char *buf=(char *)malloc(15);
if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
}
printf("socket success,socketfd=%d\n",sockfd);
server_sockaddr.sin_family=AF_INET;
server_sockaddr.sin_port=htons(SERVPORT);
server_sockaddr.sin_addr.s_addr=INADDR_ANY;
bzero(&(server_sockaddr.sin_zero),8);
if (bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr))==-1)
{
perror("bind");
exit(1);
}
if (listen(sockfd,BACKLOG)==-1)
{
perror("listen");
exit(1);
}
if ((client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_size))==-1)
{
perror("accept");
exit(1);
}
while(1)
{
if ((recvbytes = recv(client_fd,buf,15,0))==-1)
{
break;
}
printf("recvbytes= %d\n",recvbytes);
printf("received a connection : %s\n",buf);
}
close(sockfd);
}


//client:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define SERVPORT 7070
#define MAXDATASIZE 100
int main(int argc,char *argv[])
{

int sockfd,sendbytes;
char *buf="/dev/video1";
struct hostent *host;
struct sockaddr_in serv_addr;
if (argc<2)
{
fprintf(stderr,"Please enter the server's hostname\n");
exit(1);
}
if ((host=gethostbyname(argv[1]))==NULL)
{
perror("gethostbyname");
exit(1);
}
if ((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit(1);
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
serv_addr.sin_addr=*((struct in_addr *)host->h_addr);
bzero(&(serv_addr.sin_zero),8);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1)
{
perror("connect");
exit(1);
}
if ((sendbytes=send(sockfd,buf,12,0))==-1)
{
perror("send");
exit(1);
}
close(sockfd);
}



运行后客户端发送一次就退出了,可服务器端会连续不断的接受,不知如何改进才能让recv阻塞阿
uusunny 2008-05-27
  • 打赏
  • 举报
回复
按上面的方法也不行阿
我发现第一次正确接受后
第二第三.......接收到的recvbytes都是0,就这么一直循环,不是说recv是阻塞型的吗,怎会有这种情况
gezichong 2008-05-27
  • 打赏
  • 举报
回复
确信客户端只发送了一次AAAAAAA?
dthxman 2008-05-27
  • 打赏
  • 举报
回复
同楼上,或者把你的exit_tatal("recv")换成break;也行。
pottichu 2008-05-27
  • 打赏
  • 举报
回复
接收前先清理一下 buf

memset(buf, 0, 6);
if((recvbytes = recv(new_sock,buf,6,0))==-1)
{
exit_fatal("recv");
}
......
mymtom 2008-05-27
  • 打赏
  • 举报
回复
检查recvbytes的值
linqzly 2008-05-27
  • 打赏
  • 举报
回复
man recv

RETURN VALUE
These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0
when the peer has performed an orderly shutdown.
对方已经关了socket,所以你这个应该是正常的.你不能要求你的服务器还是一直阻塞的当你的客户端都已经关掉了socket的时候.

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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