Проблема при компиляции кода подключения сокета в C
struct hostent *lh = gethostbyname(hostname);
int socketDescriptor = socket(AF_INET,SOCK_STREAM, 0);
sockaddr_in socketInfo;
memset(&socketInfo, 0, sizeof(socketInfo));
socketInfo.sin_family = AF_INET;
socketInfo.sin_addr.s_addr = ((in_addr *)(lh->h_addr))->s_addr;
socketInfo.sin_port = htons(portNumber);
connect(socketDescriptor,&socketInfo,sizeof(socketInfo));
при попытке компиляции я получаю следующую ошибку:
error: cannot convert ‘sockaddr_in*’ to ‘const sockaddr*’ for argument ‘2’ to ‘int connect(int, const sockaddr*, socklen_t)’
вещи выглядят "по книге", но мне чего-то не хватает (очевидно). Что это?
4 ответов
Я думаю, что вам не хватает struct
on sockaddr_in socketInfo
. Так и должно быть struct sockaddr_in socketInfo
.
и формы socketInfo
to struct sockaddr *
было бы неплохо.
connect(socketDescriptor,&socketInfo,sizeof(socketInfo));
должно быть
connect(socketDescriptor,(struct sockaddr *) &socketInfo,sizeof(socketInfo));
struct addrinfo *server;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));/*set hints*/
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
getaddrinfo(srvname,port,&hints,&server); /*get server ip fit args*/
sid = socket(server->ai_family, server->ai_socktype,server->ai_protocol)
connect(sid,server->ai_addr, server->ai_addrlen)
Это некоторые codesnipets, которые будут работать и с которых вы можете начать.
здесь происходит то, что я настраиваю одну структуру со всеми intel и объединяю ее с некоторой дополнительной информацией, чтобы получить один хороший все указатели fit structure тоже проходят для подключения. надеюсь, это поможет
интерфейсы сокетов, помимо того, что они очень старые, намеренно нарушаются таким образом. The sockaddr_*
структуры неявно начинаются с тех же членов sockaddr
таким образом, безопасно привести их к типу "base". struct sockaddr
также sa_family
член, поэтому вы также можете решить во время выполнения, учитывая struct sockaddr*
который "производный" (хотя и не совсем) тип, чтобы бросить его.
Итак, самое маленькое, что вы можете сделать, чтобы изменить это, - это бросить struct sockaddr_in*
to struct sockaddr*
. Обычно это было бы очень неприятный. Но не волнуйтесь, в данном случае это делают все. Возможно, я даже предпочел бы бросить void*
потому что это меньше символов, и вы получите преобразование implict в struct sockaddr*
.
однако... Несколько других несвязанных моментов:
gethostbyname
может потерпеть неудачу. На самом деле это происходит довольно часто, скажем, когда пользователь вводит неверному адресу. Ваша программа рухнет, когда это произойдет. Проверьте, вернулся ли онNULL
чтобы избежать этот.на самом деле
gethostbyname
был замененgetaddrinfo
. Использовать это. Это даст вам независимость от протокола, чтобы вы не были привязаны к IPv4. Он также возвращает вамstruct sockaddr*
так что вам не нужно делать уродливый бросок.