有一个用于网络编程的函数,它的模板如下所示:
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
/* sockfd - сокет, который будет использоваться для обмена данными с сервером */
/* serv_addr содержит указатель на структуру с адресом сервера */
/* addrlen - длина этой структуры */
sockaddr 结构本身如下所示:
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
对于 sockfd 我调用 socket() 函数
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* Константа AF_INET соответствует Internet-домену */
/* SOCK_STREAM обозначает передачу потока данных с предварительной установкой соединения */
/* последний аргумент функции socket() обозначает выбор протокола, 0 - протокол выбирается по умолчанию */
对于 AF_INET 域,有一个如下所示的特殊结构:
struct sockaddr_in {
short int sin_family; // Семейство адресов
unsigned short int sin_port; // Номер порта
struct in_addr sin_addr; // IP-адрес
unsigned char sin_zero[8]; // "Дополнение" до размера структуры sockaddr
};
struct in_addr {
unsigned long s_addr;
};
在我的程序中,我使用这样的结构:
int main(void){
struct sockaddr_in test;
test.sin_family = AF_INET;
test.sin_port = htons( 80 ); /* преобразовывает число из порядка хоста в сетевой */
test.sin_addr.s_addr = inet_addr("77.37.252.217"); /* конвертирует айпи в формат long */
}
所以,现在我将调用 connect() 函数,我之前描述的模板
connect(sockfd, (struct sockaddr *)&test, sizeof(test))
实际上我的问题是 - 是否可以在 C 中将一个结构转换为另一个结构,就像我们在调用 connect () 函数时所做的那样?
ps我很抱歉我的问题延伸了这么多,只是我的良心不允许我在没有解释任何内容的情况下提出它。
ps2 如您所知,我目前正在学习网络编程,所以如果您有相关文献,所有内容都可以访问并清楚地解释,那么请在评论中指出这一点(俄语或英语 - 没关系)。提前致谢
在您的代码中,没有将一种结构转换为另一种结构,但是将指向一种结构的指针显式转换为指向另一种结构的指针。指针转换本身并没有什么不寻常的地方:使用 C 中的显式类型转换,您可以将指向任何数据类型的指针相互转换(但请参阅@wololo 在评论中的评论)。但是在这样的演员阵容之后会发生什么是一个单独的问题。
然后,通过这样的转换,在函数内部,类型结构占用的内存
connect将被重新解释struct sockaddr_in为类型结构的表示struct sockaddr。这种技术称为类型双关语。这些结构的初始字段(初始字段集)是相同的,这就是重新解释的尝试所依据的。在 C 中,这种重新解释会导致未定义的行为(违反严格的别名规则),除非在某些语言上下文中明确允许这样做。特别是,允许通过重新解释
union和重新解释为数组unsigned char。您的案例不在此列表中。您的代码是一种流行的“肮脏黑客”,从 C 的角度来看是行不通的。然后只有特定实现的功能可以使用,但这与C语言无关。这种结构技巧
struct sockaddr_in已经struct sockaddr存在了很长时间,从某种意义上说,它是网络编程的“神牛”。所以他会工作。但这只不过是那些苔藓的准标准时代的回声,当时 C 语言类似于“汇编程序”,没有人考虑过这样的问题。