微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

UDP 客户端发送到一个端口并从另一个端口接收

如何解决UDP 客户端发送到一个端口并从另一个端口接收

我正在尝试实现一个基于 UDP 协议的简单客户端/服务器回显应用程序。此应用程序的要求之一是客户端在一个端口上发送消息,但通过另一个端口从服务器接收响应。

为了说明起见,假设客户端出站端口(即服务器入站端口)为 0.0.0.0:9999,客户端入站端口(服务器出站端口)为 0.0.0.0:10000

到目前为止,我设法为客户端和服务器实现了代码(使用 sendto()recvfrom() 方法),当消息发送到/从同一个 UDP 端口接收时,该代码起作用。但是,当客户端成功地将数据发送到端口 (9999) 时,recvfrom() 方法(在端口 10000 侦听)被阻止,就好像服务器没有响应一样。但是,服务器似乎可以工作,因为服务器端的 sendto() 方法返回发送的消息的长度,地址和端口对应于服务器出站端口 0.0.0.0:10000

如果我在客户端代码MSG_DONTWAIT 中设置了非阻塞标志 (recvfrom()),错误信息是 Resource temporarily unavailable

我在此附上 udp 客户端的代码,以防您发现一些明显的错误。我完全是网络新手,所以我可能在这里遗漏了一些非常明显的东西。


struct udp_client{
    int socket;
    struct sockaddr_in sockaddr;

    int socket_inbound;
    struct sockaddr_in sockaddr_inbound;

    char server_ip_addr[32];

    char message[UDP_BUFFER_LENGTH];
};


static int setup_udp_client_socket(const char* server_ip_addr,int port,struct sockaddr_in* addr)
{

    int socket_id = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if (socket_id >= 0) {

        memset((char *)addr,sizeof(*addr));
        addr->sin_family = AF_INET;
        addr->sin_port = htons(port);

        int res = inet_aton(server_ip_addr,&addr->sin_addr); /* no need to connect() */
        if (res == -1) {
            close(socket_id);
            socket_id = -1;
        }

    }

    fprintf(stderr,"setup udp_client_socket [ %s ] [ %d ] [ %d ]\n",server_ip_addr,port,socket_id);
    return socket_id;

}


udp_client_t* udp_client__create(const char* server_ip_addr,int port)
{
    udp_client_t* self = calloc(1,sizeof(udp_client_t));
    if (self) {

        self->socket_inbound = -1;
        strncpy(self->server_ip_addr,sizeof(self->server_ip_addr) - 1);

        self->socket = setup_udp_client_socket(self->server_ip_addr,&self->sockaddr);
        if (self->socket == -1)
            udp_client__destroy(&self);

    }
    return self;

}

int udp_client__destroy(udp_client_t** p_self)
{
    if (!p_self)
        return 1;
    
    udp_client_t* self = *p_self;
    if (!self)
        return 1;

    if (self->socket >= 0)
        close(self->socket);


    if (self->socket_inbound >= 0)
        close(self->socket_inbound);

    free(*p_self);
    p_self = 0;

    return 0;
}

int udp_client__set_inbound(udp_client_t* self,int inbound_port)
{
    if (!self)
        return 1;

    if (self->socket_inbound != -1) {
        /* if already allocated,close it first */
        close(self->socket_inbound);
    }

    self->socket_inbound = setup_udp_client_socket(self->server_ip_addr,inbound_port,&self->sockaddr_inbound); 
    if (self->socket_inbound == -1)
        return 1;
    else
        return 0; 

}

int udp_client__send(udp_client_t* self,const char* message,char* reply,size_t reply_length)
{
    if (!self || !message || !reply)
        return 1;

    memset(reply,reply_length);

    socklen_t socklen = sizeof(self->sockaddr);

    int in_socket = self->socket;
    struct sockaddr_in server_addr = self->sockaddr;
    if (self->socket_inbound >=0) {
        in_socket = self->socket_inbound;
        server_addr = self->sockaddr_inbound;
    }

    fprintf(stderr,"Socket default %d,inbound %d\n",self->socket,in_socket);

    int res = sendto(self->socket,message,strlen(message),(struct sockaddr *) &self->sockaddr,socklen);
    if (res != -1) {

        socklen_t addr_len = sizeof(server_addr);
        fprintf(stderr,"Listening to socket %d address --> %s:%d\n",in_socket,inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port));
        res = recvfrom(in_socket,reply,reply_length - 1,/*MSG_DONTWAIT*/ 0,(struct sockaddr *)&server_addr,&addr_len);
        if (res == -1) {
            perror("Error recvfrom: ");
        }
        fprintf(stderr,"Reply received from socket %d (%s:%d): [ %s ]\n",ntohs(server_addr.sin_port),reply);
    }

    return (res != -1);

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。