Jeśli server tcp zakończy działanie, to twój socket w system operacyjnym nie dostanie potwierdzeń odbioru transmisji na warstwie tcp, więc zgłosi błąd do warstwy wyżej, gdzie jest intepreter pythona, wykonujący kod twojego programu klienckiego, który wykonuje write() (w postaci write, send, sendall, itp), i tenże write() zostanie przerwany przez wyjątek w pythonie, który ty złapiesz parę linijek niżej używając "except socket.ConnectionResetError as e:".
To nie takie proste. ConnectionResetError jest tylko jeżeli dostał RST od hosta serwera (i może po FIN od serwera, ale głowy nie daję). Jeżeli host, a właściwie jego kernel, był na tyle miły, że zobaczył proces, który się wywalił, to może i wyśle RST na tym połączeniu.
Ale jeżeli ktoś odłączył tą maszynę od sieci lub sama maszyna padła fizycznie, to można zapomnieć o RST. Wtedy jedyna nadzieja w timeoutach TCP. Będziesz wisiał dopóki nie przekroczysz tiemeoutu tcp (https://docs.python.org/3/howto/sockets.html#when-sockets-die). Strategia dla timeoutu z kolei jest zależna od konfiguracji stosu sieciowego. Dla Linuxa polecam zapoznać się z https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt . Ale jeżeli nic nie wysyłałeś, jedynie utrzymywałeś połączenie, to timeout w ogóle nie zostanie złapany.
Inną opcją jest skorzystanie z opcji keepalive ( https://stackoverflow.com/questions/12248132/how-to-change-tcp-keepalive-timer-using-python-script ) albo timeoutów na operacjach blokujących.