TCP Socket Call Sequence: Server
-
Create a socket (file descriptor)
int socket(int domain, int type, int protocol);
-
domain
: protocol family-
AF_UNIX
: Unix sockets -
AF_INET
: IPv4 sockets -
AF_INET6
: IPv6 sockets
-
-
type
: communication semantics-
SOCK_DGRAM
: UDP -
SOCK_STREAM
: TCP -
SOCK_RAW
: raw network protocol access
-
-
TCP Socket Call Sequence: Server
-
Bind the socket to an address
int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen);
-
sockfd
: socket file descriptor -
addr
,addrlen
: server address and port
-
-
Mark the socket as a passive socket
int listen(int sockfd, int backlog);
-
sockfd
can be now be used withaccept
-
OS will queue up to
backlog
pending connections
-
TCP Server: Rust
Code:
let socket = SocketAddr::from(([127, 0, 0, 1], 8888));
let listener = TcpListener::bind(socket)?;
-
Create a
SocketAddr
(IP address + port number) - Bind a new socket to the address
TCP Server: Rust
Code:
let socket = SocketAddr::from(([127, 0, 0, 1], 8888));
let listener = TcpListener::bind(socket)?;
System Calls:
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 3setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0bind(3, {sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("127.0.0.1")}, 16) = 0listen(3, 128) = 0
FD 3 is a IP socket with the TCP protocol, queuing up to 128 connections
TCP Socket Call Sequence
Server:
-
Accept a connection on the socket
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- Blocks until a connection is pending
-
sockfd
can then be reused to accept more clients
Client:
-
Create a socket
-
Connect to the server
int connect(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
TCP Server and Client: Rust
Server:
let (stream, socket) = listener.accept()?;
accept4(3, {sa_family=AF_INET, sin_port=htons(42694), sin_addr=inet_addr("127.0.0.1")}, [128 => 16], SOCK_CLOEXEC) = 4
Client:
let socket = SocketAddr::from(([127, 0, 0, 1], 8888));
let stream = TcpStream::connect(socket)?;
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 3connect(3, {sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
TCP Server and Client: Rust
impl Read for TcpStream {}
impl Write for TcpStream {}
Server:
stream.write_all("hello!".as_bytes())?;
recvfrom(4, "hello!", 4096, 0, NULL, NULL) = 6
Client:
let mut temp = [0; 4096];
let n = stream.read(&mut temp)?;
sendto(3, "hello!", 6, MSG_NOSIGNAL, NULL, 0) = 6