问题描述
我正在尝试实现一个基于 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 (将#修改为@)