Let's quickly review device files: In Linux, application programs communicate read and write operations to the kernel through file descriptors. That works great for files, and it turned out that the same API could be used for character devices that produce and consume streams of characters, and block devices that read and write blocks of fixed size at a random access address, just by pretending that these are also files.
But a way was needed to configure those devices (set baud rates etc.), and for that, the ioctl call was invented. It just passes a data structure that's specific to the device and the kind of I/O control used to the kernel, and gets back the results in the same data structure, so it's a very generic extensible API and can be used for lots of things.
Now, how do network operations fit in? A typical network server application wants to bind to some network address, listen on a certain port (e.g. 80 for HTTP, or 22 for ssh), and if a client connects, it wants to send data to and receive data from this client. And the dual operations for the client.
It's not obvious how to fit this in with file operations (though it can be done, see Plan 9), that's why the UNIX designers invented a new API: sockets. You can find details in the section 2 man pages for
recv. Note that while it is distinct from the file I/O API, the
socket call nevertheless also returns a file descriptor. There are numerous tutorials on how to use sockets on the web, google a bit.
So far this is all pure UNIX, nobody was talking about network interfaces at the time sockets were invented. And because this API is really old, it is defined for a variety of network protocols beyond the Internet protocol (look at the
AF_* constants), though only a few of those are supported in Linux.
But as computers started to get multiple network cards, some abstraction for this was needed. In Linux, that is the network interface (NI). It's not only used for a piece of hardware, but also for various tunnels, and user-application endpoints that serve as tunnels like OpenVPN, etc. As explained, the socket API isn't based on (special) files and is independent of the filesystem. In the same way, network interfaces don't show up in the file system, either. However, the NIs are made available in the
/sys filesystem (as well as other networking tunables).
A NI is simple a kernel abstraction of an endpoint where network packets enter and leave the kernel. Sockets, on the other hand, are used to communicate packets with applications. No socket needs to be involved with the processing of a packet. For example, when forwarding is enabled, a packet may enter on one NI and leave on another.
In that sense, sockets and network interfaces are totally independent.
But there had to be a way to configure NIs, just like you needed a way to configure block and character devices. And since sockets already returned a file descriptor, it was somewhat logical to just allow an
ioctl on that file descriptor. That's the netdevice interface you linked.
There are quite a few other abuses of system calls in a similar way, for example for packet filtering, packet capture etc.
All of this has grown piece after piece, and is not particularly logical in many places. If it had be designed all at once, one could probably have made a more orthogonal API.