2

我有 UDP 客户端和服务器的编写代码片段。我使用相同的端口进行发送和接收。我的问题是客户端有很多消息丢失,所以有人可以帮我优化我的代码,这是我的 UDP 客户端代码:

#define SERVERIP "192.168.170.155"
#define SERVERPORT 5000
#define DEVICE_SEND_PORT 5000
#define DEVICE_RECEIVE_PORT 5000
#define BUFFERSIZE 2048

/**For socket file descriptor identification*/
#define S1READY 0x01

int m_SendSocketId;
int m_ReceiveSocketId;
int msgcount;
int socketbuffsize = 1*1024*1024;


/**
* FUNCTION NAME : waitToRead
* Implementation of select and non-blocking socket mechanism
* @param socket Socket that needs to be in select and non blocking mode
* @return Returnd the file descriptors which, returned by select function
*/
int waitToRead(int socket)
{
    fd_set fds;
    struct timeval timeout;
    int rc; // number of file descriptor returned
    int result; // result 
    int fd; // file descriptor

    fd=fcntl(socket,F_GETFL,0);
    fcntl(socket,F_SETFL,fd | O_NONBLOCK);

    // Set time limit. 
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    // Create a descriptor containing our sockets.
    FD_ZERO(&fds);
    FD_SET(socket, &fds);
    rc = select(sizeof(fds)*8, &fds, NULL, NULL, &timeout);
    if (rc==-1)
    {
        printf("[%s:%d#%s] Select Failed\n",__FILE__, __LINE__,__func__);
        return -1;
    }

    result = 0;
    if (rc > 0)
    {
        if (FD_ISSET(socket, &fds))
            result |= S1READY;
    }
    return result;
}
/**
* FUNCTION NAME : receiveMessage
* This function opens particular port that is defined in the 
* Configuration file, and listens on that port.
* @return if there'll be any issue in listening, then it will return 
* false otherwise it will return true.
*/
bool receiveMessage()
{
    struct sockaddr_in serverAddr; //Information about the Device UDP Server
    struct sockaddr_in client_addr; // Information about Qgate Server
    char buffer[BUFFERSIZE]; // Buffer to store incoming message
    int addr_len; // to store client address length 
    int serverlen; // to store server address length
    int sockResult; // to store result given by waitToRead
    int optval = 1;
    int receivedByte = 0;

    //Open a datagram Socket
    if((m_ReceiveSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        printf("[%s:%d#%s] UDP Client - socket() error\n",__FILE__, __LINE__,__func__);
        return false;
    }

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


    setsockopt(m_ReceiveSocketId, SOL_SOCKET,SO_REUSEADDR, &optval, sizeof(optval));

    /*if (setsockopt(m_ReceiveSocketId, SOL_SOCKET, SO_RCVBUF, &socketbuffsize, sizeof(socketbuffsize)) == -1) 
    {
        printf("Recieve Socket memory Allocation fail\n");
    }*/

    if((serverAddr.sin_addr.s_addr = INADDR_ANY) == (unsigned long)INADDR_NONE)
    {

        printf("[%s:%d#%s] Host Not found(%d)\n",__FILE__, __LINE__,__func__,h_errno);
        close(m_ReceiveSocketId); // close the socket
        return false;
    }

    if (bind(m_ReceiveSocketId, (struct sockaddr *) &serverAddr,sizeof(struct sockaddr_in)) < 0 )
    {
        printf("[%s:%d#%s] UDP Client- Socket Bind error=%s\n",__FILE__, __LINE__,__func__,strerror(errno));
        close(m_ReceiveSocketId); // close the socket
        return false;
    }

    serverlen = (int )sizeof(serverAddr);
    addr_len = sizeof(struct sockaddr); 
    // Loop and listen for incoming message 
    while(1)
    {
        //wait at select to, read
        sockResult = waitToRead(m_ReceiveSocketId);

        if(sockResult == S1READY)
        {
            receivedByte = read(m_ReceiveSocketId,buffer,BUFFERSIZE);   
            buffer[receivedByte] = '\0';

            if(receivedByte == -1)
            {
                printf("[%s:%d#%s] UDP Client - receive error", __FILE__,__LINE__,__func__);
                close(m_ReceiveSocketId);
                return false;
            }
            else if(receivedByte > 0)
            {
                //printf("[%s:%d#%s] received message = %d bytes\n",__FILE__,__LINE__,__func__,(int)strlen(buffer));
                printf("count: %d, buffer %s \n", msgcount++, buffer);
            }
        }

        memset(buffer, 0, BUFFERSIZE);
        fflush(stdout);
    }

    close(m_ReceiveSocketId); // close the socket
    printf("[%s:%d#%s] Recieve socket closed:%s\n",
                            __FILE__, __LINE__,__func__, strerror(errno));
    return true;
}


bool sendMessage(char *message)
{
    struct sockaddr_in  serverAddr; //Information about the server
    struct sockaddr_in deviceAddr; //Device UDP Client Address for sending message
    int optval = 1;

    //Open a datagram Socket
    if((m_SendSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        printf("[%s:%d#%s] UDP Client - socket() error\n",__FILE__, __LINE__,__func__);
        return false;
    }

    // Clear out the device struct
    memset(&deviceAddr, 0x00, sizeof(struct sockaddr_in));

    deviceAddr.sin_family = AF_INET;
    deviceAddr.sin_port = htons(DEVICE_SEND_PORT);

    setsockopt(m_SendSocketId, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

    /*if (setsockopt(m_SendSocketId, SOL_SOCKET, SO_SNDBUF, &socketbuffsize, sizeof(socketbuffsize)) == -1) 
    {
        printf("send Socket memory Allocation fail\n");
    }*/

     if((deviceAddr.sin_addr.s_addr = INADDR_ANY) == (unsigned long)INADDR_NONE)
    {
        // in netdb.h 
        printf("[%s:%d#%s] Host Not found(%d)\n",__FILE__, __LINE__,__func__,  h_errno);
        close(m_SendSocketId); // close the socket
        return false;
    }

    if (bind(m_SendSocketId, (struct sockaddr *) &deviceAddr,sizeof(struct sockaddr_in)) < 0 )
    {
        printf("[%s:%d#%s] UDP Client- Socket Bind error=%s\n",__FILE__, __LINE__,__func__,strerror(errno));
        close(m_SendSocketId); // close the socket
        return false;
    }


    // Clear out the server struct
    memset(&serverAddr, 0x00, sizeof(struct sockaddr_in));

    //Configure Server Address.
    //set family and port
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(SERVERPORT);
    //serverAddr.sin_addr.s_addr = htonl(39898);

    if((serverAddr.sin_addr.s_addr = inet_addr(SERVERIP)) == (unsigned long)INADDR_NONE)
    {
        printf("[%s:%d#%s] Host Not found %d\n",__FILE__, __LINE__,__func__,h_errno);
        close(m_SendSocketId);
        return false;
    }

    // Send data to the server.
    if( sendto(m_SendSocketId, message,strlen(message) ,0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0 )
    {
        printf("[%s:%d#%s] UDP Client - sendto() error=%s \n",__FILE__, __LINE__,__func__,strerror(errno));
        close(m_SendSocketId);  
        return false;
    }

    close(m_SendSocketId);
    return true;
}

int main ()
{
    int loop;
    char str[10];
    msgcount = 1;   
    pthread_t receiveThread;

    if(pthread_create(&receiveThread, NULL,(void *)&receiveMessage, NULL) != 0)
    {
        printf("[%s:%d#%s] thread create Failed(%s)\n",
            __FILE__, __LINE__,__func__, strerror(errno));
        return false;
    }

    for(loop =0; loop < 1000; loop++)
    {
        sprintf(str,"%4d",loop);
        sendMessage(str);   
    }

    pthread_join(receiveThread, NULL);  
    return 0;
}

这是临时 UDP 服务器代码,它接收几乎 90% 以上的消息并发送相同的消息,但 udpclient 无法接收消息。

int main()
{
        int sock;
        int addr_len, bytes_read, bytes_send;
        char recv_data[1024];
        int i;
        int count=0;
        struct sockaddr_in server_addr , client_addr;


        if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
            perror("Socket");
            exit(1);
        }

        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(5000);
        server_addr.sin_addr.s_addr = INADDR_ANY;
        bzero(&(server_addr.sin_zero),8);

        //client_addr.sin_family = AF_INET;

        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

        if (bind(sock,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)
        {
            perror("Bind");
            exit(1);
        }

        addr_len = sizeof(struct sockaddr);

        printf("\nUDPServer Waiting for client on port 5000");
        fflush(stdout);

    while (1)
    {
        bytes_read = recvfrom(sock,recv_data,1024,0,(struct sockaddr *)&client_addr, (socklen_t *)&addr_len);
        recv_data[bytes_read] = '\0';


        if(recv_data[0]!=0x07)
        {
            recv_data[0] = 0x09;
            //client_addr.sin_port = htons(51254);

            bytes_send = sendto(sock, recv_data, bytes_read, 0, (struct sockaddr *)&client_addr, (socklen_t)sizeof(client_addr));
            if(bytes_send < 0 )
            {
                perror("send to ");
            }
            printf("\nNumber  %d", ++count);
            memset(&recv_data, 0x00, 1024);

        }
        else
        {
            printf("Received Keep ALive\n");        
        }
        memset(&client_addr, 0x00, sizeof(struct sockaddr_in));

        fflush(stdout);

    }
    return 0;
}

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

4

2 回答 2

2

您的代码与 UDP 丢弃数据包无关,除非您发送数据包的速度对于网络或接收器而言太快。UDP不可靠。它丢弃数据包。如果您的应用程序协议不需要丢弃数据包,则您必须通过基于 ACK 或基于 NACK 的重试协议在该级别构建可靠性。

或者在这种情况下像其他人一样使用 TCP。

于 2012-05-22T10:22:14.107 回答
-1

问题出在 sendMessage 函数中,这里我每次需要发送消息时都在重新创建套接字,我认为这需要时间。我还不知道哪个调用被阻塞,但是发送套接字可以解决我的问题。现在消息的丢弃率只有 20% 到 30%。

于 2012-05-22T12:39:43.323 回答