CS3984 Computer Systems in Rust



TCP Socket Call Sequence: Server

  1. 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

  1. 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
  2. Mark the socket as a passive socket

    int listen(int sockfd, int backlog);
    
    
    
    • sockfd can be now be used with accept
    • 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)?;


  1. Create a SocketAddr (IP address + port number)
  2. 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:

  1. 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:

  1. Create a socket

  2. 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