一个网络编程中send函数的菜鸟问题

pineapple1175 2006-12-26 04:12:24
刚接触linux网络编程,碰到一些烦人的小问题,比如说写一个测试程序,写了一个客户端和服务器端的程序,实现功能很简单,客户端发送一个字符串给服务器断,服务器断将这个字符串处理一下然后返回给客户端,在我建立了连接之后在客户端用send()之后发现服务器断接收不到字符串,后来测试了半天我在send之后马上关掉连接的socket文件sockfd服务器端马上就收到了,我想问一下是不是每次send之后一定要关掉连接的sockfd才能再服务器端才能接收到客户端发送的字符串的??如果是这样我要再后面的程序中接收来自服务器端回送的字符串之后应该怎么办呢?总不能说我重新建立一个连接吧.......郁闷中.
...全文
263 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
pineapple1175 2006-12-27
  • 打赏
  • 举报
回复
to:zengg82()
谢谢
pineapple1175 2006-12-27
  • 打赏
  • 举报
回复
to:sqs570408(流氓总督)
谢谢你的意见,我试过了,行的
zengg82 2006-12-27
  • 打赏
  • 举报
回复
你在getbuf函数中用select控制sockfd的阻塞。

可以像这样:
fd_set rd;
struct timeval time;
time.tv_sec = 10;
time.tv_usec = 0;
FD_ZERO(&rd);
FD_SET(sockfd,&rd);

index=0;

n=0;
while(1)
{
if(select(sockfd+1,&rd,NULL,NULL,&time) > 0)
n=recv(sockfd,tempbuf,MAXLEN,0);
else
break;
if(n == 0)
break;
if(n == -1)
break;
printf("recv buf len %d\n",n);

for(i=0;i<n;i++)

buf[index++]=tempbuf[i];
printf("recv buf finish and the buf is %s\n",buf);

}
因为socket默认是阻塞的(你也不要把它设成非阻塞的),所以它一直阻塞在循环的判断里(其实这也不能叫死循环),所以一直都没有出这个循环,只有当client端关闭socket时会通知servic(通过信号来通知),然后recv就会结束,这样你的程序才跳出这个循环。

但要改为非阻塞的,recv就会返回-1。当然你也可以改成非阻塞的,然后用select控制它。
sqs570408 2006-12-27
  • 打赏
  • 举报
回复
程序已经调试完了,好用。
你的服务器端程序中的getbuf函数中的接收消息别用循环
while( (n=recv(sockfd,tempbuf,MAXLEN,0))>0 )
改为
if ( (n=recv(sockfd,tempbuf,MAXLEN,0))>0 )
就可以了

结果请回复,谢谢!
sqs570408 2006-12-27
  • 打赏
  • 举报
回复
学习!
sqs570408 2006-12-27
  • 打赏
  • 举报
回复
客气。

学习!
pineapple1175 2006-12-26
  • 打赏
  • 举报
回复
我还是把原代码贴上吧,其实我已经把它贴到一个帖子上了,就是没人来理我:(
---------------服务器端-----------------
#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<sys/socket.h>
#include<sys/wait.h>

#include<arpa/inet.h>

#include<netinet/in.h>

#include<string.h>



#define PORT 9877

#define BUFLEN 1024

#define MAXLEN 128

#define BACKLOG 10



void getbuf(char *buf,int sockfd);

void reversebuf(char *buf);



/*

//main

*/

int main(int argc,char *argv[])

{

/*init serversockfd,clientsockfd;*/

int listenfd,connectfd;

int clientaddrlen;

int status;

struct sockaddr_in clientaddr,serveraddr;

char buf[BUFLEN];

char *welcome="Connect to server successful.Welcome!!!\n";

pid_t pid;

if( (listenfd=socket(AF_INET,SOCK_STREAM,0))<0 )

{

/*create socket if failure exit*/

perror("create socket error!");

exit(1);

}

/*init serveraddr*/

bzero(&serveraddr,sizeof(serveraddr));

serveraddr.sin_family=AF_INET;

serveraddr.sin_port=htons(PORT);

serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);

/*bind port and serveraddr to listenfd*/

if( bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(struct sockaddr))<0 )

{

perror("bind port failure!");

exit(1);

}

if( listen(listenfd,BACKLOG)<0 )

{

perror("listen error");

exit(1);

}

for(;;)

{

clientaddrlen=sizeof(clientaddr);

if( (connectfd=accept(listenfd,(struct sockaddr *)&clientaddr,&clientaddrlen))<0 )

{

perror("accept from client failure!");

exit(1);

}
printf("Received client: %s request\n",inet_ntoa(clientaddr.sin_addr));

if( (pid=fork())<0 )

{

perror("fork error");

exit(1);

}

else if( pid==0 )

{
getbuf(buf,connectfd);

printf("Get client string: %s\n",buf);
if( send(connectfd,welcome,strlen(welcome),0)<0 )

{

perror("send welcome failure");

exit(1);

}
reversebuf(buf); /*reverse buf*/

if( send(connectfd,buf,strlen(buf),0)<0 ) /*send reversed string to client*/

{

perror("send reversed string error");

exit(1);

}
close(connectfd);
exit(0);

}
close(connectfd);

}

close(connectfd);

close(listenfd);

exit(0);

}





/*

//getbuf

*/

void getbuf(char *buf,int sockfd)

{

char tempbuf[MAXLEN];

int n;

int i,index;

index=0;

n=0;

while( (n=recv(sockfd,tempbuf,MAXLEN,0))>0 )

{

for(i=0;i<n;i++)

buf[index++]=tempbuf[i];

}

buf[index]='\0';

if(n<0)

{

perror("recv error");

exit(1);

}

}





/*

//reversebuf

*/

void reversebuf(char *buf)

{

char c;

int i,len;

len=strlen(buf);

int mid=(int)len/2;

for(i=0;i<mid;i++)

{

c=buf[i];

buf[i]=buf[len-1-i];

buf[len-1-i]=c;

}

}



----------------客户端---------------------
#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<sys/socket.h>

#include<arpa/inet.h>

#include<netinet/in.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<string.h>

#include<sys/time.h>



#define PORT 9877

#define BUFLEN 1024

#define MAXLEN 128

#define MAXSLEEP 128





int connect_retry(int sockfd,struct sockaddr *addr,socklen_t alen);

void printbuf(int sockfd);

void getbuf(int sockfd,char *buf);



int main(int argc,char *argv[])

{

int sockfd;

struct sockaddr_in serveraddr;

int addrlen;

char *str="hello";

pid_t pid;

/*char buf[BUFLEN];*/

if(argc!=2)

{

printf("usage:clienttest ipaddress\n");

exit(1);

}

if( (sockfd=socket(AF_INET,SOCK_STREAM,0))<0 )

{

perror("create socket error");

exit(1);

}

bzero(&serveraddr,sizeof(serveraddr));

serveraddr.sin_family=AF_INET;

serveraddr.sin_port=htons(PORT);

inet_pton(AF_INET,argv[1],&serveraddr.sin_addr);

addrlen=sizeof(struct sockaddr);

if( connect_retry(sockfd,(struct sockaddr *)&serveraddr,addrlen)<0 )

{

printf("connect to server error\n");

exit(1);

}

if(send(sockfd,str,strlen(str),0)<0)

{

perror("send str to server error");

exit(1);

}
fflush(sockfd);

printbuf(sockfd);

close(sockfd);

exit(0);

}





/*

//connect_retry

*/

int connect_retry(int sockfd,struct sockaddr *addr,socklen_t alen)

{

int nsec;

for(nsec=1;nsec<MAXSLEEP;nsec<<=1)

{

if( connect(sockfd,addr,alen)==0 )

return 0;

if(nsec<=MAXSLEEP/2)

sleep(nsec);

}

return (-1);

}





/*

//printbuf

*/

void printbuf(int sockfd)

{

char buf[BUFLEN];

fd_set rfd;

struct timeval timeout;

timeout.tv_sec=10;

timeout.tv_usec=0;

FD_ZERO(&rfd);

FD_SET(sockfd,&rfd);

switch(select(sockfd+1,&rfd,NULL,NULL,&timeout))

{

case -1:

perror("select error");

exit(1);

case 0:

printf("receive data from server timeout");

break;

default:

getbuf(sockfd,buf);

printf("Get string from server: ");

printf("%s",buf);

break;

}

printf("\n");

}





/*

//getbuf

*/

void getbuf(int sockfd,char *buf)

{

char tempbuf[MAXLEN];

int i,n,index;

n=0;

index=0;

while( (n=recv(sockfd,tempbuf,MAXLEN,0))>0 )

{

for(i=0;i<n;i++)

buf[index++]=tempbuf[i];

}

buf[index]='\0';

if(n<0)

{

perror("recv data from server error");

exit(1);

}

}



hyg2008 2006-12-26
  • 打赏
  • 举报
回复
这是因为你recv的时候给的缓冲区长度太大,而你又是用的阻塞方式,它会一直等到数据够填整个缓冲区了才返回。
如果是非阻塞方式就不会出现这个问题了。
playmud 2006-12-26
  • 打赏
  • 举报
回复
解释一下为什么你关掉socket就能收到,
这是因为关掉连接会给对端发送一个连接终止的信号,这样对端的接受函数就会知道,从而产生一个终端,终止read操作。这样你的read就返回了,看上去的现象就是你这边一关闭,那边就收到了,其实数据是已经发送过去了的。
playmud 2006-12-26
  • 打赏
  • 举报
回复
或者每次读取一个字符,直到读完为止,这样看看。
playmud 2006-12-26
  • 打赏
  • 举报
回复
了解了,不是发送的问题,而是接受的问题.
你用的什么?用非阻塞的读取函数。
pineapple1175 2006-12-26
  • 打赏
  • 举报
回复
to:playmud((猪头流氓)(抵制日货)(问君何处去,天上人间))
fflush()这个我也试过了,不行。
pineapple1175 2006-12-26
  • 打赏
  • 举报
回复
楼上那位兄弟,说的是,可是为什么我建立了连接之后服务器端收不到来自客户端发送过来的字符串呢,这个可是一个很奇怪的问题,我试过的,如果在send之后直接关掉sockfd服务器端就可以收到字符串了,这就麻烦了,如果每次send之后都要这样的话连什么连接都不用谈了。郁闷啊.......
playmud 2006-12-26
  • 打赏
  • 举报
回复
根据你描述的问题来看,应该是缓冲的问题,你可以每次sendto以后fflush(sockfd)一下看看
awjx 2006-12-26
  • 打赏
  • 举报
回复
建立连接后,可以永远不关闭socket,如果不掉线,永远可以send,此谓长连接!

23,116

社区成员

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

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