在 C++ 中的 UDP 套接字编程中获取“传输端点未连接”

Posted

技术标签:

【中文标题】在 C++ 中的 UDP 套接字编程中获取“传输端点未连接”【英文标题】:Getting "Transport endpoint is not connected" in UDP socket programming in C++ 【发布时间】:2012-04-12 07:04:13 【问题描述】:

我在 UDP 服务器程序中收到 Transport endpoint is not connected 错误,而我正在尝试 通过shutdown(m_ReceiveSocketId, SHUT_RDWR); 关闭套接字 以下是我的代码 sn-p:

 bool UDPSocket::receiveMessage()
    
        struct sockaddr_in serverAddr; //Information about the server
        struct hostent *hostp; // Information about this device 

        char buffer[BUFFERSIZE]; // Buffer to store incoming message
        int serverlen; // to store server address length

        //Open a datagram Socket
        if((m_ReceiveSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
        
            Utility_SingleTon::printLog(LOG_ERROR,"(%s %s %d) UDP Client - socket() error",__FILE__,__func__, __LINE__);
            pthread_exit(NULL);
            return false;
        


        //Configure Server Address.
        //set family and port
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_port = htons(m_ListeningPort);

        if (bind(m_ReceiveSocketId, (struct sockaddr *) &serverAddr,sizeof(struct sockaddr_in)) < 0 )
        
            Utility_SingleTon::printLog(LOG_ERROR,"(%s %s %d) UDP Client- Socket Bind error=%s",__FILE__,__func__, __LINE__,strerror(errno));
            pthread_exit(NULL);
            return false;
        

        //TODO Re-Route Mechanism.
        if((serverAddr.sin_addr.s_addr = inet_addr(m_ServerIPStr.c_str())) == (unsigned long)INADDR_NONE)
        
            /* Use the gethostbyname() function to retrieve */
            /* the address of the host server if the system */
            /* passed the host name of the server as a parameter. */
            /************************************************/
            /* get server address */
            hostp = gethostbyname(m_ServerIPStr.c_str());
            if(hostp == (struct hostent *)NULL)
            
                /* h_errno is usually defined */
                /* in netdb.h */
                Utility_SingleTon::printLog(LOG_ERROR,"%s %d %s %s %d", "Host Not found",  h_errno,__FILE__,__func__, __LINE__);
                pthread_exit(NULL);
                return false;
            
            memcpy(&serverAddr.sin_addr, hostp->h_addr, sizeof(serverAddr.sin_addr));
        


        serverlen = (int )sizeof(serverAddr);

        // Loop and listen for incoming message 
        while(m_RecevieFlag)
        
            int receivedByte = 0;
            memset(buffer, 0, BUFFERSIZE);
            //receive data from the server
            receivedByte = recvfrom(m_ReceiveSocketId, buffer, BUFFERSIZE, 0, (struct sockaddr *)&serverAddr, (socklen_t*)&serverlen);
            if(receivedByte == -1)
            

                Utility_SingleTon::printLog(LOG_ERROR,"[%s:%d#%s] UDP Client - receive error",__FILE__,__LINE__,__func__);
                close(m_ReceiveSocketId);
                pthread_exit(NULL);
                return false;
            
            else if(receivedByte > 0)
            
                string rMesg;
                rMesg.erase();
                for(int loop = 0; loop < receivedByte; loop++)
                    rMesg.append(1, buffer[loop]);
                Utility_SingleTon::printLog(LOG_DEBUG,"[%s:%d#%s] received message=%d",__FILE__,__LINE__,__func__, rMesg.length());
                QOMManager_SingleTon::getInstance()->setReceivedMessage(rMesg);
                raise(SIGUSR1);
            

        

        close(m_ReceiveSocketId);
        pthread_exit(NULL);
        return true;

    

任何帮助将不胜感激。 谢谢尤维。

【问题讨论】:

你不应该在调用bind之前设置serverAddr.sin_addr吗?另外,你从不在任何地方打电话给shutdown shutdown 在类的析构函数中。关于绑定我不这么认为..如果我在serverAddr.sin_addr 之后使用bind 则不起作用 如果shutdown的调用在析构函数中,那么大多数情况下你不是已经关闭了套接字吗? receiveMessage 是一个线程函数,如果我不调用shutdown 则执行卡在recvfrom 或侦听模式。所以要退出套接字的侦听模式,我使用了@ 987654334@。并在recvfrom.. 之后继续执行。 我自己并没有经常使用 UDP 套接字,但是快速的 Google 搜索表明 shutdown 不应该用于 UDP 套接字。 recvfrom 阻塞,因为套接字阻塞,要么使套接字非阻塞,要么使用标志 MSG_DONTWAITrecvfrom 【参考方案1】:

您不需要为 UDP 套接字调用 shutdown()。从手册页:

The shutdown() call causes all or part of a full-duplex connection on the socket
associated with sockfd to be shut down.

如果您在 UDP 套接字上调用 shutdown(),它将返回 ENOTCONN (指定的套接字未连接)因为 UDP 是无连接协议。

您需要做的就是关闭套接字并将套接字设置为 INVALID_SOCKET。然后在你的析构函数中检查套接字在关闭之前是否已经设置为 INVALID_SOCKET 。

【讨论】:

如果我这样做了,那么线程的执行会卡在recvfrom 并且线程永远不会退出。 @Yuvi:如果关闭套接字,recvfrom() 应该返回 ENOTSOCK。这没有发生吗? 是的,但是如何摆脱 recvfrom 阻塞套接字,你有任何参考链接吗? 我认为您需要发布更多代码。您是否试图通过在不同的线程中执行某些操作来退出 recvfrom() ?如果不是,那么您可能希望使您的套接字非阻塞和/或使用 select() 来检查套接字上可用的数据。关于 select() 和其他 tcp 细节的细节在这里:beej.us/guide/bgnet/output/html/singlepage/bgnet.html#select

以上是关于在 C++ 中的 UDP 套接字编程中获取“传输端点未连接”的主要内容,如果未能解决你的问题,请参考以下文章

套接字编程:在 UDP 上发送数据包(C++)

C++ UDP客户端/套接字编程:不能发送和接收

Linux网络(C++)——网络套接字(TCP/UDP编程模型)多进程,多线程,线程池服务器开发(画图解析)

在 C++ 套接字编程中嵌入 Python

Linux学习_UDP编程

套接字编程 --- UDP协议