Skip to content

Connection left open after .disconnect() #972

Open

Description

@pmpn8ez

2 Different PLC's
S7-314C-2 PN/DP Newer better
S7-313C-2 DP - Old junk connected to ethernet via CP 343-1

I ran this on both
import snap7
import time
PLC_IP = "192.168.1.99" #192.168.2.122 for 314
RACK = 0
SLOT = 2

client = snap7.client.Client()
client.connect(PLC_IP, RACK, SLOT)
print(client.connected)
data = client.mb_read(0, 1)
print(data[0])
time.sleep(10)
client.disconnect()
print(client.connected)
client.destroy()

On the 314 I can watch the connection in online diagnostics go up by one, then down by 1 - Awesome
On the 313 the communication resource count goes up by 1.... then NEVER goes back down until i reset the plc.

Is this an issue with the driver package or the fact I'm going through a CP 343-1??

Activity

  1. gijzelaerr commented on Nov 5, 2026

    @gijzelaerr
    Owner

    Thanks for the clear comparison. From the code, disconnect() does the same thing on both PLCs: it sends a COTP disconnect request and closes the TCP socket. Since the 314 releases its connection and the 313 doesn't, the CP 343-1 looks like the likely difference, but I can't confirm that from here.

    Two things would narrow it down:

    1. A Wireshark capture of your script going through the CP, filtered on tcp.port == 102. That shows whether the disconnect request and TCP FIN go out, and how the CP answers.
    2. The same script with python-snap7 2.x, the version that wraps the native Snap7 library, on the same PLC. If the count also stays up there, it's on the CP side. If it goes back down, we're doing something different and the capture will show what.

    Also, does the count keep climbing if you run the script repeatedly, until the CP refuses connections? That tells us how much this matters in practice.

  2. pmpn8ez commented on Nov 5, 2026

    @pmpn8ez
    Author

    Yes, i keep overloaded the 8 allowed connections, if i open/close it 8 times the plc starts refusing / i cant go online. Power cycle, and its back down to 0, until i go online at 1 of course. Very much matters when trying to use it for an hmi.

    After that good news/bad news
    I have an old HMI i built that i use for classes... not sure if i ever tried it but it will not connect to the 313C via CP343.
    Tried the same script as above installing v2.1.0 from pip got this is python...

    got this b' ISO : An error occurred during recv TCP : Connection timed out'
    Traceback (most recent call last):
    File "d:\Code\oldsnap7test\test.py", line 8, in
    client.connect(PLC_IP, RACK, SLOT)
    File "d:\Code\oldsnap7test.venv\Lib\site-packages\snap7\client.py", line 197, in connect
    check_error(self._lib.Cli_ConnectTo(self._s7_client, c_char_p(address.encode()), c_int(rack), c_int(slot)))
    File "d:\Code\oldsnap7test.venv\Lib\site-packages\snap7\error.py", line 142, in check_error
    raise RuntimeError(error)
    RuntimeError: b' ISO : An error occurred during recv TCP : Connection timed out'

    So good news the new pure python driver works better, bad news i can't prove either way if the cp343 keeps the connection alive.

  3. gijzelaerr commented on Nov 6, 2026

    @gijzelaerr
    Owner

    Thanks for trying 2.x. That it can't connect through the CP at all is useful to know too, even if it rules out the comparison.

    That leaves the capture as the way to find out what happens. If you can, run the script once through the CP with Wireshark on tcp.port == 102, starting from a power-cycled PLC, and attach the pcap or a screenshot of the packet list. What I'm looking for is whether our disconnect request and the TCP FIN go out, and what the CP sends back.

    Until then, for an HMI, keeping one connection open and reusing it avoids running out of the 8 connections.

  4. pmpn8ez commented on Nov 6, 2026

    @pmpn8ez
    Author

    Attached zip containing capture.
    Power cycle, verified only 1 connection (Me) went offline
    Ran above script, connections now 2 (me and open connection)

    Issue972.zip

  5. gijzelaerr commented on Nov 7, 2026

    @gijzelaerr
    Owner

    Thanks, @pmpn8ez, the capture shows the problem straight away, and it's on our side.

    When the CP accepts the connection (frame 6), it gives its own connection reference in the COTP connection confirm:

    CC  d0  00 01  44 31 ...   destination 0x0001 (ours, echoed), source 0x4431 (the CP's)
    

    Our disconnect request (frame 14) should be addressed to the CP's reference, 0x4431. It went to 0x0001 instead:

    DR  80  00 01  00 01 00 00   destination 0x0001 (wrong), source 0x0001
    

    python-snap7 read the reference from the wrong field of the confirm. The CP answers that request with two resets, which fits it never releasing the connection. The 314's own port releases it anyway, which is why only the CP showed the problem.

    #979 fixes this in both clients. Could you try it from that branch?

    pip install "git+https://github.com/gijzelaerr/python-snap7@fix/cotp-peer-reference"
    
    1. Starting from a power-cycled PLC, run your script from the first post 8 or more times in a row, and check in online diagnostics whether the communication resource count goes back down each time.
    2. If you can, capture one of those runs as before. The disconnect request should now say 80 44 31 00 01 (or whatever reference the CP hands out that time).

    If the count still climbs, the capture will show what the CP does with the corrected request, and we'll look at the close sequence next. Right now we close the TCP connection 0.04 ms after sending the request, without waiting for the CP.

  6. pmpn8ez commented on Nov 9, 2026

    @pmpn8ez
    Author

    Still leaving the connection open, fresh .venv
    pip install "git+https://github.com/gijzelaerr/python-snap7@fix/cotp-peer-reference"
    ran my test and it goes up everytime
    Capture attached

    Issue972_2.zip

  7. gijzelaerr commented on Nov 11, 2026

    @gijzelaerr
    Owner

    Thanks for the second capture, @pmpn8ez. It shows #979 did its part: the disconnect request now goes to the CP's reference (80 44 31 00 01). The problem is what comes right after it:

    • our FIN follows the request 48 µs later, before the CP can answer it;
    • the CP answers both with a reset and never sends a disconnect confirm;
    • half a second later the CP still sends an ACK on that connection, so it hasn't really let go of it.

    The first capture has the same sequence. #987 changes two things:

    1. disconnect() now waits up to one second for the CP to confirm the request, or close the connection itself, before our side closes.
    2. The request loses a stray zero byte after its header. ISO class 0 doesn't allow data in a disconnect request, and a strict CP may treat it as an error.

    Could you try it the same way as before?

    pip install "git+https://github.com/gijzelaerr/python-snap7@fix/disconnect-close-sequence"
    

    Run your script a few times from a power-cycled PLC and check the resource count. A capture of one run would show whether the CP now answers with a disconnect confirm (03 00 00 09 05 c0 …), and how long it takes.

  8. pmpn8ez commented on Nov 11, 2026

    @pmpn8ez
    Author

    Still staying open. Again deleted .venv, created new one, install via command above.

    Issue972_3.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions