在使用C++套接字时不能接收多个消息

在使用C++套接字时不能接收多个消息,c++,sockets,C++,Sockets,我已经附上下面的代码,标题说明了一切。我能够接收一条消息,然后在第一条消息之后发送的所有其他消息都没有被发送或没有被读入 客户端,send_msg被多次调用,cppClientSocket是设置连接的构造函数 void cppClientSocket::send_msg(const char msg[], int size){ sendto(sockfd ,msg, size , 0, (struct sockaddr *)&serv, sizeof(serv)); } cpp

我已经附上下面的代码,标题说明了一切。我能够接收一条消息,然后在第一条消息之后发送的所有其他消息都没有被发送或没有被读入

客户端,send_msg被多次调用,cppClientSocket是设置连接的构造函数

void cppClientSocket::send_msg(const char msg[], int size){
    sendto(sockfd ,msg, size , 0, (struct sockaddr *)&serv, sizeof(serv));
}

cppClientSocket::cppClientSocket(int port){
    sockfd = socket(AF_INET,SOCK_DGRAM,0);

    serv.sin_family = AF_INET;
    serv.sin_port = htons(port);
    serv.sin_addr.s_addr = inet_addr("127.0.0.1");
};
服务器,cppServerSocket用于构造UDP套接字的另一端。在while循环中从另一个类连续调用Retrieve

cppServerSocket::cppServerSocket(int port){
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd<0){
        std::cout << "AN error occured when creating the socket" << std::endl;
        return;
    }

    addrlen = sizeof(remaddr); /* length of addresses */ 

    /* bind the socket to any valid IP address and a specific port */ 
    memset((char *)&myaddr, 0, sizeof(myaddr)); 
    //set to udp
    myaddr.sin_family = AF_INET;
    //host to network - long : convert a number into a 32-bit network representation.
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    //host to network - short : convert a number into a 16-bit network representation.
    myaddr.sin_port = htons(port);

    if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
        perror("bind failed"); 
        return; 
    }
}

std::string cppServerSocket::retrieve(){
    int count = recvfrom(fd, buf, BUFSIZE-1, 0, (struct sockaddr *)&remaddr, &addrlen); 
    if(!displayedError && count < 0){
        std::cout << "An Error occured: " << strerror(errno) <<  std::endl;
        displayedError = true;
        return "";
    }
    if (count >= 0){
        printf("received message: \"%s\"\n", buf);
        std::string rcv(buf,count);
        return rcv;
    }
}
谢谢你的帮助

更新 如果我修改检索,使它像一个服务器一样,只需打印它接收到的每一条消息,它就可以正常工作而不会出错

std::string cppServerSocket::retrieve(){
    for(;;){
    int count = recvfrom(fd, buf, BUFSIZE-1, 0, (struct sockaddr *)&remaddr, &addrlen); 
    if(!displayedError && count < 0){
        std::cout << "An Error occured: " << strerror(errno) <<  std::endl;
        displayedError = true;
        //return "";
    }else if (count >= 0){
        printf("received message: \"%s\"\n", buf);
        std::string rcv(buf,count);
        //return rcv;
    }
    }
    return "";
}
下面添加了用于调用原始检索方法的代码

void check_socket(cppServerSocket css){
    string temp;

    temp.append(css.retrieve());
    if(temp.size()>0){
        std::cout << temp << std::endl; //for debugging
        debug.push_back(temp);
        debug.pop_front();
    }
}
下面是main中调用check_socket方法的代码

    //code inside of main
    cppServerSocket css(3000);
    for(int i=0; i< test_time; i++){
        printScreen(test_devices, test_dev_status, false);
        t = clock();
        while(clock() - t < CLOCKS_PER_SEC){
            check_socket(css);
        }
    }
明白了

问题出在check_socketcppServerSocket css中,因为我没有通过引用传递调用我的cppServerSocket的desctructor,并且在该析构函数中我指定套接字应该关闭。因此,在收到第一条消息后,socket将被关闭。为了解决这个问题,我通过引用传递了cppServerSocket

void check_socket(cppServerSocket &css){
    string temp;

    temp.append(css.retrieve());
    if(temp.size()>0){
        std::cout << temp << std::endl; //for debugging
        debug.push_back(temp);
        debug.pop_front();
    }
}

谢谢大家的帮助

那么send_msg是如何调用的呢?我怀疑您收到了所有消息,但收到的消息以null结尾,因此printf只打印存储在buf中的第一条消息。如果你要坚持打印一个应该避免的,那么你也应该打印计数值。考虑检查RevvOutlook输出来进一步诊断这个问题。成功完成后,recvfrom应返回消息的长度(以字节为单位)。如果没有可接收的消息,则应返回0。否则,-1并设置errno以指示错误。@AdvSphere:如果没有可接收的消息,则应返回0-这不是真的。如果套接字阻塞,它将阻塞,直到收到消息。否则,它将失败,并出现EAGAIN或EWOOLDLOCK错误。recvfrom返回0的唯一时间是收到长度为0的消息,或者连接的套接字被对等方正常断开。@TylerWeiss:bad file descriptor表示传递给recvfrom的套接字描述符无效。这意味着问题不在receive本身,调用方有一个需要解决的逻辑错误fixed@AdvSphere:如我所说,UDP允许0长度的消息,因此对于有效消息,count very well可能是0。这取决于正在实施的实际协议。不要将0视为错误条件。在这种特殊情况下,这无关紧要,因为return和return stringbuf为0;将产生相同的字符串值。出于日志报告的目的,长度为0的消息仍然是有效消息。但是receive的调用者将无法区分0长度的消息和套接字错误,除非cppServerSocket将该信息存储在某个地方。实际上,我不明白这种方法的意义。只需调用您的receive方法。该函数似乎保留了过去接收到的消息的历史记录,尽管它看起来一次只允许保留一条消息,除非其他函数也正在进行调试。这比此线程中显示的要多得多。debug对象是由25个空字符串初始化的字符串对象组成的deque,因此当一条消息传入时,它会将最旧的消息推出。并插入保持大小为25的新消息。