Проблема при компиляции кода подключения сокета в 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 тоже проходят для подключения. надеюсь, это поможет


Если бы это было просто const Это сработало бы, но, очевидно,sockaddr и sockaddr_in различные типы.


интерфейсы сокетов, помимо того, что они очень старые, намеренно нарушаются таким образом. The sockaddr_* структуры неявно начинаются с тех же членов sockaddr таким образом, безопасно привести их к типу "base". struct sockaddr также sa_family член, поэтому вы также можете решить во время выполнения, учитывая struct sockaddr* который "производный" (хотя и не совсем) тип, чтобы бросить его.

Итак, самое маленькое, что вы можете сделать, чтобы изменить это, - это бросить struct sockaddr_in* to struct sockaddr*. Обычно это было бы очень неприятный. Но не волнуйтесь, в данном случае это делают все. Возможно, я даже предпочел бы бросить void* потому что это меньше символов, и вы получите преобразование implict в struct sockaddr*.

однако... Несколько других несвязанных моментов:

  1. gethostbyname может потерпеть неудачу. На самом деле это происходит довольно часто, скажем, когда пользователь вводит неверному адресу. Ваша программа рухнет, когда это произойдет. Проверьте, вернулся ли он NULL чтобы избежать этот.

  2. на самом деле gethostbyname был заменен getaddrinfo. Использовать это. Это даст вам независимость от протокола, чтобы вы не были привязаны к IPv4. Он также возвращает вам struct sockaddr* так что вам не нужно делать уродливый бросок.