S7-300 PC Communication via TCP/IP: ISO-on-TCP and S7Comm

David Krause20 min read
S7-300SiemensTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

S7-300 PC Communication via TCP/IP: ISO-on-TCP and S7Comm Protocol Engineering Guide

Build a direct TCP/IP link from a Windows or Linux PC to a SIMATIC S7-300 CPU or an ET 200 station without deploying an OPC server. This reference covers the on-the-wire format (TPKT / COTP / S7Comm), STEP 7 V5.x and TIA Portal connection setup, the use of the on-board PROFINET port of a CPU 31x-2 PN/DP versus a CP 343-1 module, and a working C# and Python client built on the open-source Snap7 library. It also covers diagnostics with Wireshark, the bandwidth and cycle-time budget, and the field-proven troubleshooting matrix that resolves the eight most common reasons a fresh ISO-on-TCP link fails.

1. Overview and Use Case

The classical way to exchange data between a PC and a SIMATIC S7-300/ET 200S/ET 200M station is to install SIMATIC NET, expose variables through OPC, and consume them with an OPC client. That stack is correct in a plant, but it is overkill for a single-panel HMI, a service tool, a SCADA bridge, a test bench, or a Python/Node.js backend that just wants to read a few data blocks.

The S7-300 family already speaks a TCP/IP-based application protocol on the wire. Both the on-board Ethernet interface of a CPU 31x-2 PN/DP and every CP 343-1 / CP 343-1 Lean / CP 343-1 Advanced module implement ISO Transport over TCP (RFC 1006) on TCP port 102, and on top of that the proprietary S7 Communication (S7Comm) protocol that Siemens uses for PG, OP, and S7-connection services. Any PC that can open a TCP socket can implement a client, send a TPKT/COTP Connection Request, negotiate the S7 parameters, and execute read/write jobs against DB, I, Q, M, T, C, and the peripheral area.

The traffic pattern is identical to what the VIPA CP143 evaluation program, the Libnodave test tool, the Snap7 client, and the original STEP 7 PG functions generate. Captures against a VIPA SPEED7 CPU and a Siemens CPU 317-2 PN/DP confirm the same byte layout, the same function groups, and the same error codes.

What you give up versus OPC DA/UA: automatic tag browsing, security policies, redundancy, and certified interoperability. What you gain: a single C# class or a single Python module, no licence cost, no DCOM configuration, no firewall pinholes beyond TCP/102, and a deterministic request/response cycle that you can model on a whiteboard.

2. Protocol Architecture: ISO-on-TCP and S7Comm

Four layers separate the application data from the electrical signal. Understanding the boundary between them is the difference between a working client and a 30-hour capture session.

Layer PDU / Header Length Purpose
5 Application S7Comm Variable Read/Write/PI/PG requests, user data, CPU control
4 S7 transport S7 Header 10-12 bytes ROSCTR, PDU reference, parameter + data length
3 COTP (ISO 8073) COTP CR/CC/DT 3-18 bytes Connection establishment, data transfer, TPDU numbering
2 ISO-over-TCP (RFC 1006) TPKT 4 bytes Length framing so the TCP stream can be re-assembled
1 TCP/IP TCP 20+ bytes Reliable byte stream, port 102, three-way handshake

The transport selection is fixed for S7: ISO-on-TCP (S7-protocol "ISO-on-TCP connection" in NetPro) and S7-communication (the "S7 connection" with PUT/GET or one-sided fetch) both run on TCP/102. The TCP, ISO-over-TCP, and COTP layers are governed by open standards:

  • RFC 793 - Transmission Control Protocol
  • RFC 1006 - ISO Transport Service on top of the TCP
  • ISO 8073 / ITU-T X.224 - Connection-Oriented Transport Protocol (COTP)

The S7Comm layer is documented in the Siemens "SIMATIC Communication with SIMATIC S7" manual and reverse-engineered in the Snap7 and Wireshark dissectors. Function groups include 0x01 (read/write data), 0x02 (PI service: start/stop CPU), 0x03 (PG functions: password upload), 0x04 (SZL: system state list), and 0x07 (time). The most common field is 0x01 with subfunctions 0x04 (read var) and 0x05 (write var).

Use TCP port 102 by default. ISO-on-TCP connections on the S7-300 cannot be reassigned to a different port in the PLC firmware; a CP 343-1 Advanced can also host S7 connections, but the S7 protocol itself is hard-locked to 102 on the server side.

3. Hardware Prerequisites

Confirm the S7-300 station actually has an Ethernet port. Without that, none of this works.

Hardware Order Number (6ES7 ...) Built-in Ethernet Notes
CPU 312C 312-5BF04-0AB0 No Requires CP 343-1 Lean
CPU 313C-2 PTP 313-6BF04-0AB0 No Requires CP 343-1 Lean
CPU 314C-2 PN/DP 314-6EH04-0AB0 Yes (PROFINET 2-port switch) Port X1, supports ISO-on-TCP natively
CPU 315-2 PN/DP 315-2EH14-0AB0 Yes Standard PN CPU for ISO-on-TCP
CPU 317-2 PN/DP 317-2EK14-0AB0 Yes Two PN ports, recommended for heavy traffic
CPU 319-3 PN/DP 319-3EP04-0AB0 Yes High-end, supports large S7 PDUs (480 bytes)
CP 343-1 Lean 343-1CX10-0XE0 N/A 1 port, ISO-on-TCP and S7-comm, no PG/OP routing
CP 343-1 343-1EX30-0XE0 N/A 2-port switch, full S7/PG/OP/HTTP
CP 343-1 Advanced 343-1GX30-0XE0 N/A 2-port + IT functions, FTP, email, max 64 connections
ET 200S IM151-8 PN/DP 151-8AB01-0AB0 Yes Acts as S7-300 station for ISO-on-TCP purposes
ET 200SP IM155-6 PN 155-6AU01-0BN0 Yes PROFINET device, also supports S7 client PUT/GET via host CPU

The PC side can be any host with a TCP stack. Realistic field installations run Windows 10/11 with .NET 4.8 or .NET 6+, Windows IoT, Debian/Ubuntu LTS, or an embedded Linux on a Raspberry Pi 4. The same binary client runs unchanged on x64 and ARM64.

Network requirements: a managed switch is not required for a single client, but for production traffic, segment the PLC network with a managed switch that supports IGMP snooping and QoS for PROFINET. Bandwidth is modest - an S7 PDU carrying 480 bytes of payload consumes roughly 612 bytes on the wire including TPKT/COTP/S7 headers, TCP/IP headers, and the Ethernet frame preamble/SFD/FCS - so 100 Mbit/s is never the bottleneck.

4. STEP 7 V5.x and TIA Portal Connection Configuration

Two distinct configuration models exist, and field engineers confuse them constantly.

Model A: ISO-on-TCP connection (configured, bilateral). The PC application is a known active partner; the S7-300 is the passive server. Both sides have a configured connection block, the local TSAP and the partner TSAP are defined, and the PC calls the connection by name. This is what you set up in STEP 7 V5.x with NetPro or in TIA Portal under Devices & Networks. The advantage is that the connection is owned by the PLC program (using FB12/FB13 BSEND/BRCV or AG_SEND/AG_RECV), so the data is delivered deterministically into a configured DB.

Model B: S7-connection with PUT/GET (single-sided, no PC project in STEP 7). The PC opens a TCP/102 connection, identifies itself as an "OP" or "unspecified" partner, and the S7-300 CPU serves read/write jobs without any pre-configured connection block. This is the model used by Libnodave, Snap7, and the OPC-DA-on-S7 drivers. It is faster to deploy because you do not touch the STEP 7 project - you only tick "Permit PUT/GET access by remote partner (PLC, HMI, OPC, ...)" on the CPU protection properties.

For Model B to work, the CPU must have PUT/GET enabled. The default on a brand-new CPU is "Permit only with configuration". Change it to "Permit always" or, on recent firmware, define an "Access level 1 (no protection)" and a permissive list of partner objects. Refer to the SIMATIC S7-300 CPU 31xC and CPU 31x operating instructions for the exact dialog path.

4.1 STEP 7 V5.x NetPro Procedure (Model A)

  1. Open the S7-300 station in SIMATIC Manager and launch NetPro.
  2. Select the CPU (or CP 343-1) object on the left, right-click, "Insert New Connection".
  3. Connection partner: "Unspecified". Connection type: "ISO-on-TCP connection".
  4. On the Addresses tab set the partner IP, the partner TSAP, and the local TSAP. The TSAP is a 2-byte ASCII string. For a S7-300 CPU at rack 0, slot 2, the local TSAP is "01.01" (rack 0 = 0x01, slot 1 for the CP internal slot = 0x01, ASCII "01.01"). Format the partner TSAP the same way: for a PC application use a fixed ASCII string such as "PC.01" or a 2-byte hex value such as 0x10 0x01.
  5. On the General tab enable "Establish an active connection" if the PC is the active partner.
  6. Compile and download the connection configuration to the CPU.
  7. From the S7 program side, the connection ID is now visible in the connection table. Use FB12 "BSEND" and FB13 "BRCV" with the assigned ID for any-length data, or FB8 "USEND" and FB9 "URCV" for 4-byte messages. The CPU firmware consumes the configured connection; you cannot open it twice.

4.2 TIA Portal Procedure (Model A or B)

  1. Open the project, select Devices & Networks.
  2. Click the CPU in the network view. The PROFINET port properties show the IP address, subnet mask, and, in the Advanced Options > User-defined connection resources, the maximum number of S7 connections (typically 16 for a CPU 31x-2 PN/DP).
  3. For Model A: right-click the CPU, "Properties > Connection resources", or use the "Connections" button at the top. Add an ISO-on-TCP connection, set partner address and TSAPs as above.
  4. For Model B: CPU Properties > Protection > "Permit access with PUT/GET communication from remote partner" = Enabled. No connection block required.
  5. Compile, download the hardware configuration, and verify in the CPU diagnostic buffer that the S7-300 accepted the configuration (event ID W#16#4301 "Connection established").

5. S7Comm Message Format and Frame Layout

The S7 PDU is wrapped in three headers, in order from outer to inner: TPKT, COTP, S7. Knowing the byte layout is the difference between a library user and a library writer.

5.1 TPKT Header (4 bytes)

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Version (3)  |    Reserved   |          Length               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       0x03              0x00              16-bit big-endian, includes
                                          the 4-byte TPKT header

5.2 COTP Connection Request (CR, sent PC -> PLC)

Byte  Value   Meaning
0     0x11    COTP PDU length (17 bytes follow)
1     0xE0    PDU type: Connection Request (CR)
2-3   0x0000  Destination reference (0 on CR)
4-5   0x0001  Source reference (any non-zero)
6     0x00    Class option, prefer Class 0 (no flow control)
7-17  Parameters (TPDU size, src TSAP, dst TSAP, ...)
       Byte  7  = 0xC1 (Parameter code: src TSAP)
       Byte  8  = 0x01 (length 1)
       Byte  9  = TSAP[0]    }
       Byte 10  = TSAP[1]    } 2-byte ASCII or hex TSAP
       Byte 11 = 0xC2 (Parameter code: dst TSAP)
       Byte 12 = 0x01 (length 1)
       Byte 13 = TSAP[0]    }
       Byte 14 = TSAP[1]    }
       Byte 15 = 0xC0 (Parameter code: TPDU size)
       Byte 16 = 0x01 (length 1)
       Byte 17 = 0x0A (TPDU size 1024 = 0x0A, 512 = 0x09, 128 = 0x07)

The PLC replies with a COTP Connection Confirm (CC) where byte 1 is 0xD0 and the source/destination references are swapped. After the CC, all subsequent COTP frames are COTP Data (DT) TPDUs - 3 bytes: 0x02, 0xF0, 0x80 (length, DT, TPDU number 0 + EOT bit).

5.3 S7 Header (carried in COTP DT data)

Byte  Value   Meaning
0     0x32    S7 protocol ID (constant)
1     ROSCTR  0x01 Job request (PC -> PLC)
                0x02 Ack (no data)
                0x03 AckData (response with payload)
                0x07 UserData (no ack on S7-300/400, used for PUT/GET)
2-3   0x0000  Redundancy identification (reserved)
4-5   WORD    PDU reference (rolling counter 1..65535)
6-7   WORD    Parameter length (big-endian)
8-9   WORD    Data length (big-endian)

5.4 S7 Read Job (function group 0x01, subfunction 0x04)

Parameters (after the 10-byte S7 header):
Byte 0-1   0x00 0x04   Function: Read Var
Byte 2     0x01        Item count (1 item in this PDU)
Byte 3     0x12        Item specification: variable specification
Byte 4     0x0A        Specification length: 10 bytes
Byte 5     0x10        Syntax ID: S7ANY (data-block access)
Byte 6     0x02        Transport size: BYTE (0x02 BYTE, 0x04 WORD, 0x05 DWORD, 0x07 REAL, 0x09 DINT)
Byte 7-8   COUNT       Number of items to read (in transport-size units)
Byte 9-10  DB_NR       Data block number (only used when area = DB)
Byte 11    AREA        0x84 DB, 0x81 Inputs (I), 0x82 Outputs (Q),
                        0x83 Merkers (M), 0x85 PI, 0x86 PQ, 0x87 TM/CTC
Byte 12-14 BYTE_OFF    3-byte byte offset, big-endian

A complete PC->PLC PDU reading 100 bytes of DB10 starting at byte 0 looks like this in hexadecimal (TPKT and S7 header in red for clarity):

03 00 00 19   TPKT (length 25)
02 F0 80      COTP DT
32 01         S7 protocol ID, ROSCTR Job
00 00 00 00  Redundancy, PDU ref = 0
00 0E 00 00  Parameter length 14, data length 0
00 04 01      Read Var, 1 item
12 0A 10      Variable spec, length 10, S7ANY
02 00 64      Transport BYTE, count 100
00 0A         DB 10
84 00 00 00   Area DB, offset 0

The PLC reply contains the same PDU reference, ROSCTR = 0x03 (AckData), the same parameter block, a data block prefix of 4 bytes (0xFF, repeat of function 0x04, item count, return code 0xFF = success), and then the raw payload bytes.

6. Client Implementation: Libraries vs Raw Sockets

Three approaches are realistic for an industrial PC project. They differ in build effort, licence cost, and vendor lock-in.

Approach Library Language PDU size CPU per request Notes
Open source wrapper Snap7 C / C++ / .NET / Java / Python (python-snap7) Up to 960 bytes read, 960 bytes write Lowest - direct C client Active project, supports S7-300/400/WinAC/LOGO!/S7-1200/1500
Open source wrapper Libnodave (Thomas Hergenhahn) C / C++ / Java / .NET / Pascal Up to 222 bytes per PDU Low Older, smaller, no security, no OPC UA bridge
Raw socket None - handcrafted Any Whatever you code Higher, full control Use only if the library does not support the required SZL/PI function

Snap7 is the default choice for new projects. The prebuilt binaries are signed, the API is C-style stable, and the .NET wrapper (snap7.net) compiles cleanly under .NET 6 and .NET Framework 4.8. Libnodave is smaller and works on microcontrollers, but its PDU payload is capped at 222 bytes which means a 1 kB DB read requires five round-trips.

If you must roll your own - for example to access system state lists that Snap7 does not expose - use the byte layouts from section 5, validate the TPKT length on every read, and use a state machine for COTP connection establishment. The state machine is a four-state Mealy machine: CLOSED, AWAIT_CR, AWAIT_DT, OPEN. After the CC PDU arrives, the connection is open and remains open until the TCP socket drops or the PLC sends a COTP DR (Disconnect Request) with PDU type 0x80.

7. Worked Example: C# Client with Snap7

The following is a self-contained C# console program that reads the first 100 bytes of DB10 from a CPU 317-2 PN/DP at IP 192.168.0.20. It works against any S7-300/ET 200S/ET 200M station that has PUT/GET enabled.

using System;
using System.Linq;
using Snap7;

Reference the Snap7 .NET wrapper (Snap7.Net.dll) and the unmanaged snap7.dll for your target architecture (x86, x64, or arm64). On Windows, drop both DLLs into the same directory as the executable.

namespace S7ReadExample
{
    internal static class Program
    {
        private static int Main(string[] args)
        {
            // CPU IP, rack, slot. For a CPU 31x-2 PN/DP at rack 0, slot 2:
            // rack=0, slot=2. For a CP 343-1 at rack 0, slot 4: rack=0, slot=4.
            var client = new S7Client();
            int rc = client.ConnectTo("192.168.0.20", 0, 2);
            if (rc != 0)
            {
                Console.Error.WriteLine($"Connect failed: {client.ErrorText(rc)}");
                return 1;
            }

            // Allocate buffer: 100 bytes for DB10 starting at byte 0.
            byte[] buffer = new byte[100];
            rc = client.DBRead(10, 0, buffer.Length, buffer);
            if (rc != 0)
            {
                Console.Error.WriteLine($"DBRead failed: {client.ErrorText(rc)}");
                client.Disconnect();
                return 2;
            }

            // Decode a few fields. Real at DBW0, INT at DBW4, BOOL at DB6.0.
            float realValue = BitConverter.ToSingle(BitConverter.IsLittleEndian
                ? buffer.Take(4).Reverse().Concat(new byte[4]).Take(4).ToArray()
                : buffer, 0);
            short intValue  = BitConverter.ToInt16(BitConverter.IsLittleEndian
                ? buffer.Skip(4).Take(2).Reverse().ToArray()
                : buffer.Skip(4).Take(2).ToArray(), 0);
            bool bitValue   = (buffer[6] & 0x01) != 0;

            Console.WriteLine($"DB10.DBD0 REAL = {realValue:F3}");
            Console.WriteLine($"DB10.DBW4 INT  = {intValue}");
            Console.WriteLine($"DB10.DBX6.0 BOOL = {bitValue}");

            // Periodic poll: 200 ms cycle is safe; CPU class 1 cyclic OB1 is 100 ms.
            // For tighter loops use BCycleTime in the OB1 properties.
            client.Disconnect();
            return 0;
        }
    }
}

For a Python equivalent, install python-snap7 with pip install python-snap7 and use the same primitive:

import snap7
from snap7.util import get_real, get_int, get_bool

client = snap7.client.Client()
client.connect("192.168.0.20", 0, 2, 102)  # IP, rack, slot, port

data = client.db_read(10, 0, 100)
print("REAL @ DBW0 =", get_real(data, 0))
print("INT  @ DBW4 =", get_int(data, 4))
print("BOOL @ DBX6.0 =", get_bool(data, 6, 0))

client.disconnect()
The argument order in the Python API differs from C#: connect(IP, rack, slot, tcp_port). The C# overload is ConnectTo(IP, rack, slot) and the TCP port defaults to 102. The rack and slot must match the physical position of the Ethernet interface, not the CPU itself when the link goes through a CP 343-1.

8. Verification and Diagnostics with Wireshark

Wireshark 3.6+ ships a S7Comm dissector that decodes TPKT/COTP/S7 frames in real time. Filter on the PLC IP and observe the exchange after the client calls Connect():

ip.addr == 192.168.0.20 && tcp.port == 102

The expected sequence is:

  1. TCP three-way handshake (SYN, SYN+ACK, ACK).
  2. COTP CR from PC to PLC. Source TSAP is your configured string (e.g. PC.01). Destination TSAP is 01.01 for a CPU 31x-2 PN/DP at rack 0, slot 2.
  3. COTP CC from PLC. TPDU size should be 1024 (0x0A) for any modern CP and 512 (0x09) for a CPU 31x-2 PN/DP.
  4. S7 Setup Communication (function 0xF0, ROSCTR 0x01) from PC, immediately followed by S7 Read SZL (function group 0x04, SZL ID 0x0111/0x0112/0x0019) - these are mandatory negotiations the CPU performs before serving application data.
  5. S7 Read Var / S7 Write Var job-and-ack pairs.

If the COTP CC does not arrive, the CPU rejected the connection. Common rejection reasons show up in the CPU diagnostic buffer as event IDs W#16#4302 (connection rejected, no resources), W#16#4303 (connection rejected, partner not configured), or W#16#4304 (connection rejected, access protection). Open the CPU online with STEP 7 / TIA Portal and inspect "Diagnostic buffer > Events".

9. Bandwidth and Cycle-Time Budget

Use the following rule of thumb before committing the design:

For a CPU 31x-2 PN/DP the S7 user data per request is capped by the negotiated PDU size, which the Setup Communication job selects from the SZL. Typical values are 240 bytes (firmware 3.x) up to 480 bytes (firmware 3.3+). The full round-trip on a 100 Mbit/s wire with no other traffic is 5-10 ms for a single read; on a 1 Gbit/s link it is 1-3 ms.

To estimate the wire load, sum the per-PDU cost:

WireBytes = S7Payload + 10 (S7 header) + 3 (COTP DT) + 4 (TPKT)
            + 20 (TCP header) + 20 (IP header) + 26 (Ethernet preamble/IPG/FCS)
            + application ACKs (typically full duplex, no extra)

For 100 bytes of payload that is approximately 183 bytes per request. At a 200 ms poll rate, 5 requests per second, that is 0.9 kB/s - less than 0.01% of a 100 Mbit/s link. The CPU load, not the wire, is the limiting factor. A CPU 315-2 PN/DP sustained at 100 S7 requests per second uses roughly 5-10% of the OB1 cycle, depending on data complexity.

10. Troubleshooting Matrix

Symptom Capture / Log Evidence Root Cause Fix
TCP SYN, no SYN+ACK No reply from PLC Wrong IP, firewall, wrong VLAN, port blocked Ping the CPU. Disable host firewall. Allow TCP/102 in any intermediate ACL.
COTP CR sent, COTP RJ received PDU type 0xD2 with reason byte TSAP not configured, access protection, rack/slot mismatch Verify the destination TSAP matches the CPU/CP rack and slot. Enable PUT/GET in CPU Protection.
Connection open, DBRead returns -1 S7 response return code 0x05 / 0x0A DB does not exist, area not in CPU, wrong DB number Confirm the DB is downloaded and not optimized-block (optimized blocks are not directly addressable - link a non-optimized instance or use Symbolic I/O names).
Reads succeed, writes succeed, but values bounce Capture shows read of stale buffer Read area is a non-process image (PI/PQ) and the CPU does not refresh it Use area 0x84 (DB) or 0x83 (M) for cross-cell communication; reserve PI/PQ for fast I/O update.
Connection drops every 30 s Keep-alive timeout TCP keep-alive not enabled on host Set SO_KEEPALIVE; send a S7 Read SZL job every 5 s; lower the OS default timeouts (Linux: net.ipv4.tcp_keepalive_time=30).
Slow first read (2-3 s), fast subsequent SZL negotiation only on first call Normal behaviour Keep the connection warm by pooling; do not reconnect for every read.
WinCC flexible / TIA HMI can read, Snap7 cannot Compare COTP CR in both captures HMI uses OP TSAP, your code uses PC TSAP, access protection blocks other TSAPs Whitelist the PC TSAP in the CPU access list, or switch to "Permit always" for the connection resource.
Compile succeeds, runtime IO exception on x64 Snap7.dll architecture mismatch Mixing x86 and x64 DLLs Copy the matching snap7.dll (x64 or x86) into the build output for the active platform.

11. Field-Proven Tips

  • Capture first, code second. Wireshark against a working STEP 7 PG run tells you exactly what TSAPs and SZLs your CPU accepts.
  • Keep one S7 client per process. Multiple threads on a single S7Client serialise internally, and the locking makes write contention worse, not better.
  • Reuse the connection. Setup Communication is the expensive call; once negotiated, every job is a single round-trip.
  • Use the CPU diagnostic buffer as the primary error log. STEP 7 events 0x4301-0x4304 and 0x4531 describe connection lifecycle. TIA Portal shows the same under Online & Diagnostics > Diagnostic buffer.
  • Document your TSAPs in the PLC program header. The next engineer will need them.

12. References

  • SIMATIC S7-300 CPU 31xC and CPU 31x, Operating Instructions (Siemens support, manual entry ID 13008499).
  • SIMATIC NET, S7 Communication - Programming Interface (Siemens support, manual entry ID 1254686).
  • SIMATIC Communication with SIMATIC S7, System Manual (Siemens support, manual entry ID 15338125).
  • STEP 7 V5.x, Configuring Hardware and Communication Connections (Siemens support, manual entry ID 18652696).
  • TIA Portal, S7-300/S7-400 Programming and Operating Manual (Siemens support, manual entry ID 109751826).
  • RFC 1006 - ISO Transport Service on top of the TCP (IETF).
  • RFC 793 - Transmission Control Protocol (IETF).
  • ISO/IEC 8073 / ITU-T X.224 - Connection-Oriented Transport Protocol (ISO).

What TCP port does an S7-300 use for ISO-on-TCP and S7 communication?

Both ISO-on-TCP connections and S7 connections (PUT/GET) listen on TCP port 102 on the S7-300 CPU and on CP 343-1 modules. The port is hard-coded and cannot be reassigned in the PLC firmware. Configure any host firewall and intermediate ACL to allow TCP/102 from the PC to the CPU.

How do I enable PUT/GET access on an S7-300 CPU so Snap7 or Libnodave can read it?

Open the CPU in STEP 7 or TIA Portal, go to Properties > Protection, and set "Connection mechanisms > Permit access with PUT/GET communication from remote partner" to Enabled. On a CPU 31x-2 PN/DP with firmware 3.3 and later the option may appear under "Access level 1 (no protection) > Permit PUT/GET". Save, recompile, and download the hardware configuration.

What is the difference between an ISO-on-TCP connection and an S7 connection?

An ISO-on-TCP connection is a bilateral configured connection set up in NetPro or TIA Portal Devices & Networks. The PLC program owns it through FB12 BSEND / FB13 BRCV (or AG_SEND / AG_RECV on older code). An S7 connection is a single-sided connection; the CPU serves read/write jobs from a remote partner without any pre-configured block, as long as PUT/GET is enabled. Both run on TCP/102 with the same TPKT/COTP/S7 frame layout.

What rack and slot do I pass to Snap7 when the link goes through a CP 343-1?

Pass the rack and slot of the CP 343-1 itself, not the CPU. For a CP at slot 4 in rack 0, call client.ConnectTo("ip", 0, 4). The S7-300 CPU has a fixed internal slot (slot 2 for the CPU 31x-2 PN/DP and most other S7-300 CPUs), but a CP 343-1 is addressed by the physical slot in which the module is inserted.

Why can WinCC flexible read a DB but Snap7 gets return code 0x05 (object does not exist)?

WinCC flexible uses symbolic or absolute access, and the DB it reads is typically non-optimized. Snap7/Libnodave only access the absolute address layout. If the DB is "optimized" (the default for new S7-1500 blocks, optional on S7-300), the absolute offset is hidden and direct read returns 0x05. Either uncheck "Optimized block access" on the DB properties and re-download, or use a non-optimized shadow DB that mirrors the data.

Back to blog