gpt4 book ai didi

c - 调用 getaddrinfo() 后 sockaddr 值意外更改

转载 作者:行者123 更新时间:2023-11-30 19:42:04 26 4
gpt4 key购买 nike

我正在编写一个 UDP 客户端程序。我想将套接字绑定(bind)到客户端计算机上的给定端口,以便所有发送始终使用相同的端口。我使用 getaddrinfo 获取服务器的 sockaddr,并执行相同的操作来获取传递给 getaddrinfo 调用的 sockaddr。但是,在第二次调用 getaddrinfo 之后,服务器计算机的地址发生了变化,我最终将数据包从客户端计算机发送到客户端计算机本身。

以下代码是重现错误的独立示例:

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_HOST "www.google.com"
#define UDP_PORT "4000"

static struct sockaddr_in *destination_addr = NULL;
static int client_port;

int main(){

uint8_t bytes[5] = { 0xaa, 0xab, 0xac, 0xad, 0xaf}; //some data to send

uint16_t length = 5;
int status;


//initialize socket and bind
if (destination_addr == NULL) {
struct addrinfo hints;
struct addrinfo *servinfo, *p;
srand(time(NULL));
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;

if ((status = getaddrinfo(SERVER_HOST, UDP_PORT, &hints, &servinfo)) != 0) {
printf("Unable to send UDP. Reason: %s", gai_strerror(status));
return 0;
}


for (p = servinfo; p != NULL; p = p->ai_next) {
if (p->ai_addr != NULL)
destination_addr = (struct sockaddr_in *) p->ai_addr;
}
client_port = 1027 + rand()%50000;
freeaddrinfo(servinfo);
printf("Created destination_addr with IP %s\n", inet_ntoa(destination_addr->sin_addr));
}


int send_socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (send_socket_fd == -1) {
printf("Unable to create UDP socket. Reason: %s", strerror(errno));
return 0;
}
printf("IP after socket creation is %s\n", inet_ntoa(destination_addr->sin_addr));
int yes = 1;
if (setsockopt(send_socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (int)) == -1) {
perror("setsockopt");
return 0;
}
printf("IP after sockopt is %s\n", inet_ntoa(destination_addr->sin_addr));

// bind to local address
char str_client_port[6];
snprintf(str_client_port, 5, "%d", client_port);
struct addrinfo *source_addr_info;
struct addrinfo hints;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;


// ***** destination_addr changes after this call *****
getaddrinfo (NULL, str_client_port, &hints, &source_addr_info);


printf("IP after getaddrinfo is %s\n", inet_ntoa(destination_addr->sin_addr));
bind(send_socket_fd, source_addr_info->ai_addr, source_addr_info->ai_addrlen);
printf("IP after binding is %s\n", inet_ntoa(destination_addr->sin_addr));

// send
int bytes_sent = sendto(send_socket_fd, bytes, length, 0, (struct sockaddr *)destination_addr, sizeof *destination_addr);
printf("Sent to IP %s\n", inet_ntoa(destination_addr->sin_addr));
if (bytes_sent != length){
if (bytes_sent == -1){
printf("UDP send failed. Reason: %s", strerror(errno));
}
else {
printf("UDP: not all bytes could be sent.");
}
}


close(send_socket_fd);
return 1;

}

在我的机器上执行该程序生成的输出是:

Created destination_addr with IP 64.233.167.105
IP after socket creation is 64.233.167.105
IP after sockopt is 64.233.167.105
IP after getaddrinfo is 0.0.0.0
IP after binding is 0.0.0.0
Sent to IP 0.0.0.0

我对 C 套接字编程相当陌生,并且很确定我犯了一些愚蠢的错误,但是在谷歌搜索并尝试了很多事情之后,我仍然坚持这一点。任何想法?

最佳答案

已解决。正如 @molbdnilo 指出的,该错误是由调用 freeaddrinfo 引起的。为了解决这个问题,我现在复制 p->ai_addr 指向的值,以便在释放时它不会丢失。我替换为:

if (p->ai_addr != NULL)
destination_addr = (struct sockaddr_in *) p->ai_addr;

if (p->ai_addr != NULL){
destination_addr = malloc(sizeof *destination_addr);
memcpy(destination_addr, (struct sockaddr_in *)p->ai_addr, sizeof *p->ai_addr);
}

并且成功了。

关于c - 调用 getaddrinfo() 后 sockaddr 值意外更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32860395/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com