Sockets enable a network application to communicate with another network application running on another machine. Simply put, a socket is an entry-point for a network "pipe" that connects the above two applications sitting on two different machines (or, on the same machine!). A lot of network applications communicate using socket-semantics.

Sockets are bidirectional in nature; this means that sockets forming a network "pipe" can both send and receive data simultaneously.

For example, the following figure shows two sockets (socketA and socketB) communicating with each other.

Figure: Communication using two sockets

Typically, a socket endpoint is identified by three parameters: (a) IP address (IPv4 or IPv6) of the machine, (b) the port number on that machine, and (c) the transport protocol (e.g. TCP or UDP). A port number is a logical local identification point for network applications; each host can have as much as 65,536 ports.

Depending upon the transport protocol provided, sockets can be divided into two types: connection-oriented and connection-less. We will demonstrate examples of each of them below.

Connection-oriented Sockets

Connection-oriented sockets require an explicit connection between the two ends before they can send data. Once they are connected, one end can send data to the other other without specifying any address. Since they are connected, they already know the address of the other end. One of the key Internet protocols, TCP (Transmission Control Protocol) uses connection-oriented sockets.

We provide a simple figure to illustrate the case of connection-oriented sockets. In this case, the server (socket0) accepts new connections from the clients to create a new "pipe" for each of them. When a new connection request comes from a client socket (socketB), then the server socket creates a new local socket (socketA) and associates the new socket with the client socket. After this step, socketA and socketB become connected. The parent server socket, socket0 detaches itself from this connection and continues to wait for new incoming requests.

Figure: Connection Establishment for TCP sockets

Connection-less Sockets

Connection-less sockets do not require any connection setup and the client socket (socketB) can send messages to the server socket (e.g. socketA1) anytime. The common transport protocol for connection-less sockets is UDP (User Datagram Protocol).

Because such sockets are connection-less, one socket can send messages to multiple server sockets at the same time! As an example, in the following figure, socketB could send data at the same time to multiple servers sockets: socketA1, socketA2, and socketA3.

Figure: Sending data using UDP sockets

Python socket module

Socket programming is relatively easy in Python. Python provides a module named socket that must be imported before using the socket APIs. Let us begin by seeing all the attributes (data attributes and methods) that are available with the socket module using the dir() function. We trim the output for the sake of readability:

 [user@codingbison]$ python3
 Python 3.2.1 (default, Jul 11 2011, 18:55:33) 
 [GCC 4.6.1 20110627 (Red Hat 4.6.1-1)] on linux2
 Type "help", "copyright", "credits" or "license" for more information.
 >>> import socket
 >>> >>> dir(socket)
 [ ...
   'AF_INET', 'AF_INET6', 
   '__all__', '__builtins__', 
   '__cached__', '__doc__', '__file__', '__name__', '__package__', '_blocking_errnos', 
   '_realsocket', '_socket', 'create_connection', 'dup', 'errno', 'error', 'fromfd', 
   'gaierror', 'getaddrinfo', 'getdefaulttimeout', 'getfqdn', 'gethostbyaddr', 
   'gethostbyname', 'gethostbyname_ex', 'gethostname', 'getnameinfo', 'getprotobyname', 
   'getservbyname', 'getservbyport', 'has_ipv6', 'herror', 'htonl', 'htons', 'inet_aton', 
   'inet_ntoa', 'inet_ntop', 'inet_pton', 'io', 'ntohl', 'ntohs', 'os', 'setdefaulttimeout', 
   'socket', 'socketpair', 'sys', 'timeout']

The above list consists of data attributes (constants like 'AF_INET', 'IPPROTO_TCP' etc) and functions (like gethostbyname, getnameinfo etc). One of the key methods in socket programming is the socket class (which is a constructor method) itself. It is this class that houses various socket methods like socket() (to open a socket), send() (to send socket data), etc. Let us take a look at the attributes of this class as well:

 >>> import socket
 >>> print(socket.socket)
 <class 'socket.socket'>
 >>> dir(socket.socket)
 ['__class__', '__delattr__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', 
   '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', 
   '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
   '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__weakref__', 
   '_accept', '_closed', '_decref_socketios', '_io_refs', '_real_close', 'accept', 'bind', 
   'close', 'connect', 'connect_ex', 'detach', 'dup', 'family', 'fileno', 'getpeername', 
   'getsockname', 'getsockopt', 'gettimeout', 'listen', 'makefile', 'proto', 'recv', 
   'recv_into', 'recvfrom', 'recvfrom_into', 'send', 'sendall', 'sendto', 'setblocking', 
   'setsockopt', 'settimeout', 'shutdown', 'timeout', 'type']

For additional details, we refer the reader to Python's Doc page on sockets:

comments powered by Disqus