Here is the code. It is the same as the code from this similar question: http://monkey.org/freebsd/archive/freebsd-stable/200401/msg00032.html. When I run it I always get the output:
listening on 0.0.0.0:54493 or something. Obviously the port changes, but I have no idea why I keep getting an IP address of 0.0.0.0. Am I missing something?
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
int sock;
int len = sizeof(struct sockaddr);
struct sockaddr_in addr, foo;
if((sock=socket(AF_INET, SOCK_STREAM, 0))<0)
{
exit(0);
}
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(0);
if(bind(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in))<0)
{
perror("bind");
exit(0);
}
if(listen(sock, 5)<0)
{
perror("listen");
exit(0);
}
getsockname(sock, (struct sockaddr *) &foo, &len);
fprintf(stderr, "listening on %s:%d\n", inet_ntoa(foo.sin_addr),
ntohs(foo.sin_port));
return 0;
}
You specify INADDR_ANY rather than a specific IP address, so it binds to the wildcard (all interfaces) 0.0.0.0. So, when you call getsockname() that's what you get back.
If you specified 0.0.0.0 as the IP address rather than INADDR_ANY you would get the same behavior; you will bind to all network interfaces on the machine.
For example, lets say you only have one network interface with the IP 192.168.1.12 assigned to it. You also have the loopback by default - 127.0.0.1
Using 0.0.0.0 or INADDR_ANY means you'll be bound to both those addresses, rather than a specific one. You will be able to connect to to your process via either IP.
If you were to bind to a specific IP rather than INADDR_ANY, your process would only listen on that IP and you'd get back that specific IP with getsockname().
Yes, if you bind it to a LOOPBACK , u have to specify INADDR_LOOPBACK.
Otherwise it attaches itself to 0.0.0.0 which represents all the network interfaces available. I was facing the same problem, while issuing getnameinfo() call.
As mentioned in the other answers, 0.0.0.0 is returned because INADDR_ANY was specified as the host address for the listening socket. This makes sense if you think that, in a multi-homed host, client connections could come in on any of those interfaces (so which should be reported?)
Expanding on those answers; if the actual IP address of a client connection is required, use the SOCKET returned from accept() with getsockname(). This will provide the interface address on the server to which the client connected.
Related
I am trying to bind my local IPv6 address to a socket. But always get "invalid argument". The reason I want to bind the specific IP address to socket is that if I don't bind the error "No route to host" came up. When I tried to ping an IPv6 address with command below it does not work.
ping6 fe80::7ed1:c3ff:fe86
I have to point out from which interface I want to send the packet.
ping6 -I en1 fe80::7ed1:c3ff:fe86
And this works fine. So I think if I bind the socket to the interface then I can send the packet successfully.
Anyone can tell me how to send an IPv6 address without specify the interface or how to solve this problem of binding?
Here are the codes.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>
#define LOCALADDR "fe80::7ed1:c3ff:fe86:ddae"
int main(void)
{
int sock,status;
struct addrinfo local_addr;
struct addrinfo *servinfo;
char buffer[1024];
/* create a DGRAM (UDP) socket in the INET6 (IPv6) protocol */
sock = socket(PF_INET6, SOCK_DGRAM, 0);
if (sock < 0) {
perror("creating socket");
exit(1);
}
/*Binding specific interface to socket*/
memset(&local_addr, 0, sizeof(local_addr));
local_addr.ai_family = AF_INET6;
local_addr.ai_socktype = SOCK_DGRAM;
local_addr.ai_flags = AI_PASSIVE;
if ((status = getaddrinfo(NULL, "3535", &local_addr, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
if (bind(sock, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0)
error("ERROR on binding");
I have also tried to replace "NULL" in the "getaddrinfo" to be "LOCALADDR".
if ((status = getaddrinfo(LOCALADDR, "3535", &local_addr, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
And I still get the same problem.
I can successfully binding the socket with "in6addr_any",but then I get the error "No route to host".
That is a link-local IPv6 address, not a routable IPv6 address. The link-local addresses are specific to a link, and each link can have the same addresses as the other links. For instance if you have three different interfaces, you can assign the same link-local address to each of the interfaces. To use a link-local address, you need to specify the interface so that the OS knows which link to use. All the interfaces will have a link-local address in the same network: fe80::/10.
If you use a routable IPv6 address, you will not need to specify an interface.
You are creating the socket incorrectly. The 'domain' (first argument) should be AF_INET6, not PF_INET6. I am uncertain whether these in fact expand to different values in your environment, but the AF_* macros are the ones designated for this purpose.
Otherwise, for a socket that accepts connections, you should get an address much the way you first present. In particular, the docs for getaddrinfo() say
If the AI_PASSIVE flag is specified in hints.ai_flags, and node is NULL, then the returned socket addresses will be suitable for bind(2)ing a socket that will accept(2) connections. The returned socket address will contain the "wildcard address" (INADDR_ANY for IPv4 addresses, IN6ADDR_ANY_INIT for IPv6 address). The wildcard address is used by applications (typically servers) that intend to accept connections on any of the hosts’s network addresses. If node is not NULL, then the AI_PASSIVE flag is ignored.
Thus, you certainly could and probably should specify a NULL first argument.
Note, however, that getaddrinfo() returns a linked list of addresses, and under some circumstances it is necessary to choose a different one than the first. I think the first ought to be fine in this particular case, though.
Do also be aware that a "no route to host" message from a client trying to connect does not necessarily indicate that the server is not listening. It could well be that the client is using the wrong address (c.f. #RonMaupin's answer) or, just as it says, that there is no (known) route through the network from the client to the server. That could arise because of router or firewall configuration, for example.
Both connect() and bind() system calls 'associate' the socket file descriptor to an address (typically an ip/port combination). Their prototypes are like:-
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
and
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
What is the exact difference between 2 calls? When should one use connect() and when bind()?
Specifically, in some sample server client codes, found that client is using connect() and server is using the bind() call. Reason was not fully clear to me.
To make understanding better , lets find out where exactly bind and connect comes into picture,
Further to positioning of two calls , as clarified by Sourav,
bind() associates the socket with its local address [that's why server side binds, so that clients can use that address to connect to server.]
connect() is used to connect to a remote [server] address, that's why is client side, connect [read as: connect to server] is used.
We cannot use them interchangeably (even when we have client/server on same machine) because of specific roles and corresponding implementation.
I will further recommend to correlate these calls TCP/IP handshake .
So, who will send SYN here, it will be connect(). While bind() is used for defining the communication end point.
The one liner : bind() to own address, connect() to remote address.
Quoting from the man page of bind()
bind() assigns the address specified by addr to the socket referred to by the file descriptor sockfd. addrlen specifies the size, in bytes, of the address structure pointed to by addr. Traditionally, this operation is called "assigning a name to a socket".
and, from the same for connect()
The connect() system call connects the socket referred to by the file descriptor sockfd to the address specified by addr.
To clarify,
bind() associates the socket with its local address [that's why
server side binds, so that clients can use that address to connect
to server.]
connect() is used to connect to a remote [server] address, that's
why is client side, connect [read as: connect to server] is used.
I think it would help your comprehension if you think of connect() and listen() as counterparts, rather than connect() and bind(). The reason for this is that you can call or omit bind() before either, although it's rarely a good idea to call it before connect(), or not to call it before listen().
If it helps to think in terms of servers and clients, it is listen() which is the hallmark of the former, and connect() the latter. bind() can be found - or not found - on either.
If we assume our server and client are on different machines, it becomes easier to understand the various functions.
bind() acts locally, which is to say it binds the end of the connection on the machine on which it is called, to the requested address and assigns the requested port to you. It does that irrespective of whether that machine will be a client or a server. connect() initiates a connection to a server, which is to say it connects to the requested address and port on the server, from a client. That server will almost certainly have called bind() prior to listen(), in order for you to be able to know on which address and port to connect to it with using connect().
If you don't call bind(), a port and address will be implicitly assigned and bound on the local machine for you when you call either connect() (client) or listen() (server). However, that's a side effect of both, not their purpose. A port assigned in this manner is ephemeral.
An important point here is that the client does not need to be bound, because clients connect to servers, and so the server will know the address and port of the client even though you are using an ephemeral port, rather than binding to something specific. On the other hand, although the server could call listen() without calling bind(), in that scenario they would need to discover their assigned ephemeral port, and communicate that to any client that it wants to connect to it.
I assume as you mention connect() you're interested in TCP, but this also carries over to UDP, where not calling bind() before the first sendto() (UDP is connection-less) also causes a port and address to be implicitly assigned and bound. One function you cannot call without binding is recvfrom(), which will return an error, because without an assigned port and bound address, there is nothing to receive from (or too much, depending on how you interpret the absence of a binding).
bind tells the running process to claim a port. i.e, it should bind itself to port 80 and listen for incomming requests. with bind, your process becomes a server. when you use connect, you tell your process to connect to a port that is ALREADY in use. your process becomes a client. the difference is important: bind wants a port that is not in use (so that it can claim it and become a server), and connect wants a port that is already in use (so it can connect to it and talk to the server)
From Wikipedia http://en.wikipedia.org/wiki/Berkeley_sockets#bind.28.29
connect():
The connect() system call connects a socket, identified by its file descriptor, to a remote host specified by that host's address in the argument list.
Certain types of sockets are connectionless, most commonly user datagram protocol sockets. For these sockets, connect takes on a special meaning: the default target for sending and receiving data gets set to the given address, allowing the use of functions such as send() and recv() on connectionless sockets.
connect() returns an integer representing the error code: 0 represents success, while -1 represents an error.
bind():
bind() assigns a socket to an address. When a socket is created using socket(), it is only given a protocol family, but not assigned an address. This association with an address must be performed with the bind() system call before the socket can accept connections to other hosts. bind() takes three arguments:
sockfd, a descriptor representing the socket to perform the bind on.
my_addr, a pointer to a sockaddr structure representing the address to bind to.
addrlen, a socklen_t field specifying the size of the sockaddr structure.
Bind() returns 0 on success and -1 if an error occurs.
Examples:
1.)Using Connect
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(){
int clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set the IP address to desired host to connect to */
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.17");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Connect the socket to the server using the address struct ----*/
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
/*---- Read the message from the server into the buffer ----*/
recv(clientSocket, buffer, 1024, 0);
/*---- Print the received message ----*/
printf("Data received: %s",buffer);
return 0;
}
2.)Bind Example:
int main()
{
struct sockaddr_in source, destination = {}; //two sockets declared as previously
int sock = 0;
int datalen = 0;
int pkt = 0;
uint8_t *send_buffer, *recv_buffer;
struct sockaddr_storage fromAddr; // same as the previous entity struct sockaddr_storage serverStorage;
unsigned int addrlen; //in the previous example socklen_t addr_size;
struct timeval tv;
tv.tv_sec = 3; /* 3 Seconds Time-out */
tv.tv_usec = 0;
/* creating the socket */
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
printf("Failed to create socket\n");
/*set the socket options*/
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
/*Inititalize source to zero*/
memset(&source, 0, sizeof(source)); //source is an instance of sockaddr_in. Initialization to zero
/*Inititalize destinaton to zero*/
memset(&destination, 0, sizeof(destination));
/*---- Configure settings of the source address struct, WHERE THE PACKET IS COMING FROM ----*/
/* Address family = Internet */
source.sin_family = AF_INET;
/* Set IP address to localhost */
source.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY = 0.0.0.0
/* Set port number, using htons function to use proper byte order */
source.sin_port = htons(7005);
/* Set all bits of the padding field to 0 */
memset(source.sin_zero, '\0', sizeof source.sin_zero); //optional
/*bind socket to the source WHERE THE PACKET IS COMING FROM*/
if (bind(sock, (struct sockaddr *) &source, sizeof(source)) < 0)
printf("Failed to bind socket");
/* setting the destination, i.e our OWN IP ADDRESS AND PORT */
destination.sin_family = AF_INET;
destination.sin_addr.s_addr = inet_addr("127.0.0.1");
destination.sin_port = htons(7005);
//Creating a Buffer;
send_buffer=(uint8_t *) malloc(350);
recv_buffer=(uint8_t *) malloc(250);
addrlen=sizeof(fromAddr);
memset((void *) recv_buffer, 0, 250);
memset((void *) send_buffer, 0, 350);
sendto(sock, send_buffer, 20, 0,(struct sockaddr *) &destination, sizeof(destination));
pkt=recvfrom(sock, recv_buffer, 98,0,(struct sockaddr *)&destination, &addrlen);
if(pkt > 0)
printf("%u bytes received\n", pkt);
}
I hope that clarifies the difference
Please note that the socket type that you declare will depend on what you require, this is extremely important
Too Long; Don't Read: The difference is whether the source (local) or the destination address/port is being set. In short, bind() set the source and connect() set the destination. Regardless of TCP or UDP.
bind()
bind() set the socket's local (source) address. This is the address where packets are received. Packets sent by the socket carry this as the source address, so the other host will know where to send back its packets.
If receive is not needed the socket source address is useless. Protocols like TCP require receiving enabled in order to send properly, as the destination host send back a confirmation when one or more packets have arrived (i.e. acknowledgement).
connect()
TCP has a "connected" state. connect() triggers the TCP code to try to establish a connection to the other side.
UDP has no "connected" state. connect() only set a default address to where packets are sent when no address is specified. When connect() is not used, sendto() or sendmsg() must be used containing the destination address.
When connect() or a send function is called, and no address is bound, Linux automatically bind the socket to a random port. For technical details, take a look at inet_autobind() in Linux kernel source code.
Side notes
listen() is TCP only.
In AF_INET family, the socket's source or destination address (struct sockaddr_in) is composed by an IP address (see IP header), and TCP or UDP port (see TCP and UDP header).
I'm having trouble to use bind method on Windows (C language). Well. My code is supposed to do the following things:
get 2 addresses from the user: One must be an ip address from the local machine and another a remote address ( a google address for example).
The application i'm writing will bind to the local address
The application will connect to the second address.
I got some code from the Internet. You can see all the sources i had consulted on the comments.
This application will only accepts a string from the client (which specifies the local
address which the application will bind), then, the app will connect to a remote service
google, youtube or whatever. The main purpose that this app serves is to know if, when
binded to a local address, the operative system (in this case Windows Based system) gives priority to:
- SA/DA rule
- Forwarding table
SOURCES:
http://stackoverflow.com/questions/2065495/using-a-specific-network-interface-for-a-socket-in-windows
http://stackoverflow.com/questions/2605182/when-binding-a-client-tcp-socket-to-a-specific-local-port-with-winsock-so-reuse
http://www.delta-search.com/?q=error+on+binding+to+local+address%2Cwindows&s=web&as=0&rlz=0&babsrc=HP_ss
http://social.msdn.microsoft.com/Forums/zh/vcgeneral/thread/763a00ab-0e7f-44c6-9794-840fc6cb2e07
http://www.delta-search.com/?q=add+ws2_32.lib+visual+studio+2010&babsrc=HP_ss&s=web&rlz=0&as=3&ac=0%2C331
http://stackoverflow.com/questions/5220309/why-am-i-getting-linker-errors-for-ws2-32-dll-in-my-c-program
http://msdn.microsoft.com/en-US/windows/desktop/aa904949
http://msdn.microsoft.com/en-us/library/windows/desktop/ms737550(v=vs.85).aspx
#pragma once
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <Ws2tcpip.h>
#include <stdio.h>
void Abort(char *msg);
void main(int argc,char*argv[]){
int ret, fd;
struct sockaddr_in sa_dst;
struct sockaddr_in sa_loc;
if(argc < 3)
Abort("Syntax: SourceIpAddress(to bind) DestinationIpAddress(to connect)");
fd = socket(AF_INET, SOCK_STREAM, 0);
// Local
memset(&sa_loc, 0, sizeof(struct sockaddr_in));
sa_loc.sin_family = AF_INET;
sa_loc.sin_port = htons(0);
sa_loc.sin_addr.s_addr = inet_addr(argv[1]);
if((ret = bind(fd, (struct sockaddr *)&sa_loc, sizeof(struct sockaddr))) < 0)
Abort("Binding to local address");
// Remote
memset(&sa_dst, 0, sizeof(struct sockaddr_in));
sa_dst.sin_family = AF_INET;
sa_dst.sin_port = htons(80);
sa_dst.sin_addr.s_addr = inet_addr(argv[2]); // google :)
if((ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr))) < 0)
Abort("Connect to remote address");
printf("\n\nConnection Successfully made!!\n\n"); }
void Abort(char *msg){
fprintf(stderr,"\n\n<ERROR>: <%s>\n",msg);
perror("\n\nExiting...");
exit(EXIT_FAILURE); }
The problem is that bind returns -1. I've tested already.
Can anyone help me on this?
Thanks in advance
When a Winsock function fails, you can call WSAGetLastError() to find out why.
In this case, you are not calling WSAStartup(), so socket() fails with a WSANOTINITIALISED error that you are ignoring, so you end up passing an invalid socket to bind().
I'm having trouble figuring this out - I'm working with sockets in C using this guide - http://binarii.com/files/papers/c_sockets.txt
I'm trying to automatically get my ip and port using:
server.sin_port = 0; /* bind() will choose a random port*/
server.sin_addr.s_addr = INADDR_ANY; /* puts server's IP automatically */
...
...
bind(int fd, struct sockaddr *my_addr,int addrlen); // Bind function
After a successful bind, how do I find out what IP and Port I'm actually assigned?
If it's a server socket, you should call listen() on your socket, and then getsockname() to find the port number on which it is listening:
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if (getsockname(sock, (struct sockaddr *)&sin, &len) == -1)
perror("getsockname");
else
printf("port number %d\n", ntohs(sin.sin_port));
As for the IP address, if you use INADDR_ANY then the server socket can accept connections to any of the machine's IP addresses and the server socket itself does not have a specific IP address. For example if your machine has two IP addresses then you might get two incoming connections on this server socket, each with a different local IP address. You can use getsockname() on the socket for a specific connection (which you get from accept()) in order to find out which local IP address is being used on that connection.
The comment in your code is wrong. INADDR_ANY doesn't put server's IP automatically'. It essentially puts 0.0.0.0, for the reasons explained in mark4o's answer.
I have an application that is receiving data from multiple multicast sources on the same port. I am able to receive the data. However, I am trying to account for statistics of each group (i.e. msgs received, bytes received) and all the data is getting mixed up. Does anyone know how to solved this problem? If I try to look at the sender's address, it is not the multicast address, but rather the IP of the sending machine.
I am using the following socket options:
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("224.1.2.3");
mreq.imr_interface.s_addr = INADDR_ANY;
setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
and also:
setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse));
After some years facing this linux strange behaviour, and using the bind workaround describe in previous answers, I realize that the ip(7) manpage describe a possible solution :
IP_MULTICAST_ALL (since Linux 2.6.31)
This option can be used to modify the delivery policy of
multicast messages to sockets bound to the wildcard INADDR_ANY
address. The argument is a boolean integer (defaults to 1).
If set to 1, the socket will receive messages from all the
groups that have been joined globally on the whole system.
Otherwise, it will deliver messages only from the groups that
have been explicitly joined (for example via the
IP_ADD_MEMBERSHIP option) on this particular socket.
Then you can activate the filter to receive messages of joined groups using :
int mc_all = 0;
if ((setsockopt(sock, IPPROTO_IP, IP_MULTICAST_ALL, (void*) &mc_all, sizeof(mc_all))) < 0) {
perror("setsockopt() failed");
}
This problem and the way to solve it enabling IP_MULTICAST_ALL is discussed in Redhat Bug 231899, this discussion contains test programs to reproduce the problem and to solve it.
[Edited to clarify that bind() may in fact include a multicast address.]
So the application is joining several multicast groups, and receiving messages sent to any of them, to the same port. SO_REUSEPORT allows you to bind several sockets to the same port. Besides the port, bind() needs an IP address. INADDR_ANY is a catch-all address, but an IP address may also be used, including a multicast one. In that case, only packets sent to that IP will be delivered to the socket. I.e. you can create several sockets, one for each multicast group. bind() each socket to the (group_addr, port), AND join group_addr. Then data addressed to different groups will show up on different sockets, and you'll be able to distinguish it that way.
I tested that the following works on FreeBSD:
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
const char *group = argv[1];
int s = socket(AF_INET, SOCK_DGRAM, 0);
int reuse = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)) == -1) {
fprintf(stderr, "setsockopt: %d\n", errno);
return 1;
}
/* construct a multicast address structure */
struct sockaddr_in mc_addr;
memset(&mc_addr, 0, sizeof(mc_addr));
mc_addr.sin_family = AF_INET;
mc_addr.sin_addr.s_addr = inet_addr(group);
mc_addr.sin_port = htons(19283);
if (bind(s, (struct sockaddr*) &mc_addr, sizeof(mc_addr)) == -1) {
fprintf(stderr, "bind: %d\n", errno);
return 1;
}
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(group);
mreq.imr_interface.s_addr = INADDR_ANY;
setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
char buf[1024];
int n = 0;
while ((n = read(s, buf, 1024)) > 0) {
printf("group %s fd %d len %d: %.*s\n", group, s, n, n, buf);
}
}
If you run several such processes, for different multicast addresses, and send a message to one of the addresses, only the relevant process will receive it. Of course, in your case, you probably will want to have all the sockets in one process, and you'll have to use select or poll or equivalent to read them all.
Use setsockopt() and IP_PKTINFO or IP_RECVDSTADDR depending on your platform, assuming IPv4. This combined with recvmsg() or WSARecvMsg() allows you to find the source and destination address of every packet.
Unix/Linux, note FreeBSD uses IP_RECVDSTADDR whilst both support IP6_PKTINFO for IPv6.
http://www.kernel.org/doc/man-pages/online/pages/man7/ip.7.html
Windows, also has IP_ORIGINAL_ARRIVAL_IF
http://msdn.microsoft.com/en-us/library/ms741645(v=VS.85).aspx
Replace
mc_addr.sin_addr.s_addr = htonl(INADDR_ANY);
with
mc_addr.sin_addr.s_addr = inet_addr (mc_addr_str);
it's help for me (linux), for each application i receive separate mcast stream from separate mcast group on one port.
Also you can look into VLC player source, it show many mcast iptv channel from different mcast group on one port, but i dont know, how it separetes channel.
I have had to use multiple sockets each looking at different multicast group addresses, and then count statistics on each socket individually.
If there is a way to see the "receiver's address" as mentioned in the answer above, I can't figure it out.
One important point that also took me awhile - when I bound each of my individual sockets to a blank address like most python examples do:
sock[i].bind(('', MC_PORT[i])
I got all the multicast packets (from all multicast groups) on each socket, which didn't help. To fix this, I bound each socket to it's own multicast group
sock[i].bind((MC_GROUP[i], MC_PORT[i]))
And it then worked.
IIRC recvfrom() gives you a different read address/port for each sender.
You can also put a header in each packet identifying the source sender.
The Multicast address will be the receiver's address not sender's address in the packet. Look at the receiver's IP address.
You can separate the multicast streams by looking at the destination IP addresses of the received packets (which will always be the multicast addresses). It is somewhat involved to do this:
Bind to INADDR_ANY and set the IP_PKTINFO socket option. You then have to use recvmsg() to receive your multicast UDP packets and to scan for the IP_PKTINFO control message. This gives you some side band information of the received UDP packet:
struct in_pktinfo {
unsigned int ipi_ifindex; /* Interface index */
struct in_addr ipi_spec_dst; /* Local address */
struct in_addr ipi_addr; /* Header Destination address */
};
Look at ipi_addr: This will be the multicast address of the UDP packet you just received. You can now handle the received packets specific for each multicast stream (multicast address) you are receiving.