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.
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.
i am working on a chat.
i can start my server and client on the same computer using the 127.0.0.1 ip address and can talk fine, but if I try using my own IP address in the client to connect to the server, it does not connect. If someone else also tries to do it, it doesn't work
i have portforwarded in my router like this:
external host: my ip
internal host: my internal ip i got with ipconfig (192.168.1.4)
internal port: 54444
external port: 54444
even then, I think I should still be able to connect to my IP address without a portforward since the server is hosted on 127.0.0.1/localhost, right?
this is my client code:
WSADATA wsa;
if (!WSAStartup(MAKEWORD(2, 2), &wsa))
{
printf("started server\n");
SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sock)
{
printf("created listen socket\n");
sockaddr_in addr;
addr.sin_family = AF_INET;
inet_pton(AF_INET, "92.83.235.216", &addr.sin_addr);
addr.sin_port = htons(54444);
if (!connect(listen_sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)))
{
printf("connected to server\n");
char buffer[2048];
char input[2048];
for(;;)
{
printf("message: ");
scanf_s("%s", input);
if (send(listen_sock, input, strlen(input) + 1, 0))
{
printf("\nsent message \"%s\"", input);
}
memset(input, 0, sizeof(input));
printf("\n");
}
}
}
}
printf("%d\n", WSAGetLastError());
WSACleanup();
it stops after it shows "creating listen socket", right at the connect() call
Any ideas?
EDIT: server code is very jumbled because of me making it into a class to make it easier to use + adding a thread to handle multiple connections, but like I said it does work internall
only thing different in the server code besides the listen and accept calls is these rules i added:
char opt_val = 1;
setsockopt(this->m_listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val));
setsockopt(this->m_listen_sock, IPPROTO_TCP, TCP_NODELAY, &opt_val, sizeof(opt_val));
What you're describing sounds like your SYN packets are being dropped (SYN... no SYN/ACK or RST). You can use wireshark to see what is happening with the actual tcp connection (filter on port).
You might want to eliminate the server as a source of error by listening on localhost and connecting that way. You can verify it is listening on the correct address and port using netstat.
Otherwise, it would help if you posted your server code.
My code is based on the book "Network Programming for Microsoft Windows Second Edition", which can be found online as a PDF.
My code for the server application is:
#include <iostream>
#include <winsock2.h>
int main(void)
{
WSADATA wsaData;
SOCKET ReceivingSocket;
SOCKADDR_IN ReceiverAddr;
int Port = 5150;
char buffer;
SOCKADDR_IN SenderAddr;
int SenderAddrSize = sizeof(SenderAddr);
WSAStartup(MAKEWORD(2,2), &wsaData);
ReceivingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
ReceiverAddr.sin_family = AF_INET;
ReceiverAddr.sin_port = htons(Port);
ReceiverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(ReceivingSocket, (SOCKADDR *)&ReceiverAddr, sizeof(ReceiverAddr));
recvfrom(ReceivingSocket, &buffer, 1, 0, (SOCKADDR *)&SenderAddr, &SenderAddrSize);
std::cout << buffer << std::endl;
buffer = 'b';
sendto(ReceivingSocket, &buffer, 1, 0, (SOCKADDR*)&SenderAddr, SenderAddrSize);
std::cin.get();
closesocket(ReceivingSocket);
WSACleanup();
}
And for the client application is:
#include <winsock2.h>
#include <iostream>
int main()
{
WSADATA wsaData;
SOCKET SendingSocket;
SOCKADDR_IN ReceiverAddr;
SOCKADDR_IN ex;
int Port = 5150;
char buffer = 'a';
WSAStartup(MAKEWORD(2,2), &wsaData);
SendingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
ReceiverAddr.sin_family = AF_INET;
ReceiverAddr.sin_port = htons(Port);
ReceiverAddr.sin_addr.s_addr = inet_addr("-->insert ip here<--");
sendto(SendingSocket, &buffer, 1, 0, (SOCKADDR *)&ReceiverAddr, sizeof(ReceiverAddr));
int len = sizeof (ex);
recvfrom(SendingSocket, &buffer, 1, 0, (SOCKADDR*)&ex, &len);
std::cout << buffer << std::endl;
std::cin.get();
closesocket(SendingSocket);
WSACleanup();
}
When I insert a local IP, the code works perfectly fine - the applications detect each other and exchange buffers. But when I insert my global IP, the applications don't detect each other. Is it a problem with the code, or something I have to change when using a global IP, or something wrong with my network settings?
To clarify:
When I said about "inserting IP address", I meant writing it instead of "-->insert ip here<--".
By local IP, I meant my computer's local IP address, checked in the console using the ipconfig command.
By global IP, I meant the global IP of my router, which I checked on myglobalip.com, and I forwarded port 5150 to my local IP address.
This might be a bit off topic, but if it's something wrong with network settings, I would appreciate if you could give a link to a good tutorial because I couldn't find one that worked.
Nice code. Nice and simple. All I had to do was cut and paste (and add #pragma comment (lib, "ws2_32.lib")).
Are the client and the server both running on your LAN? If so, my tests indicate that they won't be able to talk to each other via your router's external IP address. This is because the router doesn't loop back packets sent out through its ADSL / VDSL port (why would it?) so they just disappear into the ether. I tried enabling both the DMZ and port forwarding on my router (at minimum, you need one or the other) but no dice, which was what I was expecting.
So to test this, you will need the help of a friend with a router of his own. Let's suppose he is running the client. You will then need to put your server machine into your router's DMZ or (better, because it's safer) set up port forwarding for UDP port 5150 on your router to the server machine. In either case, give that machine a static IP address on your LAN else it might move. Then you have a chance of seeing this work.
Our friends over at superuser have this to say about sending UDP packets via [routers implementing] NAT (which is what you will have there) and getting an answer back:
IF Machine A sends [a UDP] frame from the same source port as the destination port ("Port N"), and IF the NAT is able to preserve that source port (i.e. it's configured to preserve source ports when possible, and that source port is not in use), THEN you can expect a reply to "Port N" to get back to Machine A.
But the problem currently is that nothing is listening. Certainly not your server program.
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 have a connection protocol that has been defined by our customer. Data are sent between two linux computers using UDP and TCP protocols. The IP addresses and ports are fixed on startup.
We are sending messages at 200 Hz and I have been using connect to save some time on the transmissions.
My problem is that if there is a communication error, I need to tear down the connections and reinitialise.
I have a problem with one of the UDP connections as it will not rebind to the required address and returns errno 22.
The code I am using is something like:
int
doConnect(int& sock, int local_port, char *local_ip, int remote_port, char *remote_ip)
{
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(local_port);
inet_pton(local_ip,&addr.sin_addr.s_addr);
if (0 > bind(sock, (struct sockaddr*)&addr, sizeof(addr)))
{
printf("Bind Error errno = %d\n", errno);
return ERR_BIND;
}
memset(&addr, 0, sizeof(sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(remote_port);
inet_pton(remote_ip,&addr.sin_addr.s_addr);
if (0 > connect(sock, (struct sockaddr*)&addr, sizeof(addr)))
{
printf("Connect Error errno = %d\n", errno);
return ERR_CONNECT;
}
return ERR_OK;
}
The way that this is used is like this:
int s1(-1), s2(-1);
doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");
When an error occurs
close(s1);
close(s2);
doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");
Here the local address is 172.17.21.3 and I am connecting to 172.17.21.1. s1 listens to a broadcast message.
s1 successfully reconnects to the remote machine, but s2 fails with error 22 from the call to bind.
I have tried explicitly calling bind and connect to an AF_UNSPEC address immediately before I close the socket. This doesn't solve the problem.
Are there any options that I should be using?
Perhaps you could try:
int val = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
I also suggest you double check that you're not passing the same socket to the two consecutive doConnect() calls (as errno 22 = EINVAL, which in the case of bind() appears to mean that the socket is already bound to an address).
The underlying socket layer might hold the port & IP address still open, even after your call to close. Try some of the following:
do a sleep(10) (or more) between the close and the call to doConnect again
configure the sockets using setsockopt with the SO_LINGER set to off
This actually happens more commonly with TCP connections, but I see no reason UDP can't have this problem as well.