A
A
Alexey Maslov2019-01-17 12:03:23
linux
Alexey Maslov, 2019-01-17 12:03:23

How to correctly close a tcp connection?

There is a service written in Go running on Ubuntu 16.04.
The essence of the work is that it polls about 30 servers.
After receiving data from the server, it must in response send information that the data has been received, in response to this, the server will throw another portion of data, and so on. It happens that the data on the server is over, and then I just fall asleep for 60 seconds, then everything is new.
It also happens that the servers do not respond (a network break or some other problem on the server side (it doesn’t matter)), in such cases I close the connection and try to connect again, after a certain interval.
So, after starting the service, I observe the following picture:
5c403ec5cf0a1064315090.png
Then, after some time (apparently when the disconnects occurred):
5c4043e149a38489791413.png
Which subsequently (after 6 hours) leads to an error:go dial error on addr dial tcp socket: to many open files
i.e. socket is created? B connection, as it were, remains in a suspended state?
Although the connection is explicitly closed: conn.Close()
example code to understand what's what:

//Сбор данных - вызов в гоурутине
func stantionListener(server Servers, p DataProducer)  {
  //Основной цикл для сервера
  for {
    conn, err := net.Dial("tcp", "адрес сервера")
    if err != nil {
      log.Fatal("dial error on addr:", addr, err)
      return
    }
    defer conn.Close()
    
    //Цикл, в котором происходит обмен с сервером данными
    for {
      if wr, err := conn.Write([]byte("Запрос к серверу")); //Запрос #1
        wr == 0 || err != nil {
        log.Println(addr, err)
        break
      }
      err = conn.SetReadDeadline(time.Now().Add(5 * time.Second))
      if err != nil {
        log.Println(addr, err)
        break
      }

      //Пытаемся получить данные в ответ
      buff := make([]byte, 1024)
      rd, err := conn.Read(buff)
      if err != nil{
        log.Println(addr, err)
      }

      err = res.Parser(buff[:rd])
      if err != nil {
        log.Println(err, stDesc)
      } else {
        //Отправляем запрос о том, что все ок
        if wr, err := conn.Write([]byte("ok, данные получил")); //Запрос #4
          wr == 0 || err != nil {
          log.Println(err, stDesc)
        }
      }

      d := time.Duration(kpi.current * float32(time.Second))
      time.Sleep(d)
    }//end for

    log.Println("error, when connect or receive data", stDesc, "wait 60seconds")
    time.Sleep(time.Minute) //Ждем 1 минуту, прежде чем выполнить повторное подключение
  }
}

As I understand it, when you reconnect to the same server, it creates instead of TYPE: IPv4 - sock, device: 0x7

Answer the question

In order to leave comments, you need to log in

2 answer(s)
I
igorzakhar, 2019-01-17
@lelick

Doesn't process the call:
due to an infinite loop.

V
vipsiteedit, 2021-02-25
@vipsiteedit

Close the connection at the end of the first conn.Close() loop, as the defer is only executed when the method ends.

.....
      d := time.Duration(kpi.current * float32(time.Second))
      time.Sleep(d)
    }//end for
    conn.Close()
    log.Println("error, when connect or receive data", stDesc, "wait 60seconds")
    time.Sleep(time.Minute) //Ждем 1 минуту, прежде чем выполнить повторное подключение
  }
}

Or make a separate method inside the first loop where you can use defer conn.Close()

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question