Add rough draft of sockets post.
This commit is contained in:
parent
2792d7c497
commit
ae96f956ab
52
_drafts/about_sockets.md
Normal file
52
_drafts/about_sockets.md
Normal 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).
|
Loading…
Reference in New Issue
Block a user