I'm currently working on a networking assignment. We intended the client to automatically get assigned an IP and port to a TCP socket, and bind an UDP socket to the same address and port as the TCP socket. This way, both UDP and TCP share the same IP and port.
I've checked several questions here and all of them seem to state that the source port depends on the address you specify on binding the socket, however, this doesn't seem to work.
This is the code on my client, where I bind the UDP socket:
sockaddr_in udpAddress;
udpAddress.sin_family = AF_INET;
udpAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
udpAddress.sin_port = htons(27015);
bind(udpSocket, (sockaddr*)&udpAddress, sizeof(udpAddress));
printf("[UDP] Bound to port %d\n", ntohs(udpAddress.sin_port));
printf("Error when binding: %d\n", WSAGetLastError());
char buffer[32];
sprintf(buffer, "TEST\n");
sendto(udpSocket, buffer, 7, 0, (sockaddr*)&serverAddress, sizeof(serverAddress));
When running the application, this prints the following:
[UDP] Bound to port 27015
Error when binding: 0
Error 0 implies that there is no error, so this should be fine.
However, when I check on the server console, I see the following print:
[UDP] 127.0.0.1:64910
Which is generated by the following code:
#if PLATFORM == PLATFORM_WINDOWS
typedef int socklen_t;
#endif
sockaddr_in from;
socklen_t fromLength = sizeof(from);
short messageSize = recvfrom(udpSocket, (char*)udpBuffer, udpBufferSize, 0, (sockaddr*)&from, &fromLength);
if (messageSize > 0)
{
unsigned int from_address = ntohl(from.sin_addr.s_addr);
unsigned int from_port = ntohs(from.sin_port);
printf("[UDP] %d.%d.%d.%d:%d\n", from_address >> 24, from_address >> 16 & 0xff, from_address >> 8 & 0xff, from_address & 0xff, from_port);
}
I really wonder why this port is invalid. Does anyone know what I'm doing wrong?
Also worth saying, it seems like every time I restart my application, the port increments, so I'm not even sure if this is my own fault. If I send a packet to the server using the program PacketSender, the port reported on the server is the same port reported by the program, but this port is assigned automatically, not chosen.
I have found the solution to my problem. When I tried to check for the return value of bind(), I kept getting prompted with an error. It turns out that for whatever reason, I was in the std namespace without explicitly stating this anywhere in my own code. After changing bind() to ::bind(), I was able to catch the return value and bind() did what I expected.
Related
I'm having issues working with a UDP socket in Windows. I have a separate application I'm trying to communicate with that outputs on port 1625 and receives on port 26027. I tried to make a simple executable that reads one message and sends one message. The read works fine, but the send ends up with a WSAEADDRNOTAVAIL (10049) error.
To troubleshoot I also tried the equivalent code in Linux with (using Windows Subsystem for Linux) on the same machine and it works fine. So I can't figure out what the issue is. I also tried disabling Windows Firewall but that didn't make a difference. Any suggestions would be appreciated.
The Windows Visual C++ code:
#pragma comment(lib, "Ws2_32.lib")
#include <iostream>
#include <WS2tcpip.h>
#define MAXLINE 1024
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// Define local port address.
sockaddr_in local_port;
memset(&local_port, 0, sizeof(local_port));
local_port.sin_family = AF_INET;
local_port.sin_addr.s_addr = INADDR_ANY;
local_port.sin_port = htons(1625);
// Bind local socket.
int socket_id = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bind(socket_id, (const struct sockaddr *)&local_port, sizeof(local_port));
// Receive UDP Port message.
char in_buffer[MAXLINE];
int num_bytes = recv(socket_id, (char *)in_buffer, MAXLINE, 0);
in_buffer[num_bytes] = '\0';
printf("Received : %s\n", in_buffer);
// Set up send destination port.
sockaddr_in dest_port;
memset(&dest_port, 0, sizeof(dest_port));
dest_port.sin_family = AF_INET;
dest_port.sin_addr.s_addr = INADDR_ANY;
dest_port.sin_port = htons(26027);
// Send UDP message to specific UDP port.
char out_buffer[] = "Test message";
int result = sendto(
socket_id, out_buffer, strlen(out_buffer), 0, (struct sockaddr *)&dest_port, sizeof(dest_port));
printf("Send result : %d -- WSA Error : %d\n", result, WSAGetLastError());
closesocket(socket_id);
return 0;
}
Terminal output from running this executable is:
Received : 5e4009df*755=-0.0028:761=0.6942
Send result : -1 -- WSA Error : 10049
The WSL linux C++ code (the same source code except for WSA includes and error output):
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define MAXLINE 1024
int main()
{
// Define local port address.
sockaddr_in local_port;
memset(&local_port, 0, sizeof(local_port));
local_port.sin_family = AF_INET;
local_port.sin_addr.s_addr = INADDR_ANY;
local_port.sin_port = htons(1625);
// Bind local socket.
int socket_id = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bind(socket_id, (const struct sockaddr *)&local_port, sizeof(local_port));
// Receive UDP Port message.
char in_buffer[MAXLINE];
int num_bytes = recv(socket_id, (char *)in_buffer, MAXLINE, 0);
in_buffer[num_bytes] = '\0';
printf("Received : %s\n", in_buffer);
// Set up send destination port.
sockaddr_in dest_port;
memset(&dest_port, 0, sizeof(dest_port));
dest_port.sin_family = AF_INET;
dest_port.sin_addr.s_addr = INADDR_ANY;
dest_port.sin_port = htons(26027);
// Send UDP message to specific UDP port.
char out_buffer[] = "Test message";
int result = sendto(
socket_id, out_buffer, strlen(out_buffer), 0, (struct sockaddr *) &dest_port, sizeof(dest_port));
printf("Send result : %d\n", result);
close(socket_id);
return 0;
}
Terminal output from running this executable is:
Received : 5e4009df*755=-0.0028:761=0.6942
Send result : 12
I can also validate that the output to port 26027 via this Linux implementation is received by the other application and can also see it in Wireshark.
EDIT:
After Remy's answer below I was able to get this working as per the comments below. To clarify my network:
My network if I view it with Wireshark now looks like:
127.0.0.1 UDP 50223 → 1625 Len=32
127.0.0.1 UDP 1625 → 26027 Len=12
Where my node binds to 1625 where it can recv() UDP from some unknown port number (50223 in this case), and sendto() port 26027.
You can't use recv() with a UDP socket unless you first call connect() to statically assign the peer's IP/port to the socket, which you are not doing. So recv() will fail, but you are not checking for that. You need to use recvfrom() instead.
Also, no matter what, you can't send packets to INADDR_ANY (0.0.0.0) as you are. That is why you are getting the send error.
sendto Function
WSAEADDRNOTAVAIL
The remote address is not a valid address, for example, ADDR_ANY.
Windows Sockets Error Codes
WSAEADDRNOTAVAIL
10049
Cannot assign requested address. The requested address is not valid in its context. This normally results from an attempt to bind to an address that is not valid for the local computer. This can also result from connect, sendto, WSAConnect, WSAJoinLeaf, or WSASendTo when the remote address or port is not valid for a remote computer (for example, address or port 0).
You need to send to an actual IP/port, such as to the peer's IP/port that is reported by recvfrom() when it receives a packet.
Running a Linux system on a PowerPC Architecture which is connected via Ethernet to another Device obtaining a UDP connection (Package Based),
I try to setup a socket and bind it to my Port 8813. But whenever I enter a Port different from 0, Binding fails.
Here is the code:
int connector::initUDPSocket(){
struct hostent *server;
//Construct Socket
struct sockaddr_in {
__uint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
}
;
sockaddr_in socketaddress;
socklen_t addrlen = sizeof(struct sockaddr_in); /* length of addresses */
udpsocket=socket(AF_INET,SOCK_DGRAM ,0);
if(udpsocket<=0)
{
printf("No Socket opened!");
return 1;
}
else
{
printf("ONE Socket opened!");
memset((char *) &socketaddress,0, sizeof(socketaddress));
socketaddress.sin_family = AF_INET;
socketaddress.sin_addr.s_addr=htonl(inet_addr("192.168.0.10"));//<=That's the external devices address;// htonl(inet_addr("192.168.0.1"));//<=That's my devices address;//htonl(INADDR_ANY);//INADDR_ANY;//
socketaddress.sin_port = htons(8813);//8813;//htonl(8813);//htons(0); //<=Only the last one works
int bind_result=bind(udpsocket,(struct sockaddr *)&socketaddress,sizeof(socketaddress));
if( bind_result == SOCKET_ERROR)
{
printf(LFL_CRI,"BIND failed! Error: %s",strerror(errno)); //Returns "BIND failed! Error: Address family not supported by protocol"
}
else
{
printf(LFL_CRI,"BIND worked!");
//Nun den Listener für den DatenStream aufsetzen.
char SockAddrBuffer[sizeof(struct sockaddr_storage)];
socklen_t SockAddrBufferSize = sizeof(SockAddrBuffer);
int numofbytes=recvfrom(udpsocket, udp_buffer, UDP_BUFFERSIZE, 0, (struct sockaddr *)SockAddrBuffer, &SockAddrBufferSize);
if (numofbytes >0)
{
printf("%i bytes received",numofbytes);
}
}
}
return 0;
}
}
What I found out so far:
Ping 192.168.0.10 is possible
Data seem not to be blocked by the firewall; iptables -nvL mentioned no dropped packages. I added a new rule for that, before this rule was applied, the number or dropped packages increased when the external device was connected.
Using a test tool on my Windows PC (simply debugging, if there's incoming traffic on a port; connecting the external device to it), I receive data; so, the external device definitely sends data
Binding to Port 0 works; the netstat -au mentions a tool listening on port 2, while the program is running
Error Message: BIND failed! Error: Address family not supported by protocol
So, 2 questions are open here:
What am I doing wrong?
What am I understanding wrong about "bind". What sense does it make to listen to "some random port assigned to my program by the system"? I mean, if I setup an http-Server, I want to listen to Port 80 and not to port "RANDOM". What is this good for?
You've redefined struct sockaddr_in in your code. If is in any way different from how the system defines it, any code that attempts to use this struct will not work properly.
You need to #include <netinet/in.h> to get the proper definition of this struct.
I have the following configuration for my experiment.
Wifi(Belkin) router connected to Internet.
Laptop with Windows 7 OS
Laptop with Ubuntu OS.
Experiment: When I connect both of my laptop to Wifi router it assigns DHCP IPs 192.168.2.2 to Linux & 192.168.2.3 to Win 7. Both of them can browse internet.
I start a UDP server on my Linux machine with the following code.
int main(int argc, char *argv[]) {
int sd, rc, n, cliLen, flags;
struct sockaddr_in cliAddr, servAddr;
char msg[MAX_MSG];
//Create a socket
sd=socket(AF_INET, SOCK_DGRAM, 0);
if(sd<0){ printf("%s: cannot open socket \n",argv[0]); exit(1); }
//Bind now to a port
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr("192.168.2.2");
servAddr.sin_port = htons(9999);
rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr));
if(rc<0) {printf("%s: cannot bind port number %d \n", argv[0], 9999);exit(1);}
//We are done ... Notify User
printf("%s: waiting for data on port UDP %u\n",argv[0],LOCAL_SERVER_PORT);
//Server's Infinite Loop
while(1)
{
memset(msg,0x0,MAX_MSG);//Sanity
/* receive message */
cliLen = sizeof(cliAddr);
n = recvfrom(sd, msg, MAX_MSG, flags,(struct sockaddr *) &cliAddr, (socklen_t * )&cliLen);
if(n<0){printf("%s: cannot receive data \n",argv[0]);continue;}
//Received message
printf("%s: from %s:UDP%u : %s \n", argv[0],inet_ntoa(cliAddr.sin_addr),ntohs(cliAddr.sin_port),msg);
sleep(1);
//Sending back the data thus received
sendto(sd,msg,n,flags,(struct sockaddr *)&cliAddr,cliLen);
}//while
return 0;
}
This code work well & I can receive the packet to the server when some local client on the Linux machine tries to contact my server.
PROBLEM : When I make the same client in Android AVD present in my windows 7 system I am unable to reach my server.
I thought may be that's firewall issue, so I removed the firewall & added by pass custom rules to the IP "192.168.2.2" as given in the following link. http://www.brighthub.com/computing/windows-platform/articles/40014.aspx#
But it did not work. I thought that first I should try with raw java first then with AVD.
Hence, I created a UDP client with Java code still I was not able to connect to server.
Then I thought let's try with raw C++ so that I would come to know exactly what is the problem. Following is the Visual Studio code which I implemented for the same.
#define PORT_NUM 9999 // Port number used
#define IP_ADDR "192.168.2.2" // IP address of server1
#define BUFFER_SIZE 4096
void main(void){
WORD wVersionRequested = MAKEWORD(2,2); // Stuff for WSA functions
WSADATA wsaData; // Stuff for WSA functions
int client_s; // Client socket descriptor
struct sockaddr_in server_addr; // Server Internet address
int addr_len; // Internet address length
char out_buf[BUFFER_SIZE]; // Output buffer for data
char in_buf[BUFFER_SIZE]; // Input buffer for data
int retcode; // Return code
// This stuff initializes winsock
WSAStartup(wVersionRequested, &wsaData);
client_s = socket(AF_INET, SOCK_DGRAM, 0);
if (client_s < 0){ printf("*** ERROR - socket() failed \n"); exit(-1);}
server_addr.sin_family = AF_INET; // Address family to use
server_addr.sin_port = htons(PORT_NUM); // Port num to use
server_addr.sin_addr.s_addr = inet_addr(IP_ADDR); // IP address to use
strcpy(out_buf, "Test message from CLIENT to SERVER");
retcode = sendto(client_s, out_buf, (strlen(out_buf) + 1), 0,(struct sockaddr *)&server_addr, sizeof(server_addr));
if (retcode < 0){printf("*** ERROR - sendto() failed \n");exit(-1);}
addr_len = sizeof(server_addr);
retcode = recvfrom(client_s, in_buf, sizeof(in_buf), 0,(struct sockaddr *)&server_addr, &addr_len);
if (retcode < 0){printf("*** ERROR - recvfrom() failed \n");exit(-1);}
printf("Received from server: %s \n", in_buf);
retcode = closesocket(client_s);
if (retcode < 0){ printf("*** ERROR - closesocket() failed \n");exit(-1);}
WSACleanup();
}
But it gives me error of destination unreachable.
To find out exactly what is going on at the packet level, I installed "Wireshark", on my ubuntu machine.
My observation is... whenever my windows client executes I get a ICMP message 3 times on the Wireshark having the type 3 message. The detailed analysis of the packet showed that the port is unreachable.
Kindly help me to find out what I am missing here :(.
Have you tried disabling the firewall on the linux machine, or adding an exception for the port you are using?
sudo ufw disable
or use the following to show your iptables firewall rules:
sudo iptables -L
Check the connection between the two machines
ICMP: ping win->lin and back
TCP: connect SSH, Samba, or even browser if you can run some web server
UDP: use nc (netcat) utility to test UDP/TCP connection between two machines
If one of these does not work, look for the problem :
Shut down the firewalls on both computers and on the wireless AP, run sniffers on Win and on Lin machines.
If the connection is ok, the you know you have a bug in your program. Start debugging each end against something working - i.e. nc.
I'm new to Windows networking, and I am trying to find out which PORT number my socket is bound to (C++, Windows 7, Visual Studio 2010 Professional). It is a UDP socket, and from what I understand, using the following initial setup should bind it to a random available port/address:
sockaddr_in local;
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = 0; //randomly selected port
int result = bind(clientSock, (sockaddr*)&local, sizeof(local));
//result is always 0
As far as using this method, it works for sending data or binding it to a specific port (replacing the 0 with a desired port number). What I need is to bind it randomly, and then find out which port it was bound to afterwards. Is there any way I can do this? It seems that the "local" struct contains "0.0.0.0" as the IP address and "0" as the PORT number.
Thanks for any and all help! I appreciate it.
Use getsockname. For example:
struct sockaddr_in sin;
int addrlen = sizeof(sin);
if(getsockname(clientSock, (struct sockaddr *)&sin, &addrlen) == 0 &&
sin.sin_family == AF_INET &&
addrlen == sizeof(sin))
{
int local_port = ntohs(sin.sin_port);
}
else
; // handle error
This also works for *nix-based systems, but note that some systems define the third argument of getsockname to be of type socklen_t* instead of int*, so you might get warnings about pointers differing in signedness if you're writing cross-platform code.
I am writing a small program that tests an UDP network service. The implementation of the service is allowed to create a new socket for the session and respond to the client from there, at which point the client is then required to talk to this address (similar to TFTP).
Minimal client sans error checking looks like this:
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
sockaddr_in destaddr = { ... };
MSGBUF msg[] = { ... };
DWORD sent;
WSASendTo(fd, msg, sizeof msg / sizeof *msg, &sent, 0, (sockaddr *)sa, sizeof sa, 0, 0);
char buffer[4096];
MSGBUF rcvmsg = { sizeof buffer, buffer };
DWORD received;
sockaddr_storage sa;
socklen_t sa_len = sizeof sa;
DWORD flags = 0;
WSARecvFrom(fd, &rcvmsg, 1, &received, &flags, (sockaddr *)&sa, &sa_len, 0, 0);
The client works fine if the server responds from the same address and port that the initial message was sent to, however replies from another port are silently discarded and the client hangs in WSARecvFrom.
Explicitly binding the socket to { AF_INET, INADDR_ANY, 0 } to force assignment of a local port, or invoking listen(fd, 5); makes no difference, as expected.
Is there anything in WSASendTo that implicitly connects an UDP socket, and if so, what should I do to avoid this?
UDP doesn't have connections. Datagrams are sent to and from ports; it's one-way communication.
It sounds to me like your server is letting itself be assigned a temporary port (i.e. passing 0 as the port in sockaddr_in), instead of using a specific port. This won't work.
Since UDP has no concept of a connection, each time you send data, it could be sent from a different port; the first send doesn't reserve the port that it was given, it just sends a datagram from it and then lets it go.
Your server should be binding itself to a specific port.
Meh, it was a firewall issue. Adding the application to the list of programs allowed to receive incoming traffic fixed the issue.