Add rough draft of sockets post.

This commit is contained in:
Anna Rose 2016-05-04 16:54:29 -04:00
parent 2792d7c497
commit ae96f956ab

52
_drafts/about_sockets.md Normal file
View File

@ -0,0 +1,52 @@
---
category: technology
title: About Sockets
tags:
- networking
- linux
- programming
---
A 'socket' is an abstraction for a network connection. Each machine has a socket it is communicating with; from an application's perspective, sockets make it possible to treat a network connection like a file, and simply read()/write() on it.
Here is an overview of the lifecycle of a TCP socket:
Establishing a connection
An application on one system creates a socket and then calls bind(), listen(), and accept() -> this creates a socket in the LISTEN state. The socket will stay in the LISTEN state (and the accept() call will block) until an incoming connection is made on that port.
On another system, an application creates a socket and calls connect(), passing it the address of the first system. This creates a client-side socket, which starts in SYN_SENT.
Once these two sockets start talking, they go through a '3-way handshake' (transparent to the application) to establish some necessary metadata, and then both sockets change to the ESTABLISHED state.
Sending data
At this point the applications can simply read() and write() to the socket. Each application will read() what the other application write()s.
Shutting down the connection
When one side of the connection calls close() on its socket, it sends a packet telling the other end it is finished (a FIN packet), and the socket *that sent the FIN* changes to FIN_WAIT.
When a connection *receives* a FIN, it changes to the CLOSE_WAIT state.
When a socket in FIN_WAIT receives a FIN, it closes.
A socket in CLOSE_WAIT, by contrast, cannot close *until the application calls close() on the socket*. Once this happens, the system sends a FIN so that the remote end can finish closing, and the socket closes.
Now, from an application's perspective, all of these socket states are transparent; they are a kernel abstraction. The application just has a file descriptor that it is writing and reading on. So how do we detect when the other side has closed down the connection (i.e. that we are in CLOSE_WAIT)?
When you try to read() on a socket the other side has close()d, you get EOF (the end of file marker). It is considered correct programming to, at this point, do any necessary clean-up work and call close() on your own socket.
Otherwise you end up with sockets is CLOSE_WAIT.
In other words, if a socket is stuck in CLOSE_WAIT, it is necessarily a fault in the application - the application is failing to check for the connection closing, and thus never calls close().
This problem is common in applications that do nothing but write() to their sockets (they never read() so they never detect the EOF).