Winsock UDP broadcast packets not sent - c++

I'm encountering a strange issue using winsock when multiple network adapters are active but then one is disconnected.
This is the basic scenario:
Wifi and Ethernet are active and connected
Launch app, send UDP broadcast and receive response
Unplug Ethernet, restart app and try to send again - Nothing is sent (Wireshark shows nothing, seems Windows is dropping them before they get to NIC?)
Disable the disconnected Ethernet adapter and try again - sends fine over Wifi and gets response.
Now this is a very specific scenario but I believe it's happening in other cases, this is just the only way I know to reproduce it every time.
The following is a code snippet of the UDP send, for this example assume dstAddrStr is 192.168.1.255
struct sockaddr_in sa_remote;
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET) {
printf("Error creating socket: %ld\n", WSAGetLastError());
}
int enable = 1;
if ((setsockopt(sock,
SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof(enable))) == -1) {
printf("Error enabling broadcasts: %ld\n", WSAGetLastError());
}
const MIB_IPADDRROW & row = iptbl->table[i];
uint32 ipAddr = ntohl(row.dwAddr);
uint32 netmask = ntohl(row.dwMask);
uint32 baddr = ipAddr & netmask;
if (row.dwBCastAddr) baddr |= ~netmask;
char dstAddrStr[32]; Inet_NtoA(baddr, dstAddrStr);
memset(&sa_remote, 0, sizeof(struct sockaddr_in));
sa_remote.sin_family = AF_INET;
sa_remote.sin_addr.s_addr = inet_addr(dstAddrStr);
sa_remote.sin_port = htons(_DST_PORT);
if (sendto(sock, dpString, strlen(dpString), 0, (struct sockaddr *)&sa_remote, sizeof(struct sockaddr_in)) < 0){
printf("UDP send error Error: %ld", WSAGetLastError());
break;
}

Related

C++ TCP Server (Winsock) Connecting (invalid client) Instantly Then Closes

Edit: Working on a solution - turns out googling 204.204.204.204 gets me further than more descriptive requests.
Honestly. Wits end. I have no idea how I can spend an entire day doing something that took 10 minutes in Flask (Server) and Javascript (client). I need this to run in C++ and allow a client to connect via BlueStacks' port on the same machine. The client is unimportant because I can't even get that far.
I've tried WinSocks, I've tried WxWidget's networking implementation, I've even tried some random C++ wrapper thing. All of them failed (typically within the EXAMPLE! As in, copy paste and errors everywhere). So I ultimately went back to WinSockets and followed a tutorial on YouTube.
int ServerStuff() {
WSADATA WsData;
WORD ver = MAKEWORD(2, 2);
int wsOK = WSAStartup(ver, &WsData);
if (wsOK != 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
return false;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Quitting");
return false;
}
//Bind the ip and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; //Could also use inet_pton
bind(listening, (sockaddr*)&hint, sizeof(hint));
//Tell winsock the socket is for listening
listen(listening, SOMAXCONN);
//Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
//if (clientSocket == INVALID_SOCKET) {
// wxLogMessage("Client Invalid Socket");
// return false;
//}
char host[NI_MAXHOST]; //Client's remote name
char service[NI_MAXHOST]; //Service (port) the client is connected on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
}
else {
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
wxLogMessage(host);
int wut = client.sin_port;
wxString mystring = wxString::Format(wxT("%i"), wut);
wxLogMessage("Connected on port");
wxLogMessage(mystring);
//wxLogMessage(to_string(ntohs(client.sin_port)));
}
wxLogMessage("Got this far somehow");
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//while loop: accept and echo message back to client
char buf[4096];
while (true)
{
ZeroMemory(buf, 4096);
//Wait for client to send data
int bytesReceived = recv(clientSocket, buf, 4096, 0);
if (bytesReceived == SOCKET_ERROR) {
//wxLogMessage("ERROR in recv");
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
send(clientSocket, buf, bytesReceived + 1, 0);
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
ServerStuff();
//Close(true);
}
On the YouTube video ("Creating a TCP Server in C++" - not allowed to post links) this works! The command window opens, is blank infinitely until he connects a client and then the client sends a message and the server replies with the same exact message in return.
Not mine. Mine just rushes through everything and then closes. My log used to immediately quit on the commented code where it states the client socket is invalid so I commented it out. Now my output is:
204.204.204.204
Connected on port
52428
Got this far somehow
I don't know what to do. I'm just trying to send data over a same-machine TCP connection. I'm baffled as to how this is so difficult. It seems like some random process is immediately trying to connect as a client to my server ? But why is it allowed to connect on port 52428 when I'm explicitly hosting on 54000?
My goal:
Start Server
Connect to Server using a Java App within BlueStacks
Send data from Server to Client
It makes more sense for the computer to be the server because there will be multiple BlueStacks instances and I'd prefer to not have to "spawn" multiple programs / servers for what I'm doing.
I see a few mistakes in your socket code.
not calling WSACleanup() if WSAStartup() is successful and then something goes wrong afterwards.
not calling closesocket() if socket() is successful and then something goes wrong afterwards.
not zeroing out the sockaddr_in that you pass to bind(). Random bytes in the struct can cause bind() to fail.
ignoring the return values of bind(), listen(), accept(), and send().
not treating the return value of getnameinfo() correctly. It returns 0 on success, not failure.
sending +1 extra byte back to the client than you received from the client. If the client sends fewer bytes than your buffer can hold, that extra byte would be 0x00 due to your ZeroMemory() call. But if the client actually sends enough bytes to completely fill your buffer, then you would send an extra byte from memory that you do not own. If you really want to send a null terminator after everything you echo, do so explicitly. Otherwise, a true echo server should only send back exactly what it receives, no more, no less.
Try something more like this:
void ServerStuff() {
WSADATA WsData;
int ret = WSAStartup(MAKEWORD(2, 2), &WsData);
if (ret != 0) {
wxLogMessage("Can't initialize Winsock! Error: %d", ret);
return;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Error: %d", WSAGetLastError());
WSACleanup();
return;
}
//Bind the ip and port to a socket
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.s_addr = INADDR_ANY; //Could also use inet_pton
ret = bind(listening, (sockaddr*)&hint, sizeof(hint));
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't bind socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Tell winsock the socket is for listening
ret = listen(listening, SOMAXCONN);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't listen on socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Wait for a connection
sockaddr_in client = {};
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET) {
wxLogMessage("Can't accept a client! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
char host[NI_MAXHOST] = {}; //Client's remote name
ret = getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, NULL, 0, 0);
if (ret != 0) {
wxLogMessage("Can't get client name info! Error: %d", ret);
inet_ntop(AF_INET, &(client.sin_addr), host, NI_MAXHOST);
}
wxLogMessage("Client: %s, Connected on port: %hu", host, ntohs(client.sin_port));
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//while loop: accept and echo message back to client
char buf[4096];
int bytesReceived;
while (true)
{
//Wait for client to send data
bytesReceived = recv(clientSocket, buf, sizeof(buf), 0);
if (bytesReceived == SOCKET_ERROR) {
wxLogMessage("Can't read from client! Error: ", WSAGetLastError());
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
ret = send(clientSocket, buf, bytesReceived, 0);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't send to client! Error: ", WSAGetLastError());
break;
}
}
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}

Trying to receive incoming UDP packets, empty buffer

I'm trying to read these incoming UDP packets using Wireshark:
I'm using the next code:
struct sockaddr_in si_other;
struct sockaddr_in remaddr; /* remote address */
int slen = sizeof(remaddr);
int s, recvlen;
char buf[BUFLEN];
char message[BUFLEN];
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//create socket
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR) //IPPROTO_UDP
{
printf("socket() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
//setup address structure
memset((char *)&si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);
if (bind(s, (struct sockaddr *)&si_other, sizeof(si_other)) < 0) {
perror("bind failed");
return 0;
}
u_long nMode = 1; // 1: NON-BLOCKING
if (ioctlsocket(s, FIONBIO, &nMode) == SOCKET_ERROR)
{
closesocket(s);
WSACleanup();
return 0;
}
//start communication
while (1)
{
printf("waiting on port %d\n", PORT);
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Done");
puts(buf);
}
The address I'm binding is 192.168.1.1 and the port 1234.
And the given output by WSAGetLastError is an empty buffer error: 10035
I tried to disconnect firewall, antivirus...and I'm running the program as a administrator, and it didn't help.
Why is the buffer empty? I'm clearly seeing that there are packets coming, what could be blocking the incoming data to the socket?
the given output by WSAGetLastError() is an empty buffer error: 10035
No it isn't. 10035 is WSAEWOULDBLOCK. That means the operation would block in blocking mode, i.e. that no data was present to be received at the moment you called recvfrom().
The address I'm binding is 192.168.1.1
The IP 192.168.1.1 is shown as a gateway
These two statements are mutually inconsistent. If it's a gateway it's an external IP address, and if it's an external IP address you can't bind to it.
I tried INADDR_ANY and it didn't help
Not surprising. If you're not 192.168.1.1 you can't receive its messages. Unclear why you would think otherwise.
As #EJP mentioned 10035 is WSAEWOULDBLOCK, i.e., no data is ready. The cause of this is that the receiver is 192.168.1.1 which is your gateway's IP address, thus not a local IP. In this case you cannot receive the packets in a normal manner.
You can receive these packets, even though they are not meant for you, by using an UDP sniffer, e.g., using libpcap.
Thanks for the answers, they pointed me to the right direction. I 've got now the program working and I'm able to receive the incoming UDP packets.
The solution was to "sniff" these UDP packets, winsock allows that using the WSAIoctl function after bind, in my case adding the next code to the above program (after the bind function):
if (WSAIoctl(s, SIO_RCVALL, &j, sizeof(j), 0, 0, (LPDWORD)&si_other, 0, 0) == SOCKET_ERROR)
{
printf("WSAIoctl() failed.\n");
return 1;
}
I hope could help somebody else with similar issue.

C++ Winsock UDP sendto succeeds but I don't see the data being sent

I am working with UDP sockets over an ethernet interface between my workstation (192.168.0.1) and my WinCE6 device (192.168.0.100).
From my workstation I can send UDP packets toward my WinCE device where I have a receiving socket set up and properly receiving data on port 9002; the device then properly echoes back data to my workstation.
I want my device to answer to my workstation on a specific port: 9001.
This is the server running into my device, it is the same as this but I modified the socket bind to the address of the specific interface and I changed the PORT define:
#define BUFLEN 512 //Max length of buffer
#define PORT 9002 //The port on which to listen for incoming data
void test_udp( void )
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
char buf[BUFLEN];
WSADATA wsa;
slen = sizeof(si_other) ;
//Initialise winsock
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
return;
}
//Create a socket
if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
printf( "Could not create socket : %d" , WSAGetLastError());
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl( 0xC0A80064 );
server.sin_port = htons( PORT );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
return;
}
//keep listening for data
while(1)
{
//clear the buffer by filling null, it might have previously received data
memset(buf,'\0', BUFLEN);
//try to receive some data, this is a blocking call
if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
return;
}
// *** CHANGE THE SEND PORT
si_other.sin_port = htons( 9001 );
//now reply the client with the same data
if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR)
{
return;
}
}
closesocket(s);
WSACleanup();
return;
}
When I added the line below the // *** CHANGE THE SEND PORT comment to try to send the data back to port 9001, I am getting an appropriate return value for sendto which matches the number of bytes I expect to have been sent, but I don't see the data coming on my workstation (listening on 9001).
I have been banging my head against this and I cant see anything wrong. In the modified example, Any help would be greatly appreciated.
UPDATE: A firewall on my development PC was at fault. It allowed traffic back on the same port my PC was sending on, but blocked traffic on any other port. Resolving that allowed the the traffic to be sent without code changes. I had disabled the firewall previously, but did not realize that the OS had flagged the ethernet as a "public network", which still had the firewall enabled.
If, as you said, you are not getting a SOCKET_ERROR from the sendto and you are seeing an appropriate return value, this means that your OS was able to find a route toward the destination IP and was able to buffer your send request.
To change the send port it's ok if you want to answer to a different port with respect to the one from which you received data but note that this is not a typical case; the si_other struct in fact will contain the source address after the recvfrom and so the source port too. So keep your code as it is on your device side.
If you are not seeing data flowing to your workstation probably, in a simple networking context as your development environment, the problem is on the workstation: it is not receiving data.
I agree with #Daniel that you have to investigate with WireShark to see what's happening to packets.
Hope this helps

How to run a live server win winsock?

So I want to run a live server on my pc to connect and get info from someone else. I thought I can let the other person connect to my ip address on a port that is not used. So for example if my hypothetical ip address is 214.231.34.12 and port 50000 and I open te connection and give this information to someone, they can connect to it and send me information through TCP.
I thought I could use this code:
// TCPClient.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
/*
Live Server on port 50000
*/
#include<io.h>
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
int c;
char *message;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_addr.s_addr = inet_addr("214.231.34.12");
server.sin_family = AF_INET;
server.sin_port = htons(50000);
//Bind
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//Listen to incoming connections
listen(s, 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while ((new_socket = accept(s, (struct sockaddr *)&client, &c)) != INVALID_SOCKET)
{
puts("Connection accepted");
//Reply to the client
message = "Hello Client , I have received your connection. But I have to go now, bye\n";
send(new_socket, message, strlen(message), 0);
}
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d", WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
But it is failing at binding the connection. This whole TCP and winsocket stuff is totally new to me and I do not understand how I should approach this differently. I know this code is not receiving any information yet, it is just the connection that I try to get working at the moment. Is this not the right way to set this up?
The bind() fails with windows socket error 10049
There are plenty of obstacles for establish a TCP connection over internet:
internet itself: bad/unstable connection, dynamic ips, etc
ISP: maybe your ISP blocks some ports or ips
router: router firewall, NAT traversal problems, upnp, etc
OS: windows firewall, antivirus, port blocked/in use
YOUR APP: maybe a code mistake
Is a complete new world link to pcs over internet, the concept is the same, but implement it......
So it might be an answer, but maybe I have to use another port as datenwolf suggested.
I found that it is not possible to bind to my ISP's ipaddress. So I have forward the port I want to use and then connect to the ipaddress of my computer, as mentioned here:
connecting to an IP address instead of localhost?
I tried that, so I changed the ipaddress in code to:
//Prepare the sockaddr_in structure
server.sin_addr.s_addr = inet_addr("192.168.178.93");
server.sin_family = AF_INET;
server.sin_port = htons(50000);
And then when I connect to 214.231.34.12 and port 50000 with telnet, the connection works! I just wonder if this is a valid result?

c++ WINSOCK recvfrom no get data from network

i have problem because my server dont get UDP data. Ports on router are forwarded, data income to local-server network (it is visible on sniffer (3) ) but server dont receive it.
Server and server network screen
You can see 1 and 2 TCP packets correct income to server on connected sockets. But my client then send UDP data to server and data enter to local-server network (see that sniffer detect it on 3) but server dont take it.
Here is code of client:
struct sockaddr_in si_other;
int s, slen = sizeof(si_other);
char buf[10];
char message[10];
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//create socket
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
printf("socket() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
//setup address structure
memset((char *)&si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(14996);
si_other.sin_addr.S_un.S_addr = inet_addr(server ip);
memcpy(message, "cokolwiek", 8);
//send the message
if (sendto(s, message, strlen(message), 0, (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
But its not problem with client. Here is server code but i think it is also correct:
SOCKET s;
struct sockaddr_in server, si_other;
int slen, recv_len;
char buf[10];
WSADATA wsa;
slen = sizeof(si_other);
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//Create a socket
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(14996);
//Bind
if (::bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//blocking on it, waiting for data
if ((recv_len = recvfrom(s, buf, 10, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
printf("Data: %s\n", buf);
Some description that may help - main server loop is select() and when client ask for order, server send order back to client and starts proceeding command.
server:
while (1) {
select()
if (socket is in FD_SET)
get data, send it back and handleCommand()
}
handleCommand() {
tcp data exchange
wait for udp packet - it fail
}
client:
sendCommand()
//another receiving commands thread
while (recv) {
handle command
tcp data exchange
send udp data
}
Pls dont give me answears to do it in another wait. I need to punch hole for NAT Traversal. What problem is that? Another listener grabbing my data? But netstat -nop UDP -a didn't give information that something other is listening, and bind socket didn't failed. Also another important information That code work on the begining of program, i mean server receive data but later not.
Okey, so as ElderBug said
Are you sure you setup the UDP server socket before you send the data ? It's not clear in your question
Yep, it was my fault. The miniseconds decided that sending data on one machine was executed before setting up listener on server. Thank you for answer.
But i dont exactly understand the problem. Shouldn't that data income to receive buffer and wait for "grabbing" it by recvfrom function?