echo server not responding udp - c++

Am trying to implement a echo client. Client using sendto() is transmitting the message and server is receiving n displaying it. but then server is not sending the message (echo back). here is the code of both server and client. Can anyone help me with this?
Server:
char msg[100]="";
int conn_sock,n;
struct sockaddr_in server_addr,client_addr;
conn_sock=socket(AF_INET,SOCK_DGRAM,0);
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(1234);
server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
err=bind(conn_sock, (struct sockaddr *)&server_addr,sizeof(server_addr));
n=recvfrom(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&client_addr,(socklen_t *)&client_addr);
n=sendto(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&client_addr,sizeof(client_addr));
in recvfrom the value of n is number of bytes. but in sendto() value of n is -1
Client:
char msg[100];
int conn_sock,n,err;
struct sockaddr_in server_addr;
conn_sock=socket(AF_INET,SOCK_DGRAM,0);
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(1234);
server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
cin>>msg;
n=sendto(conn_sock,msg,strlen(msg),0,(struct sockaddr *)&server_addr,sizeof(server_addr));
n=recvfrom(conn_sock, msg, 15, 0, (struct sockaddr*) &server_addr,(socklen_t *)&server_addr);
recvfrom() is not receiving any data from the server.

These two lines are both wrong:
// In the server
n=recvfrom(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&client_addr,(socklen_t *)&client_addr);
// In the client
n=recvfrom(conn_sock, msg, 15, 0, (struct sockaddr*) &server_addr,(socklen_t *)&server_addr);
The last two parameters of recvfrom() are supposed to point to two separate variables. One of them receives the other peer's network address, and the other one receives the length of that network address. That you're passing the same pointer value into both means that the address length is overwriting the first several bytes of the address data, corrupting it and resulting in badness.
Here's how the server should work, receiving the length into a separate variable:
struct sockaddr_storage client_addr;
socklen_t client_addr_len = sizeof(client_addr); // This is an in+out parameter
n=recvfrom(..., (struct sockaddr *)&client_addr, &client_addr_len);
n=sendto(..., (struct sockaddr *)&client_addr, client_addr_len);
Note that I used a sockaddr_storage instead of sockaddr_in. A sockaddr_storage is guaranteed to be large enough to hold any valid socket address type for supported address families, so that this code will be forward-compatible with IPv6.
Likewise, here's how the client should work:
n=sendto(..., &server_addr, sizeof(server_addr));
do
{
struct sockaddr_storage peer_addr;
socklen_t peer_addr_len = sizeof(peer_addr);
n=recvfrom(..., (struct sockaddr *)&peer_addr, &peer_addr_len);
} while (!areSockAddrsEqual((struct sockaddr *)&server_addr, (struct sockaddr *)&peer_addr));
...
bool areSockAddrsEqual(struct sockaddr *addr1, struct sockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return false;
switch (addr1->sa_family)
{
case AF_INET:
struct sockaddr_in *addr1_in = (struct sockaddr_in *)addr1;
struct sockaddr_in *addr2_in = (struct sockaddr_in *)addr2;
return (addr1_in->sin_port == addr2_in->sin_port &&
addr1_in->sin_addr.s_addr == addr2_in->sin_addr.s_addr);
...
// Other address families such as AF_INET6 left as an exercise
}
}
Here again we make sure to pass a separate socklen_t pointer to receive the address length, and then I also added a loop to make sure that the actual packet we received was the one we were expecting from the intended server. If we instead received a different packet (say, due to another peer that just happened to send us a packet at the wrong time), we ignore it.
The check for whether or not two socket addresses are equal is a little gnarly, since it depends on the address family, and supporting both IPv4 and IPv6 is tricky.

Related

How to receive multicast UDP packets correctly?

new to multicast networking, I need to receive UDP packets from a multicast channel through one of the NICs on my windows box, followed Microsoft docs and some blog entry, but still having issues.
I create a socket via
ls = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
call.
Then setsockopt to SO_REUSEADDR
unsigned int reuse = 1;
if( setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0 )
{
LOG4CXX_ERROR(logger, "Reusing ADDR failed. Err: " << WSAGetLastError());
}
If socket is good
int result = bind(ls, reinterpret_cast<SOCKADDR*>(&server), sizeof(server));
where
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(myport);
If bind succedes
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("e.f.g.h");
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if( setsockopt(ls, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) < 0 )
{
LOG4CXX_ERROR(logger, "setsockopt multicast group add membership failed. Err: " << WSAGetLastError());
}
The box on which I need to receive packets has four NICs, network administrators told me that I have to use the third one, let's say that it has a.b.c.d IPv4 address
They told me also that mcast IP is e.f.g.h
If I run windump.exe -i 3 on my windows box I see something like this
... 12:53:58.454987 IP i.k.l.m.xxxxx > e.f.g.h.myport: UDP, length 58
...
After initializing my UDP socket I call recvfrom
sz = recvfrom(ls, buffer, DATA_BLOCK_SIZE, 0, reinterpret_cast<SOCKADDR*>(&client), &size);
where sz is an int, ls is my socket, buffer is a "suitable buffer", DATA_BLOCK_SIZE is buffer size, client is a SOCKADDR pointer to receive info from the sender, and size is the received message size.
My code stucks in the recvfrom call never receiving anything.
I'm clearly making a mistake somewhere but not understanding where and worse why.
If someone can explain me what's happening it will be very appreciated.
SOLVED ...
I changed these lines only
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("e.f.g.h");
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
to
struct ip_mreq mreq;
inet_pton(AF_INET, "e.f.g.h", &(mreq.imr_multiaddr));
inet_pton(AF_INET, "a.b.c.d", &(mreq.imr_interface));
As I have guessed I was not correctly indicating in my struct ip_mreq which was the network interface to use for multicast messages.
It was my fault. Sorry for the noise.

Socket being set up without errors, but no connection

I am trying to learn how to use TCP/IP via 2 Linux machines, both of which have functioning internet connections. I tried setting up a server and a client, but I'm not getting a connection, despite not getting any errors during setup.
Server code:
int serverSocketFd,clientSocketFd,clientLength,numberOfBytes;
static struct sockaddr_in server_address, clint address;
char buf[256];
serverSocketFd = socket(AF_INET,SOCK_STREAM,0);
if(serverSocketFd<0){error("socket() call Failed");}
//Clears the allocated space of the sockaddr_in struct before configuration
bzero((char *)&server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
//inet_aton should take an IP address in string format and convert it to the proper format for the struct. Returns nonzero for error
if(!inet_aton("XXX.XXX.XXX.XXX",&(server_address.sin_addr))){error("inet_aton() Failed");}
//Picked a random port number for this test
server_address.sin_port = htons(34567);
//Quick check that I have the expected settings
inet_ntop(AF_INET,&server_address.sin_addr,buf,255);
printf("Listening on %s:%d\n",buf,server_address.sin_port);
if(bind(serverSocketFd,(struct sockaddr *)&server_address,sizeof(server_address)) <0){error("bind() call Failed");}
//At this point, Socket should be prepped to start listening, and waits here until another program makes contact
printf("Waiting on client...\n");
listen(serverSocketFd,5);
//If a client program makes a connection, the 'clinetSocketFd' represents it
clientLength = sizeof(client_address);
clientSocketFd = accept(serverSocektFd, (struct sockaddr *)&clinet_address, (socklen_t *)&clientLength);
if(clientSocketFd < 0){error("accept() call returned invalid");}
printf("CONNECTION ACCEPTED\n");
//Now that a connection is established, wait for a request from client
bzero(buf,256);
numberOfBytes = read(clientSocketFd,buf,255);
if(numberOfBytes<0){error("read() call Failed");}
printf("MESSAGE RECEIVED: %s\n",buf);
numberOfBytes = write(clientSocketFd,"ACKNOWLEDGED",strlen("ACKNOWLEDGED"));
return numberOfBytes;
I expect the output to be a message printing my IP address and port, then a wait message, then a message announcing a connection, then a message announcing a request from the client, and the incoming text.
Client code:
static struct sockaddr_in server_address;
char buf[256];
int numberOfBytes,e;
clientSocketFd = socket(AF_INET,SOCK_STREAM,0);
if(clientSocketFd<0){error("socket() call Failed");}
//Clears allocated space of the sockaddr_in struct before configuration
bzero((char *)&server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
//The IP address being put in here is the same as the one put in the server code, the IP address of the host machine.
if(!inet_aton("XXX.XXX.XXX.XXX",&(server_address.sin_addr))){error("inet_aton() Failed");}
server_address.sin_port = htons(34567);
//Same check as server code, look at the target IP and port
inet_ntop(AF_INET, &server_address.sin_addr,buf,255);
printf("Connecting to %s:%d\n",buf,server_address.sin_port);
//As client, we connect the socketFd for the CLIENT to the address struct of the SERVER
e = connect(clientSocketFd,(struct sockaddr *)&server_address,sizeof(server_address));
if(e<0){error("connect() call Failed");printf("Error code %d\n",e);}
//Connection has now been established and can be referenced through clientSocketFd
printf("CONNECTION ESTABLISHED\n");
//Now send a generic message
numberOfBytes = write(clientSocketFd,"TESTMESSAGE",strlen(message));
if(numberOfBytes<0){error("write() call Failed");}
bzero(buf,256);
numberOfBytes = read(clientSocketFd,buf,255);
if(numberOfBytes<0){error("read() call Failed");}
printf("%s\n",buf);
return 0;
I expect the output to be roughly the same, print the target IP and port, acknowledgement messages, and then the received acknowledge.
What I end up seeing, on both machines, is up to the listen/connect stage.
I see the "Listening on/Connecting to XXX.XXX.XXX.XXX:34567", which matches up with the IP address on the machine running the server code. Then it times out. errno is set to ECONNREFUSED.
The connection is never made, but no error comes up before this point, so it doesn't seem like anything went wrong while configuring the sockets.
Can someone explain what is problem is with this code?

Linux c++ recvfrom() changes (destroys) the [socket] file descriptor

I have written a simple UDP server. Well, naturally I use recvfrom() function somewhere in it. I have searched the net for it, and found that it is caused by the buffer overflow. Is this true? But I can't figure why my code fails and throws the same error, here is the part associated with recvfrom():
char messageFromClient[1024] = {0};
returnStatus = recvfrom(udpSocket, &messageFromClient, strlen(messageFromClient), 0, (struct sockaddr*)&udpSocket,
&addrlen);
The file descriptor before invocation of recvfrom() is 3 but when I call it, it changes to -187301886
Your code fails because you specify 0 receive buffer size and you pass the socket file descriptor as the peer address argument (which overwrites its value):
Fix:
char messageFromClient[1024];
sockaddr_in addr;
socklen_t addrlen = sizeof addr;
ssize_t received = recvfrom(udpSocket, messageFromClient, sizeof messageFromClient, 0, (sockaddr*)&addr, &addrlen);

How to get the ip address in qt/linux?

I am working on a server client project on Qt. The server is running in a machine with more than one network interface. The design is such that the client will discover the server automatically. ie the client will broadcast its IP to a network the server get that message and sends back the server's IP. The problem now is that when I try to get the IP in the server, There are more than 1 IP. How to get the IP of the interface through which server have received the message?
This might be a solution for you
IPAddress FindLocalIPAddressOfIncomingPacket( senderAddr )
{
foreach( adapter in EnumAllNetworkAdapters() )
{
adapterSubnet = adapter.subnetmask & adapter.ipaddress;
senderSubnet = adapter.subnetmask & senderAddr;
if( adapterSubnet == senderSubnet )
{
return adapter.ipaddress;
}
}
}
How to get your own (local) IP-Address from an udp-socket (C/C++)
In order to get the incoming peer IP address you can use following solution in C
socklen_t len;
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
int port;
len = sizeof addr;
getpeername(s, (struct sockaddr*)&addr, &len);
// deal with both IPv4 and IPv6:
if (addr.ss_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
port = ntohs(s->sin_port);
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
} else { // AF_INET6
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
port = ntohs(s->sin6_port);
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
}
printf("Peer IP address: %s\n", ipstr);
Getting the source address of an incoming socket connection

Reopen connected datagram socket

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.