Created
October 21, 2015 04:52
-
-
Save airekans/45a45de68b21c38738ef to your computer and use it in GitHub Desktop.
Half close connection handling in TCP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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