免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: pineapple1175
打印 上一主题 下一主题

一个网络编程中send的菜鸟问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-12-26 16:14 |显示全部楼层 |倒序浏览
刚接触linux网络编程,碰到一些烦人的小问题,比如说写一个测试程序,写了一个客户端和服务器端的程序,实现功能很简单,客户端发送一个字符串给服务器断,服务器断将这个字符串处理一下然后返回给客户端,在我建立了连接之后在客户端用send()之后发现服务器断接收不到字符串,后来测试了半天我在send之后马上关掉连接的socket文件sockfd服务器端马上就收到了,我想问一下是不是每次send之后一定要关掉连接的sockfd才能再服务器端才能接收到客户端发送的字符串的??如果是这样我要再后面的程序中接收来自服务器端回送的字符串之后应该怎么办呢?总不能说我重新建立一个连接吧.......郁闷中.

论坛徽章:
0
2 [报告]
发表于 2006-12-26 17:17 |显示全部楼层

回复 2楼 linyue 的帖子

兄弟,还是不行啊,谁和我说说,郁闷死了要

论坛徽章:
0
3 [报告]
发表于 2006-12-26 17:50 |显示全部楼层

回复 4楼 mq110 的帖子

客户端:
#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);

        }

}

               


服务器端:
#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;

        }

}

论坛徽章:
0
4 [报告]
发表于 2006-12-26 22:26 |显示全部楼层

回复 6楼 linyue 的帖子

才出去看了两个小时的书就有这么多回帖了,真是感激啊,再这之前的另外一个帖子上发了半天到现在也没人来理我
我去试了一下把while循环去掉直接send了一下就直接用recv接收就能正常运行了,不过apue2上面也明确说了: Since we're using a SOCK_STREAM socket, we can't be guaranteed that we will read the entire string in one call to recv, so we need to repeat the call until it returns 0.我那段while循环也是参照apue2上面的,假如我发送比较多的内容的话还是要用这种模式来接收的,还有就是nonblocking这种状态和blocking这种状态到底有什么区别??如果我非要用while循环接收那么代码要怎么改呢???

论坛徽章:
0
5 [报告]
发表于 2006-12-26 22:27 |显示全部楼层
真感谢大家的回复,受益非浅啊,谢谢谢谢

论坛徽章:
0
6 [报告]
发表于 2006-12-26 22:33 |显示全部楼层
原帖由 linyue 于 2006-12-26 20:30 发表
我晕,你server的程序里那个getbuf函数里有个while循环不停recv,而你用的又是阻塞模式,所以你收到第一个字符串"hellp"以后,recv又阻塞在while那儿了,当然看上去就跟没受到东西一样了,其实已经收到 ...


哈哈,其实我原本来是没用fflush的因为刚看了书说用这函数能把缓冲里的数据送到kernal里面,一开始以为数据没真正发送出去,于是就用了,至于warning当时看到了,但没心情卡管那个了,^_^

论坛徽章:
0
7 [报告]
发表于 2006-12-26 22:42 |显示全部楼层
原帖由 linyue 于 2006-12-26 20:30 发表
我晕,你server的程序里那个getbuf函数里有个while循环不停recv,而你用的又是阻塞模式,所以你收到第一个字符串"hellp"以后,recv又阻塞在while那儿了,当然看上去就跟没受到东西一样了,其实已经收到 ...


用了recv第一次接收了5个字节之后第二次还会接收时返回值还会>0吗??如果是的话就代表还有数据可以接收啊?这和blocking状态有关??
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP