IPC
Latency
Bandwidth
Throughput
Baud rate
Multiplexing (muxing)
Duplex
Half duplex - Can only send or receive at any given time, not both. Full duplex - Can send and receive simultaneously
Transceiver
Octet
Network segment
A B ▢─╢ ╟─▢ ╟─▢ ▢─╫─▢ ▢─╫─▢ ║ ║ ╟─▢
Bridge
A device for connecting network segments together at the layer 1-2 (Ethernet) level.
Forwards packets from one network segment to another
A B ┋ ┋ ║ ║ ◳═══════════◰
May use some logic in forwarding packets, based on locations of hosts in network segment
A hub / switch may be considered a bridge.
Repeater
Hub
Switch
Gateway
Physical Layer (10Base-T, 100Base-T, 802.11, etc.)
Data Link Layer (Ethernet / others)
Network Layer (IP(v4|v6) / ICMP / etc.)
Transport Layer (TCP / UDP / etc.)
Session Layer (TCP / RPC / Sockets)
Presentation Layer (Encryption (SSL/TLS) / format conversions)
Application Layer (User interface)
#include <sys/types.h> /* Only required for BSD systems */ #include <sys/socket.h> int socketpair(int domain, int type, int protocol, int sv[2]);
Creates a bi-directional data pipe with descriptors placed in the sv array on success. A socketpair is essentially a pre-connected anonymous Unix domain socket connection (man 7 unix for details.) Both sv[0] and sv[1] can be read and written to. What is written on one, can be read from the other and vice versa.
man 7 unix
sv[0]
sv[1]
domain must be AF_UNIX
domain
AF_UNIX
type may be one of:
type
SOCK_STREAM Sequenced, reliable two-way data-communication stream. Out of band (OOB) communication is supported. SOCK_DGRAM Provides a data-gram oriented stream that preserves message boundaries. Unix data-gram sockets are always reliable and do not re-order packets. SOCK_SEQPACKET Provides a sequenced, connection-oriented, reliable, delivery of data-grams of a fixed maximum length. Preserves message boundaries.
protocol = 0 (selects the default protocol for AF_UNIX)
protocol
char buf[K]; int sv[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) { perror("socketpair"); exit(0); } pid_t pid = fork(); if (pid == 0) { close(sv[1]); // Write a message, including the null character: write(sv[0], "Hello, world!", 14); // Read back an 'ACK' message; read(sv[0], buf, K); printf("Child received = %s\n", buf); close(sv[0]); } else { close(sv[0]); read(sv[1], buf, K); printf("Parent received = %s\n", buf); write(sv[1], "ACK", 4); close(sv[1]); }
socket(2)
#include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol);
Creates one end (i.e. unconnected) of a data communications channel. The return value is a valid file descriptor (the socket) when >= 0 or -1 on error.
domain is one of:
AF_UNIX Local communication (process to process on the same machine.) (man 7 unix) AF_INET IPv4 communication (man 7 ip) AF_INET6 IPv6 communication (man 7 ipv6) AF_PACKET low-level packet interface (requires elevated privileges.) (man 7 packet) others...
man 7 ip
man 7 ipv6
man 7 packet
type is one of:
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data transmission mechanism may be supported. SOCK_DGRAM Supports data-grams (connection-less, unreliable messages of a fixed maximum length). SOCK_SEQPACKET Provides a sequenced, reliable, two-way connection-based data transmission path for data-grams of fixed maximum length; a consumer is required to read an entire packet with each input system call.
Protocol specifies a specific protocol to use (such as TCP), see the file /etc/protocols for a list of protocols. Typically 0 is entered here to use the default protocol as most transports only have one defined protocol anyway.
/etc/protocols
0
Difference between streams (SOCK_STREAM / SOCK_SEQPACKET) and Data-grams:
SOCK_STREAM
SOCK_SEQPACKET
Streams use the main socket as only a means to accept connections from client process. Once a connection request is accept()ed in the server, a new file descriptor in the server is created by the accept() system call, which is then used to do all the communication with the client.
accept()
The client and server can then both use regular read/write on the file descriptors to communicate, as if the connection was like a socketpair().
socketpair()
With data-gram connections, both the client and server have only one socket and messages are sent with sendto() or sendmsg() which include the address of the recipient. Received messages can be read normally, however if you wish to reply you need to use recvfrom() or recvmsg() which includes a structure that is filled in the the address of the sender which you can then use in the sendto/sendmsg calls.
sendto()
sendmsg()
recvfrom()
recvmsg()
sendto
sendmsg
int sock = socket(AF_UNIX, type, 0); #include <sys/socket.h> #include <sys/un.h> struct sockaddr_un { sa_family_t sun_family; /* set = AF_UNIX */ char sun_path[108]; /* pathname */ };
The sun_family field should always be set = to AF_UNIX and the sun_path is the file-system path where the socket file is or will be located at. The socket file is the means of connecting the sockets, i.e. it is the address for Unix domain sockets.
sun_family
sun_path
#include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
"binds" an address to a socket. Until a socket has an address it cannot receive connections (SOCK_STREAM) or receive message if it hasn't sent any (it can be used to send messages however.)
Returns 0 on success or -1 on failure.
The 'struct sockaddr' pointer is the generic socket address pointer, so sockaddr_un or sockaddr_in structures must be typecast to it. addrlen is the sizeof() the struct being used.
struct sockaddr
sockaddr_un
sockaddr_in
addrlen
sizeof()
For Unix domain sockets this will create the socket file. When you are done with the socket, you should unlink(2) the socket file from the file- system (very much like a named pipe (FIFO) should be removed when not needed.) The path to the socket file given should be writable and searchable by the process and the socket file should be writable by anyone else you want to be able to connect or send messages to it. The initial permissions (nominally 0666) on the socket are modified by the umask(2) and can be modified by chmod(2).
unlink(2)
0666
umask(2)
chmod(2)
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #define BUFSIZE 4096 int main(int argc, char *argv[]) { struct sockaddr_un addr; char buf[BUFSIZE], *path = "/tmp/serv_sock"; int r; if (argc > 1) path = argv[1]; /* Create socket, initially un-connected. */ int sock = socket(AF_UNIX, SOCK_DGRAM, 0); if (sock < 0) { perror("socket"); exit(1); } /* Create addr (filesystem socket file) */ addr.sun_family = AF_UNIX; strcpy(addr.sun_path, path); /* Remove stale socket file if present */ unlink(path); /* Bind socket to address: */ if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un))) { perror("bind"); exit(1); } printf("Listening at %s\n", path); while((r = read(sock, buf, BUFSIZE)) > 0) { printf("%.*s", r, buf); } return 0; }
Note that a client program would be virtually identical, save that in the above case it would be sending data via write(). Again, once both ends are connected via the bind() function, each end operates as if they each had one end of a socketpair().
write()
bind()