sending a packet to multiple client at a time from udp socket - sockets

I was trying to write a udp server who send an instance of a file to multiple clients.Now suppose any how I manage to know the address of those client statically(for the sake of simplicity) and now I want to send this packet to these addresses.So how exactly I need to fill the sockaddr structure to contain the address of these clients.I am taking an array of sockaddr structure(to contain client address) and trying to send at each one them at a time.Now problem is to fill the individual sockaddr structure to contain the client address.
I was trying to do something like that
sa[1].sin_family = AF_INET;
sa[1].sin_addr.s_addr = htonl(INADDR_ANY);//should'nt I replace this INADDR_ANY with client ip??
sa[1].sin_port = htons(50002);
Correct me if this is not the correct way.
All your help in this regard will be highly appreciated.
With Thanks in advance,
Mawia

sin_addr should be set to the destination address.
if (! inet_aton("1.2.3.4", &sa[1].sin_addr)) {
// Give up all hope
}
// Everything is copacetic.

Looks like you're talking about multicast. It is a bit harder than trivial.
Take a look at this thread to discover how to subscribe to a multicast group (for the client side) and how to send multicast packets (for the server side). It is discussed using python, but only low-level wrappers around socket library are used, so it should be quite simple to translate examples to any language.

As mentioned in a different answer, you're talking about multicast, but on the public Internet, that requires ISP support.
There is such a thing as an application level multicast infrastructure. This writeup, dating back to 2000, describes one such method.

Related

Switching to websocket from simple Berkeley socket

I have a simple socket implementation which uses the standard low-level Berkeley socket functions (bind, listen, accept, read, etc).
This socket listens on a port, let's say X.
Now what I'm trying to achieve is to make Simple-WebSocket-Server to listen also on this port X.
Of course this is not possible by nature - I know.
My intention is this: In my simple socket implementation I would detect if the connected client (after accepting) is my client or a websocket one, then if I find the client to be a websocket one, I would pass the whole thing into this library to behave the same as like it was the one have accepted this client.
What would be good to hand over the socket's fd, along with a first bytes that my socket read before noticing a websocket request.
I'm a bit stuck on would be the best to do this, but I don't want to reimplement the whole websocket stuff for sure.
The tricky thing here is that the Simple-WebSocket-Server does its own accept, so I don't there is a way to had over to it a fd together with an array of "first bytes".
Some approaches I could think of:
modify the Simple-WebSocket-Server so that instead of closing a non-WS client or timing-out, it makes a call to your library
instead use something like websocketpp to create your own websocket server, and then select between the two servers (I did something similar for one of my own projects, where I had to detect the socket protocol from the first byte and then select an appropriate protocol handler wampcc protcol selector)
or, you could try to have the Simple-WebSocket-Server listen on a different port Y; you also listen on X, and if detect a web-socket client on X, you internally create an internal pair of queues and then open a connection to localhost:Y, and proceed to transfer bytes between the pair of sockets; this way you don't need to modify the Simple-WebSocket-Server code.

What is the goal of using GGP(0x0003) as a protocol parameter in socket()

I started to program a packet sniffer, And I have searched for the correct parameters to pass to socket() function in order to capture packets with their Ethernet header.
I noticed that in this tutorial , In order to recieve the Ethernet header, they changed this line:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
To this line:
s = socket.socket( socket.AF_PACKET , socket.SOCK_RAW , socket.ntohs(0x0003))
And my questions are:
I understood from this link that AF_INET with raw socket won't give me the Ethernet header. My question is why?
Why he also changed from IPPROTO_TCP to ntohs(0x0003) which I know that this is GGP protocol. As far as I understood, the third parameter states the protocol which the socket will recieve. If the protocol parameter is GGP, then the socket will look for packets who have GGP as their internet layer protocol, isn't? then why they pass GGP and not TCP or IP? After all, almost every PDU has IP and\or TCP\UDP as their data protocols.. Does it matter what's the third parameter for my packet sniffer?
In addition to the second question, I think that I didn't get the objective of the third parameter. If this is IPPROTO_TCP, the socket will capture packets with TCP in the network layer (and not UDP for example)? and if i'll pass IPPROTO_IP, the socket will capture packets with IP as their internet layer protocol, without checking the other layer's protocols (It doesn't matter for the socket what protocol is used for the network layer? It only cares that IP is exists as the internet layer protocol)?
Thanks and sorry for the grammer mistakes (English isn't my first language).
If you check linux/if_ether.h you will see
#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
So the value of ETH_P_ALL is 0x0003. The authors of this tutorial use 0x0003 instead of ETH_P_ALL because in some systems when used in python a "not defined" error occurs.
The raw socket feature can be set up at different layers of the network stack, in order to allow the kernel do perform some of the work for you at lower levels (eg: ethernet crafting).
The change to GGP protocol might make sense on the website you found the example, but it is ugly to do so and getprotoent() should be used rather than using magic numbers.
Yes you can tweak (filter) how the packet capture will happen. If you want to capture all packets then use ETH_P_ALL:
When protocol is set to htons(ETH_P_ALL) then all protocols are
received.

does socket.h's recvfrom() function recieve individual packets?

The man page for recvfrom summarizes its behavior as "receive a message from a socket". If the socket is of type SOCK_STREAM or SOCK_DGRAM, is "message" synonymous with "packet"? If not, how does it differ?
My first thought was recvfrom works on stream sockets just because there's no reason to ban it. As in the famous quote:
"Unix was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things." – Doug Gwyn
If it did what I expected it to do, you could use it like a combination read() and getpeername() since it returns the sender's address. That might be considered clever.
But then I tried it on Linux, and it didn't work that way. The source address buffer was unchanged and the length indicator was set to 0.
So now I'm not sure what to say except don't use it on stream sockets. It's not meant for them.
ADDENDUM: And no, even in my wildest dreams I wouldn't have expected it to give you access to packet boundaries in a TCP stream. Data that has been put through the tcp receiving mechanism simply isn't made of packets anymore.

How to determine who wrote what to a socket, given 2 writers?

Say one part of a program writes some stuff to a socket and another part of the same program reads stuff from that same socket. If an external tool writes to that very same socket, how would I differentiate who wrote what to the socket (using the part that reads it)? Would using a named pipe work?
If you are talking about TCP the situation you describe is impossible, because connections are 1-to-1. If you mean UDP, you can get the sender address by setting the appropriate flags in the recvmesg() function.

Can UDP (unicast client) recvfrom() other servers other than the one sendto()?

I am creating a UDP socket client in C (unicast) and is wondering why recvfrom() has a struct sockaddr * argument in which in the man page says,
A null pointer, or points to a sockaddr structure in which the sending address is to be stored.
Is it possible that I could receive a message from a different server other than the one I sendto? If yes, how to create this scenario?
If no, is it correct to say that this argument is only useful when broadcast mode is used?
Yes, this is perfectly possible. The reason for this is that UDP is not stream-based, but packet-based. Every packet is treated without any history (other packets sent or received).
For this reason you may also open a UDP port and then send packets to different hosts from it. However, I do not remember how well this is supported by the API.
The UDP socket will recvfrom() any host sending to this one with correct port unless you explicitly connect(), in which case you can just write() and read(), and get errors upon received ICMP messages.
Considering you always have two parties in UDP, it seems rather obvious that someone has to recvfrom() first.