【问题标题】:return from read in connected udp sockets in c从c中连接的udp套接字中读取返回
【发布时间】:2013-04-10 19:28:37
【问题描述】:

我编程 UDP 客户端/服务器模型,这个应用程序的主要功能是客户端插入目录路径,然后服务器会将提供的目录的内容返回给客户端,所以这个客户端代码:

#include "cliHeader_UDP.h"

int
main(int argc, char **argv)
{
    int                 sockfd;
    struct sockaddr_in  servaddr;

        /*Error checking for providing  appropirate port# */
    if(argc<3 )  
        err_quit("Error,no port provided, please enter the port#:22011 \n");

    portno=atoi(argv[2]);


    for(;;)
    {
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(portno);
        Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

        sockfd = Socket(AF_INET, SOCK_DGRAM, 0);        
        dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr));
    }
    exit(0);
}

**//and here is the dg_cli implemntation :**


void
dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
    int n;
    char    sendline[MAXLINE], recvline[MAXLINE + 1];

    Connect(sockfd, (SA *) pservaddr, servlen);
    for(;;)
    {
         bzero(&sendline, sizeof(sendline));
         printf("please enter Directory Name :\n");
         Fgets(sendline, MAXLINE, fp);

        /*To check if the supplied name ended with \n in sendline buffer */
        if((p = strchr(sendline, '\n'))) *p = 0; 

        write(sockfd, sendline, strlen(sendline));
        printf("test for write\n");                     
**Line 31.......:**     while ( (n=read(sockfd, recvline, MAXLINE)) )
                {
                    if(n<0)
                    perror("Error");

                    printf("recvline is: %s\n",recvline);
                    printf("n========%d\n",n);



                }
            printf("exit from read While\n");
            recvline[n] = 0;    /* null terminate */



    }
}

第 31 行的问题...是第一次运行,因为我希望客户端插入 DIR 路径,因此服务器将返回路径的内容,但是当用户需要再次插入路径时,它仍然在 for 循环中阻塞读取并且不从 for 循环返回, 那么当缓冲区的内容结束时如何从for循环返回时设置条件,如TCP中的EOF

【问题讨论】:

    标签: c sockets unix blocking udpclient


    【解决方案1】:

    正如您所注意到的,UDP 中没有“连接”的概念——即使您调用了connect(2)——所以当通信结束时read 无法返回0。有办法解决这个问题:

    • 当输出结束或其他一些特殊标记时,让服务器发送一条长度为 0 的消息
    • 让客户端分析输入并以某种方式检测到它已结束

    这两种方法在实践中都有点脆弱:想象一下如果“输出结束”消息太多会发生什么。因此,您还必须针对这种情况进行准备,并且可能会添加超时(例如,查找 SO_RCVTIMEO)。

    【讨论】:

    • thnx 在高级。但我已经知道在 UDP 中没有连接,只是我用它来选择异步错误,所以在我的情况下,如何让客户端分析数据并检测到发送数据的结束?????跨度>
    • @user2103930 我不确定我明白你在问什么。
    • 你说“让客户端分析输入并以某种方式检测到它已经结束”怎么做我已经尝试过标志,for循环,....等但我没有成功也许你是经验在那, 告诉我提示 os smthin 那样...
    • @user2103930 也许服务器可以在输出完成后发送一个双换行符?你试过 0 长度的数据报吗?
    【解决方案2】:

    我尝试了类似的东西看看: 服务器端部分代码:

    //at server side Read the directory contents
                printf("The contents of [%s] is :\n",mesg);
                bzero(&mesg, sizeof(mesg));
                while( (dptr = readdir(dp)) !=NULL ) 
                {
                    printf(" \n[%s] \t",dptr->d_name);
                    //report(dptr->d_name, &status_buf);
                    sprintf(mesg,"%s",dptr->d_name);
    
                    if((dptr = readdir(dp)) ==NULL)     
                    {
                        bzero(&mesg, sizeof(mesg));
                        sprintf(mesg,"%c",'!');
                        Sendto(sockfd, mesg, sizeof(mesg), 0, pcliaddr, len);
                    }
    
                    Sendto(sockfd, mesg, sizeof(mesg), 0, pcliaddr, len);
    
                }
                // Close the directory stream
                closedir(dp);
    
    
    //and at the client side : 
    
    flag=1;             
            while ( (n=read(sockfd, recvline, MAXLINE)) )
                    {
                        if(n<0)
                        perror("Error");
    
                        printf("recvline is: %s\n",recvline);
                        flag=flag+1;
                        printf("Flag now is :%d\n",flag);
                        printf("n========%d\n",n);
                             bzero(&recvline, sizeof(recvline));
                        if(recvline[0]=='!')
                            return;
    
    
                    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-22
      • 2019-03-24
      • 1970-01-01
      • 2012-01-30
      • 2010-12-22
      • 2018-10-31
      • 2012-06-17
      相关资源
      最近更新 更多