- Forward


TCP Socket Programming
An Introduction with Examples in C


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu

Print

Review
Back SMYC Forward
  • TCP:
    • Connection-oriented
    • Stream-oriented
    • Reliabale
    • Internet Programming Basics:
    • Byte order
    • Addresses and ports
Connection-Oriented Protocols
Back SMYC Forward
  • The Active Party:
    • Initiates the connection
    • Is often the client but needn't be
  • The Passive Party:
    • Waits for the active party to initiate the connection
    • Is often the server but needn't be
TCP Programming
Back SMYC Forward
  • Both Parties:
    • socket() socket
    • \(\vdots\)
    • close() close
  • The Passive Party:
    • bind() bind
    • listen() listen
    • accept() accept
  • The Active Party:
    • connect() connect
Creating a Socket: socket() socket
Back SMYC Forward
int socket(int domain, int type, int protocol)
Purpose:
Create a socket
Details:
domain AF_INET or AF_INET6 for IP
type SOCK_STERAM for TCP
protocol 0 for TCP over IP
Return The file descriptor on success; -1 on error
#include <sys/socket.h> sys/socket.h
Binding to an Address and/or Port: bind() bind
Back SMYC Forward
int bind(int fd, const struct sockaddr *addr, socklen_t addrlen)
Purpose:
Associate a socket with a particular address and/or port
Details:
fd The file descriptor of a socket
addr The address/port to bind to
addrlen The length of the address
Return 0 on success; -1 on error
#include <sys/socket.h> sys/socket.h
Marking a Socket as Passive: listen() listen
Back SMYC Forward
int listen(int fd, int backlog)
Purpose:
Mark a socket as passive/listening
Details:
fd The file descriptor of the socket
backlog The limit on the number of pending connections handled (i.e., connections initiated before the call to accept()
Return 0 on success; -1 on error
#include <sys/socket.h> sys/socket.h
Waiting for a Connection Request: accept() accept
Back SMYC Forward
int accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
Purpose:
Accptes an incoming connection on a passive socket
Details:
fd The file descriptor of the passive socket
addr The address of the active socket that initiated the connection (or NULL if not needed)
addrlen The length of addr
Return The file descriptor for the connection on success; -1 on error
#include <sys/socket.h> sys/socket.h

Notes: (1) accept() blocks (unless there are pending connections). (2) The file descriptor that is returned has an associated active socket. In other words, an active socket is created by the passive socket each time accept() returns.

An Example Passive Party (and Server)
Back SMYC Forward
unixexamples/tcp/djia_server.c
 
Making a Connection Request: connect() connect
Back SMYC Forward
int connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
Purpose:
Request a connection to a passive socket
Details:
fd The file descriptor of the active socket making the request
addr The address of the passive socket
addrlen The length of the address of the passive socket
Return 0 on success; -1 on error
#include <sys/socket.h> sys/socket.h
An Example Active Party (and Client)
Back SMYC Forward
unixexamples/tcp/djia_client.c
 
A "Generic" Active Party
Back SMYC Forward
  • telnet:
    • A utility program that allows two machines to communicate using the TELNET protocol
  • Using telnet for Other Purposes:
    • Because telnet uses TCP at the transport layer and reverts to "old line-by-line mode" if the remote party doesn't support TELNET, it can be used to communicate with other applications that use TCP
Active/Passive and Client/Server
Back SMYC Forward
  • A Conceptual Question:
    • At the application layer, is the active party always the client and the passive party always the server?
  • An Answer and Explanation:
    • No! After the connection is established, the passive party could initiate the application-layer request (though this is, indeed, rare)
      Expand
Application Protocols on TCP
Back SMYC Forward
  • Using the Connection:
    • It is easy to implement complicated application protocols that involve a "back and forth"
  • Using the Stream:
    • The application protocol can read/write arbitrary streams of bytes (rather than discrete messages)
  • Using the Bidirectionality:
    • The application protocol can be simplex (as in the example above), half duplex, or full duplex
An Example of Half-Duplex Application Protocol
Back SMYC Forward
  • The Setting:
    • A client can request a bank balance from a server
  • The Protocol:
    • Client sends an ID
    • Server sends a challenge
    • Client sends a response
    • Server sends the balance (or error message)
An Example Half-Duplex Protocol - The Server
Back SMYC Forward
unixexamples/tcp/balance_server.c
 
An Example Half-Duplex Protocol - The Client
Back SMYC Forward
unixexamples/tcp/balance_client.c
 
An Example of a Stream-Oriented Application Protocol
Back SMYC Forward
  • An Observation:
    • The examples above uses small fixed size communications transfers so a message-oriented transport protocol could be used
  • The Protocol for the Next Example:
    • Client (telnet) sends a course code
    • Server responds with a line-oriented description of arbitrary length
An Example of a Stream-Oriented Application (cont.)
Back SMYC Forward
unixexamples/tcp/course_server.c
 
An Example Full-Duplex Application Protocol
Back SMYC Forward
  • The Setting:
    • Two sensor stations that measure and record the same data independently and periodically share the data they've collected
  • The Protocol:
    • Though they are peers in many ways, one station acts as the server (i.e., waits for a connections)
    • The other station initiates the connection
    • The two stations simulatenously transfer the data they've recorded
An Example Full-Duplex Protocol - The Server
Back SMYC Forward
unixexamples/tcp/sync_server.c
 
An Example Full-Duplex Protocol - The Client
Back SMYC Forward
unixexamples/tcp/sync_client.c
 
Concurrency
Back SMYC Forward
  • The Idea:
    • Handle multiple connections "at the same time" (i.e., handle each connection in its own control flow)
  • Approaches:
    • Use multiple processes
    • Use multiple threads
A Server with Multiple Processes
Back SMYC Forward
unixexamples/tcp/multiprocessed_course_server.c
 
A Server with Multiple Threads
Back SMYC Forward
unixexamples/tcp/threaded_course_server.c
 
Improving Concurrent Servers
Back SMYC Forward
  • Pre-Forking:
    • Instead of creating child processes when needed, create them at start-up (and put them in a pool)
    • Put connections in a queue
    • When a child process is done with a connection it doesn't terminate; instead it retrieves the next connection in the queue
  • Pre-Threading:
    • The same idea, but using threads instead of processes
Partial Reads/Writes
Back SMYC Forward
  • Recall (in General):
    • read() and write() may read/write fewer characters than were requested (and return the number actually read/written)
  • With Stream Sockets:
    • The buffer limit might be reached for the socket causing this kind of behavior even when there are no "errors"
Partial Reads/Writes (cont.)
Back SMYC Forward
unixexamples/tcp/tcpio.c
 
There's Always More to Learn
Back -