c++ - Error de compilación de winsock, no puede encontrar las estructuras addrinfo y algunas funciones relacionadas
gcc (5)
Acabo de empezar a aprender winsock a través del libro "Guía de Beej para la programación en red". Estoy programando bajo Windows y ejecutándolo a través de gcc. Esto es solo un comienzo para escribir mi primer programa de servidor, pero me da estos errores cuando intento compilar.
/* Server */
#include <iostream>
#include <windows.h>
#include <winsock2.h>
using namespace std;
const int winsockVersion = 2;
#define BACKLOG 10
#define PORT 3000
int main(void){
WSADATA wsadata;
if (WSAStartup(MAKEWORD(winsockVersion,0),&wsadata) == 0){
struct addrinfo hints, *res;
memset(&hints,0,sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if ( getaddrinfo(NULL,PORT,&hints,&res) == 0 ){
cout<<"-Call to get addrinfo successful!." << endl;
}
cout<<"res af_family" << res->ai_family << endl;
}
//clear stuff
if( WSACleanup() != 0){
cout<<"-WSACleanup unsuccessful" << endl;
}else{
cout<<"-WSACleanup successful" << endl;
}
return 0;
}
estos son los errores que estoy recibiendo
g++ -o server.exe server.cpp -lws2_32
Process started >>>
server.cpp: In function `int main()'':
server.cpp:20: error: aggregate `addrinfo hints'' has incomplete type and cannot be defined
server.cpp:25: error: `AI_PASSIVE'' was not declared in this scope
server.cpp:27: error: `getaddrinfo'' was not declared in this scope
server.cpp:31: error: invalid use of undefined type `struct addrinfo''
server.cpp:20: error: forward declaration of `struct addrinfo''
server.cpp:54:2: warning: no newline at end of file
<<< Process finished.
¿No deberían definirse las estructuras y funciones en windows.h o winsock.h?
SOLUCIÓN
EDITAR a cualquier persona que tropieza con esto, agregue
#define _WIN32_WINNT 0x501
#include <ws2tcpip.h>
en la parte superior de su fuente si getaddrinfo dice que no se ha declarado.
Esto es trabajo para mí:
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEFAULT_PORT 80
void error_die(const char *s)
{
fprintf(stderr, "Error: %s failed with error %d/n", s, WSAGetLastError());
WSACleanup();
exit(EXIT_FAILURE);
}
int main(int argc, char **argv)
{
char response[] = "HTTP/1.1 200 OK/r/n"
"Content-Type: text/html; charset=UTF-8/r/n/r/n"
"<!DOCTYPE html><html><head><title>Hello World</title></head>"
"<body><h1>Hello world!</h1></body></html>/r/n";
char buf[4096];
int msg_len, addr_len;
struct sockaddr_in local, client_addr;
SOCKET sock, msg_sock;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) == SOCKET_ERROR)
{
fprintf(stderr, "WSAStartup failed with error %d/n", WSAGetLastError());
WSACleanup();
return -1;
}
// Fill in the address structure
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = htons(DEFAULT_PORT);
sock = socket(AF_INET, SOCK_STREAM, 0); //TCP socket
if (sock == INVALID_SOCKET)
error_die("socket()");
if (bind(sock, (struct sockaddr *)&local, sizeof(local)) == SOCKET_ERROR)
error_die("bind()");
if (listen(sock, 5) == SOCKET_ERROR) // wait for connection
error_die("listen()");
printf("Waiting for connection.../n");
while (1)
{
addr_len = sizeof(client_addr);
msg_sock = accept(sock, (struct sockaddr*)&client_addr, &addr_len);
if (msg_sock == INVALID_SOCKET || msg_sock == -1)
error_die("accept()");
printf("Accepted connection from %s, port %d/n", inet_ntoa(client_addr.sin_addr), htons(client_addr.sin_port));
msg_len = recv(msg_sock, buf, sizeof(buf), 0);
printf("Bytes Received: %d, message: %s from %s/n", msg_len, buf, inet_ntoa(client_addr.sin_addr));
msg_len = send(msg_sock, response, sizeof(response)-1 , 0);
if (msg_len == SOCKET_ERROR)
error_die("send()");
if (!msg_len)
{
printf("Client closed connection/n");
closesocket(msg_sock);
WSACleanup();
return -1;
}
closesocket(msg_sock);
}
WSACleanup();
}
MSDN dice que deberíamos #include <ws2tcpip.h>
, pero en ws2tcpip.h
encontré este fragmento de código:
#if (_WIN32_WINNT >= _WIN32_WINNT_WINXP)
/**
* For WIN2K the user includes wspiapi.h for these functions.
*/
void WSAAPI freeaddrinfo (struct addrinfo*);
int WSAAPI getaddrinfo (const char*,const char*,const struct addrinfo*,
struct addrinfo**);
int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
char*,DWORD,int);
#endif /* (_WIN32_WINNT >= _WIN32_WINNT_WINXP) */
esto significa que _WIN32_WINNT
se define más bajo que _WIN32_WINNT_WINXP
, pero cuando intenté incluir wspiapi.h
, no obtuve "no such file or directory"
. Mi conjetura es que esto es un error de MinGW, donde diferentes partes de la biblioteca tienen versiones inconsistentes. #define _WIN32_WINNT _WIN32_WINNT_WINXP
por su cuenta, antes de incluir ws2tcpip.h
Probablemente desee #include <ws2tcpip.h>
. Recuerde que antes de , Google es su amigo para este tipo de preguntas: ¡obtendrá respuestas inmediatas de MSDN!
Pude lograr que esto funcionara con los siguientes objetos, pragma y define ...
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
La lista de los incluidos necesarios para esta respuesta se muestra en un artículo de Microsoft: Winsock incluye
¡Tener cuidado! Tu inclusión está mal. El problema es que windows.h
ya incluye winsock.h
y winsock2.h
continuación, redefine algunas estructuras y funciones, lo que winsock2.h
gran cantidad de errores de compilación. Mueva windows.h
include debajo de winsock2.h
include, o simplemente elimine windows.h
include en total, winsock2.h
incluye windows.h
.