class: center, middle # Networking ## Alan Cox and Scott Rixner --- # The Sockets API  --- layout: true --- # `socket(2)` ``` int socket(int domain, int type, int protocol); ``` - Creates a new socket and returns its file descriptor - The socket is an endpoint for network communication - The socket is not yet associated with any address or connection We will typically use the `AF_INET` domain (IPv4), `SOCK_STREAM` type (TCP), and `0` protocol (default) --- # `connect(2)` ``` int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); ``` - Used by clients to connect to servers - `sockfd` is a socket descriptor returned by `socket(2)` - Establishes a connection to a remote socket at the given address (`addr`) - `sockfd` can now be used for network communication --- # `open_clientfd` - Get the address of the server using `getaddrinfo(3)` - Create a socket using `socket(2)` - Connect to the server using `connect(2)` --- # `bind(2)` ``` int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); ``` - "Binds" a socket (`sockfd`) to a specific address and port (`addr`) - `sockfd` is a socket descriptor returned by `socket(2)` - Used by servers to specify the address they will listen on for incoming connections --- # `listen(2)` ``` int listen(int sockfd, int backlog); ``` - Prepares a bound socket (`sockfd`) to "listen" for incoming connection requests from clients - The `backlog` argument specifies the length of the queue of pending connections - `sockfd` can now be used to accept incoming connections from the network --- # `open_listenfd` - Create a socket using `socket(2)` - Set socket options to allow reuse of the address/port using `setsockopt(2)` - Bind the socket to a specific address and port using `bind(2)` - Prepare the socket to listen for incoming connections using `listen(2)` --- # `accept(2)` ``` int accept(int sockfd, struct sockaddr *_Nullable restrict addr, socklen_t *_Nullable restrict addrlen); ``` - "Accepts" an incoming connection on a listening socket (`sockfd`) - Returns a new socket descriptor for the accepted connection - `addr` is used to return the address of the client --- # `read(2)` and `write(2)` ``` ssize_t read(int fd, void buf[.count], size_t count); ssize_t write(int fd, const void buf[.count], size_t count); ``` - Read and write data from/to a connected/accepted socket - Can be used to read/write any file descriptor, not just sockets - `count` specifies the maximum number of bytes to read/write - Returns the actual number of bytes read/written, or `-1` on error - Use robust I/O (rio) functions to more easily handle "short counts" - `rio_readn` and `rio_writen` for unbuffered reads/writes - `rio_readlineb` and `rio_readnb` for buffered reads --- # `close(2)` ``` int close(int fd); ``` - Closes the socket (`fd`) - Works for any file descriptor, not just sockets - For sockets, signals EOF to the other end of the connection --- # Echo Server Send everything received from a client back to that client - Open a listening socket - Loop forever - Accept a connection from a client - Repeatedly read from then write back to the connection until the client closes it Errors on an accepted connection should not "crash" the server, just clean up and accept the next connection --- # The Sockets API  --- class: center, middle # Get Started!