How to find the destination address of a UDP packet using boost::asio? - c++

I'm developing a peer-to-peer communications network for use over a LAN in an industrial environment. Some messages are are just asynchronous, and don't require a response. Others are request-response. The request messages (and the async messages) are sent to a multicast group, and the replies to requests are sent unicast. Each endpoint, therefore, receives UDP packets that are sent to the multicast group, and also receives messages that are just sent to it using plain unicast.
So far it's working fine, but there doesn't seem to be any way in boost::asio to find out the destination address of a received UDP packet (using socket.async_receive_from) - whether it was sent to the multicast group or the actual interface. I can use the contents of the message to infer whether it was sent multicast or unicast, but it would be nice to be able to also check the destination address.
We are currently using Windows 7, but will be transitioning to Linux in the future.
Is there a way to find the destination address of a UDP packet received using boost::asio?

Unfortunately this is not possible with boost::asio, and usually is not "the way to do" it, as you try to access Transport Layer information at the Application Layer.
So you basically have two options:
a) Write non-portable system code with for example IP_PKTINFO or SO_BINDTODEVICE on Linux. Example Code can be found on the boost asio mailing list here
b) use two distinct sockets, one for the multicast and one for the unicast. You therefore need to specify a listen_address other than "0.0.0.0" on each socket.
udp::endpoint(address_v4::from_string("239.192.152.143"), 6771)
This Question on SO might also be helpful: Using a specific network interface for a socket in windows

Related

asio udp multicast sending and receiving on the same host using loopback on the same interface

I'm currently trying to implement the SOME/IP protocol which uses multicast for the service discovery. The Language is c++ and the asio library (without boost) is used in my case.
Currently the code works, but only on 2 diffrent machines. When i try multicast between the 2 apps on the same host i also receive the messages that i just send out. I understand that this is the purpose of the loopback interface, which is enabled when running on the same host but i'm wondering how you could filter out the own messages that were just send and not receive them again? As implementing the standard with that behaviour on one machine is nearly impossible.
When i bind the one programm to my ethernet interface and the other to my wifi interface a normal connection is possible without receiving the your own messaged again after sending.
Is it normal when you implement a network protocol to have 2 machines for testing or am i missing a simple settings which enables me to send / receive from 2 programms to the same multicast , on the same interface, without receiving its own send messages?
Essentially i want to send / receive with 2 programms on the same interface to the same multicast address without also receiving my own messages in each programm after sending them.
Thanks in advance for the help. If you have further question or if my explanation is not good to understand just ask please
I already tried using diffrent ports on the same machine, which resulted in no receiving of any data.

How Do I Send Data From One Computer To Another Without A Server (in C++)?

so I want to send an int32 (or any 4 bytes data) from one pc to another, the size of the data will always be the same, I don't need any checking to see if both pcs are online or any disconnect function, if pc2 didn't receive the data or he went offline, I just want pc1 to send the data, if pc2 is offline nothing happens and if it's online it store it somewhere.
Most tutorials I've found uses a server way of connecting, so there are 3 pcs, 2 clients and 1 server, client1 sends data to the server and the server sends it to client2, but is there a way to send it directly to client2, as if client2 is the server?
There are two common protocols used to send raw data over an ip based network. They are called TCP and UDP and serve slightly different approaches.
TCP is connection oriented and relies heavily on the server client model. On host acts as a server and accepts incoming requests on a predefined socekt. After the TCP connection is setup, you have a duplex (two-way) stream that you can use to exchange data.
UDP is a packet oriented protocol. One host (usually called the server) listens to imcoming packets and can answer them. No real "connection" is established tough.
You probably want to use UDP. Note that altough this protocol does not establish a connecion, there still needs to be at least one host, that is waiting for incoming data on a predefined port. This one is usually called the "server". However also the client can bind its UDP socket to a specific port and thus can act as a "client" and a "server" during the same time.
You can setup both hosts to listen and send on/to the same preefined port number and achieve a connectionless packetoriented way to exchange data. That way both hosts act as server and client simultaneously.
How you actually implement this, depends on your operating system. On Linux (and other POSIX compatible OSes) you can use standard UDP sockets, on Windows there is some equivalent API. Either way I suggest you to first follow a tutorial on how to program a standard TCP server and client, as most of the operations on the sockets are similar (create the socket, bind it to an address:port, and read/write data from it).

0MQ - get message ip

First, I want to give thanks for that amazing lib! I love it. A client is connecting himself to a server. The server should save the IP and do stuff with it later on (I really need the IP). I found that answer: http://lists.zeromq.org/pipermail/zeromq-dev/2010-September/006381.html but I don't understand how I get the IP out of the message (a XREP)... I think I am only able to read the ID, but the IP is managed internally by 0MQ. His second solution suggests to send the IP as part of the message, but I don't understand how to get the "public"-IP. I found that post: Get TCP address information in ZeroMQ
is pass bind a service to an ephemeral port, get a full connection endpoint ("tcp://ipaddress:port")
I don't get how this works. Does he mean something like a web-service?
In my opinion, it would be best to get the IP out of 0MQ (it has the IP already). I would even adjust 0MQ for that, if somebody could point to the place where the IP is saved, couldn't find it. The socket types are not that important, at the moment. I would prefer smth REQ-REP like. Thank you!
Summary:
TL;DR answer to your question is: you can't get IP address of the peer that sent a message, using ZeroMQ API.
Explanation:
ZeroMQ does not expose peer IP address because it is irrelevant for the message based communication that ZeroMQ is designed for. When it is possible for ZeroMQ to get IP address of client that is connecting to server (in example using method described here), it is useless. For a longer explanation here is how it works inside ZeroMQ and any other server implementation.
Server side of the connection does not handle connected clients by the means of the hashtable that maps IP to client, but by keeping track of connected "sockets" (socket descriptors) - when a server accepts (using accept()) a connection, it receives from operating system socket descriptor to use to communicate with connected peer. All server has to do is keep that descriptor around to read() from and write() to that client. Another client that connects to server receives another socket descriptor.
To summarize: even if ZeroMQ would be able to provide you with IP of connected peer, you should not depend on it. ZeroMQ hides from you connection management so you can focus on messaging. Connection management includes reconnections, which may result in a change of IP without changing the actual ZeroMQ socket connected on the other side.
So here's an example of why you might want to get the ip address a message was delivered from: we have a server whose job it is to synchronize updates onto occasionally-connected clients (think mobile devices here, though this is an extreme example of a mobile deivce.)
When the mobile unit comes onto the network, it sends a list of it's firmware files to the server via a dealer-router connection. The server has a list of all applicable firmware files; if the client needs an update it will initiate an update via a separate mechanism.
Since the IPs for the devices can (and do) change, we need to know the IP address associated with the mobile device FOR THIS CONNECTION, i.e. right now.
Yes, we absolutely can have the client send it's IP address in the message, but that's a waste of another n bytes of valuable satellite air time, and while not pure evil, is sure annoying. Zmq already has this information, if it didn't have it, it wouldn't be able to generate replies. The address is in the socket data, there's no reason the message couldn't (optionally, for all you guys who use wired networks and think disconnects are the exception) include a reference to the socket structure so you can get the address out of it. Other than pedantic religiosity, which is far too common in zmq.
The way ZeroMQ is designed there's no information provided on the remote IP. As far as I know you have to manage this through your application by sending that information as a message of some sort.
The messages themselves use an IP-agnostic ID which has more to do with the instance of ZeroMQ running than any particular interface. This is because there may be more than one transport method and interface connecting the two instances.

Single socket sends and receives over both wlan and eth interface

Using C++ I create a single UDP socket, supplying both an IPv4 address and port. I run this on Ubuntu and have both a wlan0 and eth0 interface up and running. Apparently something decides that both interfaces should be used, I appreciate that. Sending and receiving using a different interface does create a kind of a pickle (NAT traversal???) for me though. Using Wireshark I can see packages coming in, but my application does not register them.
To clarify:
I have a tracker which will supply me with a peer. The tracker will also contact that peer to send me a message. In order to overcome NAT traversal issues, I will send a puncture message.
The problem now is that the puncture messages is sent over wlan (I am testing locally with two machines), whereas the messages from the peer are coming in over eth.
So, I think the simplest solution would be to simply use one interface. (Or both one socket)
EDIT:
I will try what is mentioned here on specifying a single interface.
#Barmar, pointed out that UDP sockets may change interface when sendto is called with a destination address that would benefit from it.
I am still fuzzy on the reason for my problem though. Can someone explain why this is an issue in the first place?
EDIT2:
The above mentioned solution of forcing one interface for the socket bind did not work. Apparently the sendto method will choose to ignore this and still go for the other interface if it feels that that will work better.
Does anyone know how to make sure that socket sticks to the interface it was assigned to?
If you need to ensure that UDP replies come from the same address that the request was sent to, the solution is to use multiple sockets. You open one socket for each IP of the server (this may be more than one socket per interface, because of interface aliases), and bind the socket to that IP. Then you use select() or poll() to wait for requests on all sockets at once. When a request comes in on a particular socket, you send the reply out through that same socket, and its source IP will match the original packet's destination.

Send same packets to multiple clients

I have to develop a software to send same packets to multiple destination.
But i must not use multicast scheme.!!!! ( because my boss is a stupid man )
so, any way, the problem is that:
i have same packets and multiple IP address ( clients) and i can not use multicast
how can i do that in the best way?
i must use c++ as a language and Linux as a platform.
so please help me
Thanx
If your boss said you can't use multicast, maybe he/she has his/her reason. I guess broadcasting is out of the game too?
If these are the requisites, your only chance is to establish a TCP connection with every remote host you want to send packet to.
EDIT
UDP, conversely, would not provide much benefit over multicasting if your application will run over a LAN you are in charge for configuration of, that's the reason I specified TCP.
Maybe you have to describe your scenario a little better.
This could be done with either TCP or UDP depending on your reliability requirements. Can you tolerate lost or reordered packets? Are you prepared to handle timeouts and retransmission? If both answers are "yes", pick UDP. Otherwise stay with TCP. Then:
TCP case. Instead of single multicast UDP socket you would have a number of TCP sockets, one per destination. You will have to figure out the best scheme for connection establishment. Regular listening and accepting connecting clients works as usual. Then you just iterate over connected sockets and send your data to each one.
UDP case. This could be done with single UDP socket on the server side. If you know the IPs and ports of the clients (data receivers) use sendto(2) on the same data for each address/port. The clients would have to be recv(2)-ing at that time. If you don't know your clients upfront you'd need to devise a scheme for clients to request the data, or just register with the server. That's where recvfrom(2) is usefull - it gives you the address of the client.
You have restricted yourself by saying no to multicast. I guess sending packets to multiple clients is just a part of your requirement and unless you throw more light, it will be difficult to provide a complete solution.
Are you expecting two way communication between the client and the server ? in that case choosing multicast may prove complex. please clarify
You have to iterate through the clients and send packets one after another. You may want to persist the sessions if you are expecting response from the clients back.
Choice of UDP or TCP again depends on the nature of data being sent. with UDP you would need to handle out of sequence packets and also need to implement re-transmission.
You'll have to create a TCP Listerner on your server running at a particular port listening for incoming Tcp Client connections (Sockets).
Every time a client connects, you'll have to cache it in some kind of datastructre like a Name value pair (name being a unique name for the client amd value being the Network Stream of that client obtained as a result of the TCP socket).
Then when you are finally ready to transmit the data you could either iterate through this collection of name value pair connections and send them data as byte array one by one to each client or spawm off one thread per connected client and have it send the data concurrently.
TCP is a bulky protocol (due to its connection-oriented nature) and transmission of large data (like videos/images) can be quite slow.
UDP is definitely the choice for streaming large data packets but you'll have to trade-off with the delivery gurantee.