Python socket client side drop connection after 2 minutes

Viewed 223

I coded a simple python server and client but for some reason the communication closes unexpectedly.

I ran WireShark to keep tracking about what the client is doing and I see that after 2 minutes the client send a RST package for no reason.

The behavior I'm expecting is:

  1. Enginners clients send data to the server (No problem here)
  2. Server recieve data and waits for Press client
  3. Press client connect to the server sending his DCU (Client ID) and ask if there is info for him, if not, press client keeps connected to the server waiting for data.

Server:

import socketserver
import socket
import pickle


list_changes = []
list_dcu = set()

def connections(server):
    conns = []
    addrs = []
    server.listen() # Server is listening

    while True:
        my_socket, addr = server.accept()
        data_recv = pickle.loads(my_socket.recv(4096))
        server.setblocking(1)
        conns.append(my_socket)
        addrs.append(addr)

        # Registering, Appending and Search
        if data_recv[0] == 'DCU':
            try:
                append_dcu(data_recv)
                search_changes(data_recv)
            except IndexError:
                print('errrrrrrror')
        elif data_recv[0] == 'ING':
            list_changes.append(data_recv)

def append_dcu(data_recv): # Appending function
    list_dcu.add(data_recv[1])
    print('List DCU: ', list_dcu)
    return

def search_changes(data_recv): # Search for DCU in list_changes and send data if found
    i = 0
    for i in range(len(list_changes)):
        if data_recv[1] == list_changes[i][2]:
            response = pickle.dumps(list_changes[i])
            request.sendall(response)
            del list_changes[i]
    return


if __name__ == "__main__":
    host, port = "127.0.0.1", 9999
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((host, port))
    connections(server)

Client:

import socket
import pickle
import threading
from view import MainView, msg_alert


class AppInit:

    def __init__(self):
        self.controller = Controller()
        self.view = MainView(self.controller)
        return


class Controller:

    def __init__(self):
        # self.th1 =
        return

    class Threading:
        def __init__(self, var_dcu):
            self.host = '127.0.0.1'  # my_socket IP - Change it in Test Environment
            self.port = 9999
            self.var_dcu = var_dcu
            self.data = ''
            self.data_send = 0
            self.th1 = threading.Thread(target=search, args=(self.var_dcu, self.host, self.port))
            self.th1.daemon = True
            self.th1.start()

def search(var_dcu, host, port):
    data = ('DCU', var_dcu)
    data_send = pickle.dumps(data)
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    my_socket.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 10000, 3000))
    my_socket.connect(('127.0.0.1', 9999))
    my_socket.sendall(data_send)

I'm using Python 3.7

Thanks in advance. Any help will be appreciated

1 Answers

As I said, I tried using keepalive and those stuff but for some reason the client kept sending RST to the server after 2 minutes, so I changed the behavior of the client.

Client: ask the server for changes Server: respond with a list of changes or with a special string if there is no changes. Client: recieve the response, it does whatever has to and close the connection.

After 2 minutes, the cicle repeats it self

Time for the code:

Server:

import socket
import pickle
import time


class Main:

    def __init__(self):
        # self.list_changes is filled with 2 examples from Engineering client
        self.list_changes = [['ING', 'Chris', '432', 1122, 'Reason 1'],
                             ['ING', 'Jane', '431', 8899, 'Reason 2']]
        self.dict_dcu = {}
        self.host = None
        self.port = None
        self.server_socket = None

        self.server()

    def server(self):
        self.host, self.port = "127.0.0.1", 9999
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.bind((self.host, self.port))
        self.server_socket.listen() # Servidor en estado de escucha

        while True:
            self.client_sock, self.addr = self.server_socket.accept()
            self.data_recv = pickle.loads(self.client_sock.recv(4096))
            self.appending()

    def appending(self):
        if self.data_recv[0] == 'DCU':
            try:
                self.dict_dcu.update({self.data_recv[1]: self.client_sock})
                self.search_changes()
            except IndexError as error:
                print('Error: ', IndexError)
        if self.data_recv[0] == 'ING':
            try:
                self.list_changes.append(self.data_recv)
            except IndexError as error:
                print('Error :', error)
                return

    def search_changes(self):
        self.key = self.data_recv[1]
        for i in range(len(self.list_changes)):
            if self.key == self.list_changes[i][2]:
                self.key = self.dict_dcu.get(self.data_recv[1])
                self.sendmsg(self.key, self.list_changes[i])
                self.list_changes.pop(i)
                break
            elif i+1 == len(self.list_changes):
                self.sendmsg(self.key, 'No_changes')

    def sendmsg(self, socket_key, message):
        self.updates = pickle.dumps((message))
        self.client_sock.sendall(self.updates)


if __name__ == "__main__":
    main = Main()

Client:

import socket, pickle, time, threading
import view
from tkinter import messagebox
import _thread


class AppInit:
    def __init__(self):

        self.controller = Controller(view.MainView)


class Controller:
    def __init__(self, mainview):
        self.bttn = view.MsgReceiver.bttn_state
        self.main_view = mainview

        # Changes vars
        self.name = None
        self.job = None
        self.reason = None

        # DCU related vars
        self.dcu = None
        self.reg_dcu = None

        # Socket variables
        self.send_sock = None
        self.response = None
        self.addr = None
        self.listen_port = None

        self.start_app()

    def start_app(self):
        self.main_view(self.threading)

    def threading(self, dcu, bttn):
        try:
            _thread.start_new_thread(self.fetching_changes, (dcu, bttn))
        except _thread.error:
            messagebox.showerror('ERROR THREADING', 'UNABLE TO START THREAD')

    def fetching_changes(self, dcu, bttn):
        self.bttn = bttn
        self.dcu = ['DCU', dcu]
        self.reg_dcu = pickle.dumps(self.dcu)
        while True:
            self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            try:
                self.send_sock.connect(('127.0.0.1', 9999))  # Replace IP addr with IP Rad server
                self.bttn.configure(text='Connected')
                self.bttn['state'] = 'disable'
            except ConnectionRefusedError:
                messagebox.showerror('CONNECTING ERROR', 'UNABLE TO CONTACT SERVER, PLEASE CALL.\n '
                                                         '-ALBERTO TREVIÑO - CELL: 123 12345')
                self.bttn.configure(text='Connect')
                self.bttn['state'] = 'active'
                break
            self.send_sock.setblocking(True)
            self.send_sock.sendall(self.reg_dcu)
            self.response = pickle.loads(self.send_sock.recv(1024))
            if self.response != 'No_changes':
                self.name = self.response[1]
                self.job = str(self.response[3])
                self.reason = str(self.response[4])
                messagebox.showwarning('CHANGE ALERT', self.name + ' changed something in JOB: ' + self.job
                                       + " Reason:\n " + self.reason)
            else:
                print('No changes')
            self.send_sock.shutdown(socket.SHUT_RDWR)
            self.send_sock.close()
            time.sleep(10)

I hope someone finds it useful.

Related