Estoy creando un socket UDP (AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
) a través de Winsock y tratando de recvfrom
en este socket, pero siempre devuelve -1 y obtengo WSAEINVAL (10022). ¿Por qué?¿Debo vincular un socket UDP en mi programa cliente para recibir datos? (Siempre obtengo WSAEINVAL)
Cuando bind()
el puerto, eso no sucede, pero he leído que es muy difícil vincular el socket del cliente.
Estoy enviando datos a mi servidor, que responde, o al menos lo intenta.
Inc::STATS CConnection::_RecvData(sockaddr* addr, std::string &strData)
{
int ret; // return code
int len; // length of the data
int fromlen; // sizeof(sockaddr)
char *buffer; // will hold the data
char c;
//recv length of the message
fromlen = sizeof(sockaddr);
ret = recvfrom(m_InSock, &c, 1, 0, addr, &fromlen);
if(ret != 1)
{
#ifdef __MYDEBUG__
std::stringstream ss;
ss << WSAGetLastError();
MessageBox(NULL, ss.str().c_str(), "", MB_ICONERROR | MB_OK);
#endif
return Inc::ERECV;
}
...
Este es un ejemplo de trabajo que escribí hace unos momentos, y funciona sin la llamada a bind()
en el cliente:
#pragma comment(lib, "Ws2_32.lib")
#define WIN32_LEAN_AND_MEAN
#include <WS2tcpip.h>
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
SOCKET sock;
addrinfo* pAddr;
addrinfo hints;
sockaddr sAddr;
int fromlen;
const char czPort[] = "12345";
const char czAddy[] = "some ip";
WSADATA wsa;
unsigned short usWSAVersion = MAKEWORD(2,2);
char Buffer[22] = "TESTTESTTESTTESTTEST5";
int ret;
//Start WSA
WSAStartup(usWSAVersion, &wsa);
//Create Socket
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//Resolve host address
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_socktype = SOCK_DGRAM;
if(getaddrinfo(czAddy, czPort, &hints, &pAddr))
{
std::cerr << "Could not resolve address...\n";
std::cin.get();
return 1;
}
//Start Transmission
while(1)
{
ret = sendto(sock, Buffer, sizeof(Buffer), 0, pAddr->ai_addr,
pAddr->ai_addrlen);
if(ret != sizeof(Buffer))
{
std::cerr << "Could not send data\n";
std::cin.get();
return 1;
}
fromlen = sizeof(SOCKADDR);
ret = recvfrom(sock, Buffer, sizeof(Buffer), 0, &sAddr, &fromlen);
if(ret != sizeof(Buffer))
{
std::cout << "Could not receive data - error: " <<
WSAGetLastError() << std::endl;
std::cin.get();
return 1;
}
Buffer[ret-1] = '\0';
std::cout << "Received: " << Buffer << std::endl;
}
return 0;
}
Bueno ... Pero estoy creando un puerto, que estoy recibiendo de. No le estoy diciendo al SO que me envíe un mensaje, cuando en cualquier puerto hay datos ... Estoy haciendo una llamada para solicitarlo ... Como puedo obtener todos los datos en el puerto , esto debería ser suficiente, en mi opinión – Incubbus
Sin ver tu código, solo puedo adivinar, pero creo que estás poniendo el número de puerto en la estructura que pasas para el parámetro "de". Eso no ayuda. Ese parámetro no es leído por la pila, solo se escribe para que su programa pueda saber quién envió el datagrama. Observe que es opcional, por lo que puede pasar 0 aquí, así que de nuevo está en la misma situación que antes, donde la pila tiene que tener alguna forma de saber a qué programa entregar un datagrama basándose únicamente en el número de puerto del que vino en adelante Eso es lo que bind() hace: asocia un programa con un puerto. –
http://codepad.org/4ZmoP4K5 <- esta es la pieza del código responsable (todavía no sé cómo mostrar el código aquí, así que lo pegaré en el teclado) ... el puntero addr apunta a una valid sockaddr *, y m_InSock se inicializó con éxito ... (Como mencioné anteriormente, ya envié datos que se han recibido ...) Pero estoy seguro de que debería funcionar para el cliente sin el bind() , porque probé y ejemplo de un tutorial, que funcionó ... – Incubbus