This is what we used to call a "Berkeleyism". It's an error in the UC Berkeley implementation of TCP in the kernel, which, being free, became standard. (Yes, there was TCP/IP before Berkeley UNIX, at least four implementations.)<p>The trouble is that UNIX does not take "close()" very seriously. This is because "close()" is implicit on exit, and having "exit()" stall waiting for I/O is undesirable. So, close is non-blocking. When you close a file after writing, close happens immediately, even if writing is not yet done. "Calling close() DOES NOT guarantee that contents are on the disk as the OS may have deferred the writes."<p>So sockets got the same unchecked semantics as files.<p>Now, logically, you'd call "fsync()" to get a socket fully flushed. But, another Berkeleyism is that sockets were originally distinct from the file system, because networking was bolted on as an afterthought and not well integrated. Hence "send" and "recv" instead of "read" and "write". Being able to use read and write on sockets came later. So, sockets have "shutdown".