Skip to content

Instantly share code, notes, and snippets.

@airekans
Created October 21, 2015 04:52
Show Gist options
  • Save airekans/45a45de68b21c38738ef to your computer and use it in GitHub Desktop.
Save airekans/45a45de68b21c38738ef to your computer and use it in GitHub Desktop.
Half close connection handling in TCP
# several behavior in TCP when handling half close connection:
# 1. if one end "close()" socket, while the other does not read from the socket,
# the other end will not be able to detect connection close.
# If at this moment, this end send some data to the close end, close end has been closed write and read,
# so it will not be able to recv data from this connection, and it will send an "RST" in this case
# to tell its peer about this.
# When the peer recv "RST", it will just set this connection as close, so next time when it tries to write
# data on this socket, it will have the broken pipe error.
# But it can still recv data on this socket. After all data in the TCP recv buffer has been read, it will return EOF.
# 2. If one end "shutdown(W)" the socket, this will be the read half close case. So the peer can send data if he wants.
# 3. If the one calls "close()" on the socket whose recv buffer has some data, then the socket will just send "RST" instead
# of "FIN" to the peer, and just discard any data in the send buffer, so in this case, the data will be lost.
import socket
import sys
import time
import traceback
def run_server(soc, addr):
soc.bind(addr)
soc.listen(30)
print 'listening on', addr
while True:
client_soc, client_addr = soc.accept()
print client_addr, 'is connected'
i = 1
while True:
try:
client_soc.sendall('9' * 1024)
print 'send %d K' % (i)
i += 1
except:
traceback.print_exc()
print 'client_soc is broken'
break
while True:
try:
buf = client_soc.recv(4096)
print 'buf len', len(buf)
if len(buf) == 0:
print 'nothing can be read, close it'
client_soc.close()
break
except:
traceback.print_exc()
print 'nothing can be read, close it'
client_soc.close()
break
print client_addr, 'is disconnected'
def run_client(soc, addr):
soc.connect(addr)
print 'connected to', addr
test_data = '0' * 4096 * 20
last_time = time.time()
cnt_4K = 0
try:
soc.sendall(test_data)
time.sleep(15)
soc.close()
print 'close the socket'
except:
print 'socket is broken'
if __name__ == '__main__':
run_mode = sys.argv[1]
soc = socket.socket()
if run_mode == 'server':
listen_addr = sys.argv[2]
listen_addr = listen_addr.split(':')
listen_addr = (listen_addr[0], int(listen_addr[1]))
run_server(soc, listen_addr)
else:
server_addr = sys.argv[2]
server_addr = server_addr.split(':')
server_addr = (server_addr[0], int(server_addr[1]))
run_client(soc, server_addr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment