I'm trying to set up a little test application on Linux (Ubuntu) based on some code I wrote (and that worked) for Winsock. As it stands now, it's just a little test that creates a socket (and seemingly successfully connects) only to hang eternally on recv() instead of receiving datagrams. It's a plain blocking socket.
Here's how I create it:
http://pastebin.com/kcCbgxbB
A few further things tested:
- Port is open.
- Other applications are able to receive data from the multicast address successfully.
So clearly I'm overlooking something. Help greatly appreciated :-)
In Unix systems, when using a socket for multicast you should bind to INADDR_ANY, not to a interface.
Multicast filtering by interface (i.e. not receive mcast from other interfaces than the specified one) is already in place because you are correctly filling imr_interface.
So, in the end a little system configuration and bugfixing went a long way:
a) As root, I'd had to do the following to disable the reverse packet filter:
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
+ The same for ethX.
b) Add a bogus route for the ethX (route add -net 224.0.0.0. netmask 224.0.0.0 ethX)
c) Bind the socket to the to-be-joined group's IP (otherwise any subsequent socket would get all packets from all groups I joined on that particular port).
d) Set the interface member of the ip_mreq struct to the IP of the adapter we're receiving on.
And then all was fine and dandy, test runs fast & smooth (pulling 125 multicast transport streams # around 800-900 mbit - sure this can be smarter, but still). Thanks for all the pointers.
Related
[Similar Questions]:
Problems using UDP sockets bound to the same port on Windows
Handling multiple UDP sockets listening on the same endpoint
None of which ever got resolved.
[Situation]:
On Microsoft Windows, I bind two UDP server sockets in the same process. This particular (not to say peculiar) operating system supports only SO_REUSEADDR, it does not support SO_REUSEPORT; and on top of that, SO_REUSEADDR acts like SO_REUSEPORT.
So, considering the above, I am left with binding socket A to 0.0.0.0:1234 and socket B to say 192.168.1.1:1234; if I'm to reuse the same port on the same machine.
Namely, I cannot bind both to the same IP address, since Microsoft Windows would not agree with that; since yet again, it does not support two sockets to be bound to exactly the same tuple of {SRC_ADDR,DST_ADDR, SRC_PORT,DST_PORT,PROTOCOL} even when SO_REUSEADDR is used on BOTH sockets.
So, I'm forced to bind to two distinct addresses, if I'm to use the same port on the same machine. Even though 0.0.0.0 represents any address, but in any case Microsoft Windows agrees, and binds the two sockets in such a configuration, without any error.
The binding operations, in such a configuration for the two UDP sockets, do succeed.
Problem:
Now, I'm having trouble getting these sockets to receive data as expected. Namely, I expect the two sockets to receive data. In reality, only the socket which got bound first receives data.
Any ideas?
Is it that the data is always received by the socket best matching the destination? If you wonder why I'm playing that way, it's because I'm trying to multiplex two libraries with two protocols over the same port, with the least amount of modifications.
If you want two ports are received same udp packet you should set option/flag broadcast for transmit socket.
Something like:
socket_.set_option(boost::asio::socket_base::broadcast(true));
In some cases (for some OS's) you should transmit packet to broadcast address instead of exact ip-address.
As a homework assignment, I wrote UDP server-client application that tries to correct errors in the UDP communication using checksums and through confirming correctly received packets.
The problem is that on localhost, all packets are received without a problem. I tried some packet tampering programs, but they all require communication through network interface.
How to simulate UDP packet loss on localhost loopback address?
UDP is easy to deal with--just write a bit of code in the sender or receiver which drops a certain percentage of the messages, and perhaps occasionally reorders some too.
If you can't modify the actual sender or receiver, it is easy enough to write a third program which simply sits in the middle, forwarding packets with some drops and reordering.
If you're using Linux, you can probably set up iptables to drop packets for you: http://code.nomad-labs.com/2010/03/11/simulating-dropped-packets-aka-crappy-internets-with-iptables/ - this seems like it might work even on loopback ports.
Given a local IP and port for an established TCP session, can I find out which side sent the initial SYN? That is, was this connection actively or passively opened? I need something that works in C/C++ on Linux. A hacky way might be to socket()/listen() and catch EADDRINUSE but I was hoping for something cleaner. I'm not even sure if the kernel tracks this once the session is established.
EDIT: I'd also prefer not to call out to netstat (or even ss) as both are too slow with many sockets open. This code will be called often.
Always the client makes an active connection, by sending a SYN(to the server). So, given a local IP and port number, check if its a listening socket using the following command:
netstat --listening | grep given_ip:given_port
If it is not listed here, then it is a client-side socket, thus initiates a SYN. If its there, then its a listening socket and hence it has received a SYN.
The corresponding code looks as follows:
system("netstat --listening | grep given_ip:given_port > tmp.txt");
int fd = open("tmp.txt", O_RDONLY);
char buf[100] ;
if(read(fd,buf,100)>0)
printf("The socket has received a SYN!");
else
printf("The socket has sent a SYN!");
EDIT:
If you feel netstat has poor speed to scan the entire ports, then the only way to achieve the fastness is to open a raw socket and set it to receive all the TCP packets.
Process only those packets which contain a SYN in them. Now, store both source address:port and destination address:port into two tables. One that is a sender of SYN and one that is a receiver.
Now, when you are given a port and ip-address, make a scan over the data stored so far. You can also use STL map of C++ to achieve faster results.
Since there can be many requests, the map may get filled up swiftly, making the look-ups slow. I advice you to process the FIN packets also and based on that remove the corresponding entries from the table.
I'm creating my own server using some protocols : TCP-PULL ok, TCP-PUSH ok, UDP-PULL ok (but I can't serve two clients at the same time!), UDP-PUSH ok (same problem).
Now, I need to create my the last protocol : Multicast-PUSH, but I can't understand how it works and I really don't know how to code it in C++. I've read about join a group and that in multicast there's no connection, so bytes are sent even if anyone is connected.
I'm coding in C++, using MFC libraries and CSockets.
Could please someone help?
Thank's!!
Consider an example where one system needs to send the same information to multiple systems. How best to accomplish this? The obvious approach is to have a socket "connection" for each target system. When data is ready to be sent, the sender iterates over each "connection," transmitting the data to the target system. This iteration process has to occur every time a message is sent, and it has to be robust such that if a transmission fails for one system, it doesn't fail for the remaining systems. But the problem is really worse than that because typically all the systems in a multicast exchange which to transmit data. This means that each system has to have a "connection" to each and every system wishing to participate.
This is where multicast comes in. In multicast, the sender sends data once to a specialized IP address and port called the multicast group. From there the network equipment, e.g., routers, take care of forwarding the data to the other systems in the multicast group. To achieve this, all systems wishing to participate in the multicast exchange have to "join" the multicast group, which happens during socket initialization and is used to simply notify the network equipment that the system wishes to participate in the multicast exchange. There is a special range of IPv4 addresses used for multicast - 224.0.0.0 to 239.255.255.255. You must use an IP address within this range and a port number of your choosing in order for multicast to work correctly.
Check out the Multicast Wrapper Class at CodeProject for an example of how to do this in MFC.
I need to be able to send and receive UDP packets on the same port.
I am able to listen, on say port 5000, but my send uses a random high port.
The system I am working written in VB with does this and my need is to write a UDP responder for debugging various protocol issues.
I am using the Open Source C++ Sockets Library from http://www.alhem.net (Anders Hedstrom) and have been able to use the UdpSocket::Bind() to receive incoming UDP packets using the virtual function UdpSocket::OnRawData(), but have been unable to cause the UdpSocket::Open() (calls connect) to make the UdpSocket::Send() use the port chosen in Bind() (it uses random high number port instead).
Moving the Open() function doesn't help. I have posted a request on their forum - but believe from what I have read that it should be possible to do this, and I'm probably not understanding how to use UDP.
Does anyone have any ideas on what I should try?
--thanks--
System consists of a number of nodes
listening on same port (different ip
addr's). System [A] sends datagram to
System [B]. System [B] asynchronously
responds and send datagram(s) back to
[A] all using same port. Even if [B]
identifies [A]'s port, [A] is not
listening on that port
I'm not sure I understand the "all using the same port" phrase in that sentence. If A sends a datagram to B, B will know A's IP and port right away (a quick check of your library documentation reveals OnRawData has a struct sockaddr *sa parameter, if you cast it to sockaddr_in* you'll be able to extract the IP:port pair). You can use that IP:port to send datagrams to and A will receive them. A is not "listening" on that port in the sense that it haven't called listen() on the socket, but since A owns a socket that is bound to that port (whether explicitly by calling bind() or assigned random port by the OS) it will receive the data.
Now if you want ALL your communication between nodes to go through your fixed port, you can do that. You just have to send all your datagrams through your "listening" socket. If every node "listens" on the same port, it means every node owns a socket that is bound to that port. If you want datagrams sent from A to B to appear coming from this fixed port you have to send them through that socket. I'm guessing that's why bind() doesn't work for your sending socket - A has a socket bound to port X, then you create another socket and try to bind it to the same port X, bind() fails since the port is already taken (and you don't check for errors :), and then the OS assigns random free port above 1024.
Note 1: I use "listening" in quotes everywhere, because the concept is not very clear in the context of UDP sockets. Once you have created socket and bound it to a port, either by calling bind() explicitly or by sending data and letting the OS bind it to a port, you can receive data from everywhere through it. No listen() or accept() calls needed.
Note 2: You say that UdpSocket::Open() calls connect(), but that doesn't make much sense - connect() does very little for UDP sockets - it merely establishes a default address so you can use send() instead of sendto() and not specify address on every send.
Hope that clears things up.
Edit to address OP's comment: I've never used this library but according their UdpSocket documentation there are 4 overloads of the Bind() method and every single one of them accepts port in some way. None of them works for you?
A bidirectional communication link always involves two participants: a server-side and a client-side.
The client expects to communicate to a server on a defined port: that's why on the server-side one must bind() to a socket.
On the client-side, one must open a socket to the server: it doesn't really matter which socket is chosen (except for the need for it to be free).
In other words, don't try to specify a socket on the client-side: the network protocol stack will assign it to your client.