recvfrom() doesn't get any UDP messages - c++

I'm trying to get UDP messages that are being sent from different applications on my machine.
I created a socket and bind it to an address. When I send UDP messages using Packet Sender, nothing arrives. I tried disabling the firewall just to be sure, and still nothing happens.
I send messages to 127.0.0.1 port 8034.
I tried binding to both 127.0.0.1 and INADDR_ANY, neither work.
This is the code I'm using to listen :
SOCKET SendSocket = INVALID_SOCKET;
sockaddr_in RecvAddr, ClientAddr;
WSADATA wsaData;
struct sockaddr_in serv, client;
int l = sizeof(client);
char buffer[256];
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error: %d\n", iResult);
}
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SendSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
}
ClientAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
ClientAddr.sin_family = AF_INET;
ClientAddr.sin_port = htons(8034);
bind(SendSocket, (struct sockaddr *) &ClientAddr, sizeof(ClientAddr));
bool valid = true;
while( valid )
{
//cout << "\ngoing to recv\n";
int rc = recvfrom(SendSocket, buffer, sizeof(buffer), 0, (struct sockaddr *)&client, &l);
if (rc < 0)
{
//cout << "ERROR READING FROM SOCKET";
}
else
{
cout << "\n the message received is : " << buffer << endl;
}
DoPostDrawTask( valid );
}

Related

C++ winsock server accept function returns 10022 error

I got rid of the error, now I seem to be stuck on something else.
I have separate Winsock client and server programs on Code::Blocks. I'm trying to send a message from the client to the server, but the server program seems to freeze before the accept() function, doing nothing beyond the "Listening for incoming connections." output. The message in the client buffer never shows up in the server console.
It definitely looks like there's something going on with the accept function in the server program. That seems to be where the server program freezes. I tried to type a random cout line after that and there was no output for it.
The client seems to freeze, too, after "Message Sent." But then after a few minutes I get "recv failed" then "Reply Received" and then a line of what seems like emoticons. I think I have the image linked below.
enter image description here
Here's my client code:
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
WSADATA wsaData;
SOCKET sock;
sockaddr_in server;
char *buffer, server_reply[2000];
int recv_size;
int iResult;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
} else {
printf("WSAStartup successful!: %d\n", iResult);
}
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET){
printf("Socket not created.\n");
} else {
printf("Socket created.\n");
}
server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(80);
if(connect(sock, (SOCKADDR *)&server, sizeof(server)) != 0){
printf("Connect Error : %d" , WSAGetLastError());
} else {
printf("Connected\n");
};
buffer = "Hello there!";
send(sock, buffer, sizeof(buffer), 0);
printf("Message Sent.\n");
if((recv_size = recv(sock , server_reply , 2000 , 0)) == SOCKET_ERROR)
{
puts("recv failed");
}
puts("Reply received\n");
//Add a NULL terminating character to make it a proper string before printing
server_reply[recv_size] = '\0';
puts(server_reply);
closesocket(sock);
WSACleanup();
return 0;
}
Here's my server code:
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
WSADATA wsaData;
SOCKET server1, client;
sockaddr_in serverAddr, clientAddr;
int iResult;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
} else {
printf("WSAStartup successful!: %d\n", iResult);
}
server1 = socket(AF_INET, SOCK_STREAM, 0);
if (server1 == INVALID_SOCKET){
printf("Socket not created.\n");
} else {
printf("Socket created.\n");
}
serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888);
if(bind(server1, (SOCKADDR *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR){
printf("Bind failed. : %d" , WSAGetLastError());
} else {
printf("Bind successful.\n");
}
if(listen(server1, SOMAXCONN) != 0){
printf("Server not listening. : %d" , WSAGetLastError());
} else {
cout << "Listening for incoming connections..." << endl;
}
char buffer[1024];
int clientAddrSize = sizeof(clientAddr);
if((client = accept(server1, (SOCKADDR *)&clientAddr, &clientAddrSize)) == INVALID_SOCKET)
{
printf("Connect Error : %d" , WSAGetLastError());
} else {
cout << "Client connected!" << endl;
recv(client, buffer, sizeof(buffer), 0);
cout << "Client says: " << buffer << endl;
memset(buffer, 0, sizeof(buffer));
closesocket(client);
closesocket(server1);
cout << "Client disconnected." << endl;
}
WSACleanup();
return 0;
}
I'm trying to build a Winsock server program to use with my client program using C++ in CodeBlocks. However, the accept function returns error code 10022, which from what I've read means invalid argument. I don't see how any of my arguments in the accept function are invalid. Thanks for any help!
int main()
{
WSADATA wsaData;
SOCKET server1, client;
sockaddr_in serverAddr, clientAddr;
int iResult;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
} else {
printf("WSAStartup successful!: %d\n", iResult);
}
server1 = socket(AF_INET, SOCK_STREAM, 0);
if (server1 == INVALID_SOCKET){
printf("Socket not created.\n");
} else {
printf("Socket created.\n");
}
serverAddr.sin_addr.S_un.S_addr = inet_addr(INADDR_ANY);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888);
bind(server1, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
listen(server1, SOMAXCONN);
cout << "Listening for incoming connections..." << endl;
char *buffer;
int clientAddrSize = sizeof(clientAddr);
if((client = accept(server1, (SOCKADDR *)&clientAddr, &clientAddrSize)) == INVALID_SOCKET)
{
printf("Connect Error : %d" , WSAGetLastError());
} else {
cout << "Client connected!" << endl;
recv(client, buffer, sizeof(buffer), 0);
cout << "Client says: " << buffer << endl;
memset(buffer, 0, sizeof(buffer));
closesocket(client);
closesocket(server1);
cout << "Client disconnected." << endl;
}
WSACleanup();
return 0;
}
10022 is WSAEINVAL. Per the accept() documentation:
WSAEINVAL
The listen function was not invoked prior to accept.
The Windows Socket Error Codes documentation also says:
WSAEINVAL
10022
Invalid argument.
Some invalid argument was supplied (for example, specifying an invalid level to the setsockopt function). In some instances, it also refers to the current state of the socket—for instance, calling accept on a socket that is not listening.
OK, so lets look at your listen() call:
listen(server1, SOMAXCONN);
Nothing out of the ordinary there, assuming server1 is a valid socket (which you do check for, but you don't stop your program if socket() failed).
You are not checking for any listen() errors. Per the listen() documentation, one of the possible errors is:
WSAEINVAL
The socket has not been bound with bind.
OK, so lets look at your bind() call next:
bind(server1, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
Again, you are not checking for any bind() errors. Per the bind() documentation, one of the possible errors is:
WSAEADDRNOTAVAIL
The requested address is not valid in its context.
This error is returned if the specified address pointed to by the name parameter is not a valid local IP address on this computer.
Which you are likely to get, because you are not populating serverAddr correctly, specifically on this line:
serverAddr.sin_addr.S_un.S_addr = inet_addr(INADDR_ANY);
INADDR_ANYis defined as 0, so you are setting the S_addr field to the result of inet_addr(0), which is not valid so INADDR_NONE (0xFFFFFFFF) is returned, which again, you are not checking for. The correct assignment is to use INADDR_ANY as-is instead:
serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;
So, to wrap up, your error handling is inadequate, allowing errors to accumulate until you finally decide to do for errors all the way on accept(), which is way too late. You need to check EVERY function result for failure along the way, and STOP when you do encounter an error.
inet_addr takes const char* which represents IPv4 address in numbers and dots notation. You are passing INADDR_ANY to this function, it compiles but doesn't work as expected because INADDR_ANY equals 0, so inet_addr is called with null pointer. You should check the return code of this function, -1 indicates the error. And I assume you got it.
If you want to bind any local address you should use INADDR_ANY with htonl:
serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
This
char *buffer;
recv(client, buffer, sizeof(buffer), 0);
leads to undefined behaviour. buffer is uninitialized. This call of recv wants to read 4/8 bytes - sizeof(buffer), and write into uninitialized buffer pointer. You need to create a buffer with some initial size, for example by calling malloc/calloc:
char * buffer = malloc(10);
recv(client,buffer,10,0);
// free buffer after data was read
Just remove this line from your code:
using namespace std;
And every thing will work fine.
This error is caused because std package have a similar bind function so when you call bind it calls std::bind instead of the bind for the socket.

Can't receive UNICAST packet over WiFi using INADDR_ANY

I have a device broadcasting over ethernet, using the code below this successfully receives the packets. The device also unicasts the same packet over WiFi but this is not received (Disabling all other interfaces except WiFi in windows I get a timeout error). If I change:
address.sin_addr.s_addr = htonl(INADDR_ANY);
to
address.sin_addr.s_addr = inet_addr("192.168.0.13");
Which is the address of the wifi interface it does receive the packets. The packets over both ethernet and WiFi can be seen in WireShark, the only difference between them are the destination addresses (broadcast and unicast) and the ttl.
Here is the code:
int main()
{
int iResult;
char recv_buf[4000];
int opt = 1;
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
SOCKET handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int return_code = 0;
return_code = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char *>(&opt), sizeof(opt));
std::cout<<"socket option 1 return:" << return_code << std::endl;
DWORD tv = 100;
return_code = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<char *>(&tv), sizeof(tv));
std::cout << "socket option 2 return:" << return_code<< std::endl;
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(3000);
address.sin_addr.s_addr = htonl(INADDR_ANY);
//address.sin_addr.s_addr = inet_addr("192.168.0.13"); //this works
memset(&address.sin_zero, 0, sizeof(address.sin_zero));
std::cout << "bind return:" << bind(handle, (const sockaddr *)&address, sizeof(sockaddr_in)) << std::endl;
// Receive data until the server closes the connection
do {
Sleep(5000);
iResult = recv(handle, recv_buf, 4000, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (true);
return 0;
}

C++ winsock TCP listening

I have a software that decodes ADS-B messages (from planes) and sends results in hexadecimal to a port (47806).
I would like to listen to this port to show that data, so I wrote this :
WSADATA WSAData;
WSAStartup(MAKEWORD(2, 0), & WSAData);
SOCKET sock;
SOCKADDR_IN socket_in;
socket_in.sin_addr.s_addr = htonl(INADDR_ANY);
socket_in.sin_family = AF_INET;
socket_in.sin_port = htons(47806);
sock = socket(AF_INET, SOCK_STREAM, 0);
bind(sock, (SOCKADDR*)& socket_in, sizeof(socket_in));
listen(sock, 0);
int valid = 0;
while (TRUE) {
int size_socket_in = sizeof(socket_in);
valid = accept(sock, (SOCKADDR*)& socket_in, & size_socket_in);
if (valid != INVALID_SOCKET) {
std::cout << "OK";
}
}
This code should display "OK" each time a message is received, but it doesn't.
I can read data with a Telnet software, like PuTTY :
PuTTY telnet on port 47806
I don't understand why my code doesn't work.
Here's the right code :
WSADATA WSAData;
WSAStartup(MAKEWORD(2, 0), & WSAData);
SOCKET sock;
SOCKADDR_IN socket_in;
InetPton(AF_INET, "127.0.0.1", & socket_in.sin_addr.s_addr);
socket_in.sin_family = AF_INET;
socket_in.sin_port = htons(47806);
sock = socket(AF_INET, SOCK_STREAM, 0);
connect(sock, (SOCKADDR*)& socket_in, sizeof(socket_in));
int valid = 0;
char buffer[512] = "";
while (TRUE) {
valid = recv(sock, buffer, sizeof(buffer), 0);
if (valid != INVALID_SOCKET) {
std::cout << buffer;
}
}
My program is a client and not a server. So I have to define an IP adress with InetPton, connect to the server with connect and receive the messages with recv.
Thank you #Hasturkun and #RustyX for help and explanations.

trying to broadcast through udp socket

I've bumped into a problem with my broadcasting server. basically, I want it to send broadcasts continuously from the moment I launch it. for some reason it will not start until it receives a connection from somewhere. I must have messed up something but I can't realise what.
here is my code:
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET sock;
sock = socket(AF_INET, SOCK_DGRAM, 0);
char broadcast = 'a';
if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0)
{
perror("broadcast options");
closesocket(sock);
return 1;
}
struct sockaddr_in Recv_addr;
struct sockaddr_in Sender_addr;
int len = sizeof(struct sockaddr_in);
char recvBuff[50];
int recvBuffLen = 50;
//char sendMsg[] = "broadcast message from salam rofl";
Recv_addr.sin_family = AF_INET;
Recv_addr.sin_port = htons(PORT);
Recv_addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sock, (sockaddr*)&Recv_addr, sizeof(Recv_addr)) < 0)
{
perror("bind");
_getch;
closesocket(sock);
return 1;
}
//recvfrom(sock, recvBuff, recvBuffLen, 0, (sockaddr *)&Sender_addr, &len);
//cout << "\nreceived message: " << recvBuff;
while(1)
{
Sleep(3000);
//_getch();
getTime();
if(sendto(sock, currentTime, strlen(currentTime)+1, 0, (sockaddr *)&Sender_addr, sizeof(Sender_addr)) < 0)
{
perror("borhot send: ");
_getch();
closesocket(sock);
return 0;
}
else cout << "message sent successfully";
}
_getch;
closesocket(sock);
WSACleanup();
return 0;
basically if I remove recvfrom, it will give me a send error ("No error") which simply puzzles me. also, if I send it something with a client, it will start broadcasting, but if I connect with another client, only the first client is receiving the broadcast.
thank you in advance.
I doubt it matters but I'm trying to broadcast the current time.
You are not initializing Sender_Addr so you are not telling sendto() where to actually broadcast to.
Try this instead:
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
{
perror("socket creation");
_getch;
return 1;
}
BOOL enabled = TRUE;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&enabled, sizeof(BOOL)) < 0)
{
perror("broadcast options");
_getch;
closesocket(sock);
return 1;
}
struct sockaddr_in Sender_addr;
Sender_addr.sin_family = AF_INET;
Sender_addr.sin_port = htons(BROADCAST_PORT);
Sender_addr.sin_addr.s_addr = inet_addr("Broadcast IP Here");
struct sockaddr_in Recv_addr;
Recv_addr.sin_family = AF_INET;
Recv_addr.sin_port = htons(PORT);
Recv_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (sockaddr*)&Recv_addr, sizeof(Recv_addr)) < 0)
{
perror("bind");
_getch;
closesocket(sock);
return 1;
}
while(1)
{
Sleep(3000);
getTime();
if (sendto(sock, currentTime, strlen(currentTime)+1, 0, (sockaddr *)&Sender_addr, sizeof(Sender_addr)) < 0)
{
perror("borhot send: ");
_getch();
closesocket(sock);
return 0;
}
cout << "message sent successfully";
}
_getch;
closesocket(sock);
WSACleanup();
return 0;
Looks like your Sender_addr is never being initialized, thus when you remove the recvfrom you're getting an error, and when the recvfrom is in place it's getting populated with the address of the first client to connect (but never being updated).
If you don't know the addresses of the clients that you want to broadcast to, you'll need to setup some handshake where they send you a ping, you receive it with recvfrom, and you store their address in a list or something. Then, when you broadcast, you need to send your message to every client address in the list.

Check if TCP port is available (not listening or connected)

I use following code to check if a port is available or not:
bool ClassA::CheckPortTCP(short int dwPort , char *ipAddressStr)
{
struct sockaddr_in client;
int sock;
client.sin_family = AF_INET;
client.sin_port = htons(dwPort);
client.sin_addr.S_un.S_addr = inet_addr(ipAddressStr);
sock = (int) socket(AF_INET, SOCK_STREAM, 0);
int result = connect(sock, (struct sockaddr *) &client,sizeof(client));
// change to result == 0 -> failure in writing code too quick ;-)
if (result = 0) return true; // port is active and used
else return false;
}
The problem is if the port is opened but not connected the check failed! How can I easily examine that the port is available (not listening, not connected)?
e.g. port 21111 (output of netstat) -> my function doesn't recognize that the port is not free
TCP 0.0.0.0:21111 xxxxDUMMYxxxx:0 LISTENING
Thx
You have two errors: The first is that in the if statement you assign zero to result. The other is that connect returns -1 on failure to connect, and a non-negative value if it manages to connect.
There is also a problem that if you manage to connect, you don't close that connection.
the line client.sin_addr.S_un.S_addr = inet_addr(ipAddressStr); can not work for me. change it to:
bool CheckPortTCP(short int dwPort, char *ipAddressStr)
{
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup function failed with error: %d\n", iResult);
return false;
}
struct sockaddr_in client;
int sock;
client.sin_family = AF_INET;
client.sin_port = htons(dwPort);
client.sin_addr.s_addr = inet_addr(ipAddressStr);
sock = (int)socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
wprintf(L"ERROR: Socket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return false;
}
printf("INFO: Checking Port : %s:%d\n", ipAddressStr, dwPort);
int result = connect(sock, (struct sockaddr *) &client, sizeof(client));
if (result == SOCKET_ERROR) {
printf("ERROR: %s", WSAGetLastError());
WSACleanup();
return false;
}
else
{
WSACleanup();
closesocket(sock);
return true;
}
}