Get address family from socket. Linux
Damn. Searched about half an hour. Now after posting this question I found immiediately the answer.
getsockopt([...]) with option SO_DOMAIN (see socket options)
Query an existing socket's address family in Python
You just pass the file descriptor to socket.socket
, giving it as the fileno=
keyword attribute. The socket class figures out the type of socket corresponding to the file descriptor. You can then find the family as @klaus suggested: with s.family
.
import socket
s = socket.socket()
print("original socket", s)
desc = s.fileno()
print("file descriptor", type(desc), desc)
new_s = socket.socket(fileno=desc)
print("new socket", new_s.family, int(new_s.family))
Here I'm creating a socket in python, but then extracting the file descriptor from the socket object (producing an ordinary int
containing the descriptor number) so as to demonstrate putting it back into a new socket object. Running the above produces:
original socket <socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 0)>
file descriptor <class 'int'> 3
new socket AddressFamily.AF_INET 2
EDIT
Hmm... the above method does not seem to work with AF_INET6
sockets, at least in my python 3.5.2 version.
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
new_s = socket.socket(fileno=s.fileno())
print(new_s)
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('::%1', 0, 0, 1)>
That seems like a clear bug to me. The documentation says:
If fileno is specified, the values for family, type, and proto are auto-detected from the specified file descriptor.
You may need to examine new_s.laddr
and heuristically determine the family. (For AF_INET6
, laddr
will be a 4-tuple, whereas AF_INET
uses a 2-tuple). If you expect AF_UNIX
or other families, you might need to extend that.
(How) Can I determine the socket family from the socket file descriptor
See getsockname(2). You then inspect the struct sockaddr for the family.
EDIT: As a side note, its sometimes useful to query info as well, in this case info libc sockets
EDIT:
You really can't know without looking it up every time. It can't be simply cached, as the socket number can be reused by closing and reopening it. I just looked into the glibc code and it seems getsockname is simply a syscall, which could be nasty performance-wise.
But my suggestion is to use some sort of object-oriented concepts. Make the user pass a pointer to a struct you had previously returned to him, i.e. have him register/open sockets with your API. Then you can cache whatever you want about that socket.
Address family of socket is mentioned in structure and socket creation why?
socket()
creates a new socket. It needs to know what its address family is so it knows what kind of addresses it is allowed to work with, whether that be IPv4, IPv6, IPX, NetLink, etc. The address family dictates the layout and format for its address values. For instance, AF_INET
only allows IPv4 addresses, whereas AF_INET6
allows IPv6 addresses (and IPv4 addresses if the socket is set to dual-stack mode on platforms that support that feature).
Every sockaddr_...
structure has a family field. sockaddr_...
structures can be passed around to various functions, which need to know what type of address they are receiving as input, and can specify what type of address they are returning as output.
The sockaddr_in
structure is specific to IPv4 addresses only, where its sin_addr
field specifies the IPv4 address as a 32bit integer in network byte order. The same is not true of other sockaddr_...
structures.
There is a special sockaddr_storage
structure that is typically used when writing code that works with multiple addresses families, especially when calling functions that can accept multiple sockaddr_...
types.
So it is important not only for the socket to be told what its address family is, but it is also important for individual addresses to specify their own types as well. Typically, these values will match each other (except in the case of dual-stack sockets).
What is Address Family?
Members of AF_INET
address family are IPv4 addresses.
Members of AF_INET6
address family are IPv6 addresses.
Members of AF_UNIX
address family are names of Unix domain sockets (/var/run/mysqld/mysqld.sock
is an example).
Members of AF_IPX
address family are IPX addresses, and so on. I don't think you really need to distinguish between family and type here. They are merely synonyms, except that family looks like more specialized, well-suited for this purpose, whilst type is a too much general word.
How can I get the address and port of a client in C sockets (sys/socket.h)?
You can extract it from a struct sockaddr_in
(or sockaddr_in6
).
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
See the man page: http://man7.org/linux/man-pages/man7/ip.7.html
Also, you can see my DNS-server code as a practical example (there is extracted IPV6 address sin6.sin6_addr
).
Related Topics
How to Read the Results of a System() Call in C++
How to Measure CPU Time of a Specific Set of Threads
Read Unicode Utf-8 File into Wstring
What Default Promotions of Types Are There in the Variadic Arguments List
How to Include Header Files in Gcc Search Path
C++ Warning: Deprecated Conversion from String Constant to 'Char*' [-Wwrite-Strings]
Differencebetween Std::Array and Std::Vector? When Do You Use One Over Other
String Conversion with Boost Locale: Different Behaviour on Windows and Linux
How to Avoid Multiple Definition Linking Error
How to Enable C++11 in Qt Creator
How Does the Omp Ordered Clause Work
Disambiguate Class-Member in Multiple Inheritance
Get the Compiler Options from a Compiled Executable
Why Are My Struct's Members Not Properly Initialised Using '{}'