TCP:服务器和客户端的示例
- 创建标准项目并选择 CODESYS Control Win V3 作为设备。
- 通过网络扫描连接目标系统。

从 SP16 开始:
- 打开库管理器并添加以下库: Net Base Services SysTypes2 interface s SysTimeRtc Util

- 创建一个名为 gvlSetting 的全局变量列表 ,并定义以下变量:
声明
VAR_GLOBAL CONSTANT
gc_wMaxTelegram : INT := 15;
gc_uiPort : UINT := 50001;
END_VAR
VAR_GLOBAL
gc_stIpAddr : String(19) := '192.168.99.109';
END_VAR
使 IP 地址和端口与系统对应。
- 创建一个名为 TcpServer 的新 POU ,并按如下进行修改:
声明
VAR CONSTANT
c_wMaxTelegram : INT := 15;
END_VAR
VAR
ipAddress : NBS.IPv4Address;
fbTcpConnection : NBS.TCP_Connection;
fbTcpServer : NBS.TCP_Server;
fbTcpRead : NBS.TCP_Read;
fbTcpWrite : NBS.TCP_Write;
abyRx : ARRAY [0..gvlSetting.gc_wMaxTelegram] OF BYTE;
abyTx : ARRAY [0..gvlSetting.gc_wMaxTelegram] OF BYTE;
iIndex : INT;
xRead : BOOL := TRUE;
xWrite : BOOL := TRUE;
xAckTelegram : BOOL;
xBlockAck : BOOL;
udiRead : DINT;
END_VAR
实现
IF fbTcpRead.xReady THEN
IF (fbTcpRead.udiCount = (gvlSetting.gc_wMaxTelegram + 1)) THEN
IF ((abyRx[0] = 87) AND (abyRx[1] = 68) AND (abyRx[2] = 58) AND (abyRx[3] = 32)) THEN // 'WD: ' = Watchdog-Telegram
FOR iIndex := 0 TO c_wMaxTelegram DO
abyTx[iIndex] := 0;
END_FOR
// 'ACK: ' = Acknowledge-Telegram
abyTx[0] := 65;
abyTx[1] := 67;
abyTx[2] := 75;
abyTx[3] := 58;
abyTx[4] := 32;
// Receive-Counter
abyTx[5] := abyRx[4];
abyTx[6] := abyRx[5];
abyTx[7] := abyRx[6];
abyTx[8] := abyRx[7];
xWrite := TRUE;
END_IF
xWrite := TRUE;
END_IF
ELSIF fbTcpRead.xError THEN
xRead := FALSE;
END_IF
fbTcpWrite(xExecute := xWrite AND NOT xBlockAck, itfConnection := fbTcpConnection, udiSize := SIZEOF(abyTx), pData := ADR(abyTx), udiTimeOut := 0);
IF fbTcpWrite.xDone OR fbTcpWrite.xError THEN
xWrite := FALSE;
END_IF
- 创建一个名为 TcpClient 的新 POU ,并按如下进行修改:
声明
VAR CONSTANT
c_tInterval : TIME := T#1S;
c_udiInterval : UDINT := 3 * TIME_TO_UDINT(c_tInterval)/1000;
END_VAR
VAR
ipAddress : NBS.IPv4Address;
fbTcpClient : NBS.TCP_Client;
fbTcpRead : NBS.TCP_Read;
fbTcpWrite : NBS.TCP_Write;
abyTx : ARRAY [0..gvlSetting.gc_wMaxTelegram] OF BYTE;
abyRx : ARRAY [0..gvlSetting.gc_wMaxTelegram] OF BYTE;
fbBlink : BLINK := (TIMELOW := c_tInterval, TIMEHIGH := c_tInterval);
xBlink : BOOL; // Memory of the last state of PLC_PRG.fbBlink
udiVal : UDINT;
pudiVal : POINTER TO BYTE;
iIndex : INT;
xConnect : BOOL;
xRead : BOOL;
xMissingAck : BOOL;
udiResult : UDINT;
udiLastAck : UDINT;
udiNow : UDINT;
udiRead : UDINT;
eRErrorID : NBS.ERROR;
eWErrorID : NBS.ERROR;
END_VAR
实现
IF NOT fbTcpClient.xActive THEN
ipAddress.SetInitialValue(ipAddress := gvlSetting.gc_stIpAddr);
END_IF
fbTcpClient(xEnable := xConnect, itfIPAddress := ipAddress, uiPort := gvlSetting.gc_uiPort, udiTimeOut := 0);
fbBlink(ENABLE := TRUE);
IF (fbBlink.OUT AND (xBlink <> fbBlink.OUT) ) THEN
udiVal := udiVal + 1;
FOR iIndex := 0 TO gvlSetting.gc_wMaxTelegram DO
abyTx[iIndex] := 0;
END_FOR
// 'WD: ' = Watchdog-Telegram
abyTx[0] := 87;
abyTx[1] := 68;
abyTx[2] := 58;
abyTx[3] := 32;
// Counter
pudiVal := ADR(udiVal);
abyTx[4] := pudiVal^;
pudiVal := pudiVal + 1;
abyTx[5] := pudiVal^;
pudiVal := pudiVal + 1;
abyTx[6] := pudiVal^;
pudiVal := pudiVal + 1;
abyTx[7] := pudiVal^;
fbTcpWrite(xExecute := xConnect,itfConnection := fbTcpClient.itfConnection, udiTimeOut := 0, udiSize := SIZEOF(abyTx), pData := ADR(abyTx));
ELSE
fbTcpWrite(xExecute := FALSE);
END_IF
xBlink := fbBlink.OUT;
fbTcpRead(xEnable := xRead AND xConnect, itfConnection := fbTcpClient.itfConnection, udiSize := SIZEOF(abyRx), pData := ADR(abyRx), udiCount => udiRead);
IF fbTcpRead.xReady THEN
IF (fbTcpRead.udiCount = (gvlSetting.gc_wMaxTelegram + 1)) THEN
IF ((abyRx[0] = 65) AND (abyRx[1] = 67) AND (abyRx[2] = 75) AND (abyRx[3] = 58) AND (abyRx[4] = 32)) THEN // 'WD: ' = Watchdog-Telegram
udiLastAck := SysTimeRtc.SysTimeRtcGet(udiResult);
END_IF
END_IF
ELSIF fbTcpRead.xError THEN
fbTcpRead(xEnable := FALSE);
END_IF
IF NOT fbTcpClient.xActive AND NOT fbTcpClient.xBusy AND NOT fbTcpClient.xDone THEN
xConnect := TRUE;
ELSIF fbTcpClient.xDone THEN
xConnect := FALSE;
END_IF
udiNow := SysTimeRtc.SysTimeRtcGet(udiResult);
IF (udiNow > (udiLastAck + c_udiInterval)) THEN
xMissingAck := TRUE;
ELSE
xMissingAck := FALSE;
END_IF
- 修改 PLC_PRG 如下:
实现
TcpServer();
TcpClient();
- 将项目加载到控制器并启动它。将变量 TcpClient.xRead 设置为 TRUE。

SP16 之前:
- 打开库管理器并添加以下库: CAA Net Base Services SysTypes2 interface s SysTimeRtc Util

- 创建一个名为 gvlSetting 的全局变量。 修改 gvlSetting 如下:
声明
{attribute 'qualified_only'}
VAR_GLOBAL CONSTANT
gc_uiPort : UINT := 50001;
gc_stIpAddr : NBS.IP_ADDR := (sAddr := '192.168.99.74');
gc_wMaxTelegram : INT := 15; // Length o the telegram
END_VAR
使 IP 地址和端口与系统对应。
- 创建一个名为 TcpServer 的新 POU ,并按如下进行修改:
声明
VAR CONSTANT
c_wMaxTelegram : INT := 15;
END_VAR
VAR
fbTcpConnection : NBS.TCP_Connection;
fbTcpServer : NBS.TCP_Server;
fbTcpRead : NBS.TCP_Read;
fbTcpWrite : NBS.TCP_Write;
abyRx : ARRAY [0..gvlSetting.gc_wMaxTelegram] OF BYTE;
abyTx : ARRAY [0..gvlSetting.gc_wMaxTelegram] OF BYTE;
iIndex : INT;
xRead : BOOL := TRUE;
xWrite : BOOL := TRUE;
xAckTelegram : BOOL;
xBlockAck : BOOL;
udiRead : UDINT;
END_VAR
实现
fbTcpServer(xEnable := TRUE, ipAddr := gvlSetting.gc_stIpAddr, uiPort := gvlSetting.gc_uiPort);
fbTcpConnection(xEnable := fbTcpServer.xBusy, hServer := fbTcpServer.hServer);
fbTcpRead(xEnable := fbTcpConnection.xActive, hConnection := fbTcpConnection.hConnection, szSize := SIZEOF(abyRx), pData := ADR(abyRx), szCount => udiRead);
IF fbTcpRead.xReady THEN
IF (fbTcpRead.szCount = (gvlSetting.gc_wMaxTelegram + 1)) THEN
IF ((abyRx[0] = 87) AND (abyRx[1] = 68) AND (abyRx[2] = 58) AND (abyRx[3] = 32)) THEN // 'WD: ' = Watchdog-Telegram
FOR iIndex := 0 TO c_wMaxTelegram DO
abyTx[iIndex] := 0;
END_FOR
// 'ACK: ' = Acknowledge-Telegram
abyTx[0] := 65;
abyTx[1] := 67;
abyTx[2] := 75;
abyTx[3] := 58;
abyTx[4] := 32;
// Receive-Counter
abyTx[5] := abyRx[4];
abyTx[6] := abyRx[5];
abyTx[7] := abyRx[6];
abyTx[8] := abyRx[7];
xWrite := TRUE;
END_IF
xWrite := TRUE;
END_IF
ELSIF fbTcpRead.xError THEN
xRead := FALSE;
END_IF
fbTcpWrite(xExecute := xWrite AND NOT xBlockAck, hConnection := fbTcpConnection.hConnection, szSize := SIZEOF(abyTx), pData := ADR(abyTx), udiTimeOut := 0);
IF fbTcpWrite.xDone OR fbTcpWrite.xError THEN
xWrite := FALSE;
END_IF
- 创建一个名为 TcpClient 的新 POU ,并按如下进行修改:
声明
VAR CONSTANT
c_tInterval : TIME := T#1S;
c_udiInterval : UDINT := 3 * TIME_TO_UDINT(c_tInterval)/1000;
END_VAR
VAR
fbTcpClient : NBS.TCP_Client;
fbTcpRead : NBS.TCP_Read;
fbTcpWrite : NBS.TCP_Write;
abyTx : ARRAY [0..gvlSetting.gc_wMaxTelegram] OF BYTE;
abyRx : ARRAY [0..gvlSetting.gc_wMaxTelegram] OF BYTE;
fbBlink : BLINK := (TIMELOW := c_tInterval, TIMEHIGH := c_tInterval);
xBlink : BOOL; // Memory of the last state of PLC_PRG.fbBlink
udiVal : UDINT;
pudiVal : POINTER TO BYTE;
iIndex : INT;
xConnect : BOOL;
xRead : BOOL := TRUE;
xMissingAck : BOOL;
udiResult : UDINT;
udiLastAck : UDINT;
udiNow : UDINT;
udiRead : UDINT;
END_VAR
实现
fbTcpClient(xEnable := xConnect, ipAddr := gvlSetting.gc_stIpAddr, uiPort := gvlSetting.gc_uiPort, udiTimeOut := 0);
fbBlink(ENABLE := TRUE);
IF (fbBlink.OUT AND (xBlink <> fbBlink.OUT) ) THEN
udiVal := udiVal + 1;
FOR iIndex := 0 TO gvlSetting.gc_wMaxTelegram DO
abyTx[iIndex] := 0;
END_FOR
// 'WD: ' = Watchdog-Telegram
abyTx[0] := 87;
abyTx[1] := 68;
abyTx[2] := 58;
abyTx[3] := 32;
// Counter
pudiVal := ADR(udiVal);
abyTx[4] := pudiVal^;
pudiVal := pudiVal + 1;
abyTx[5] := pudiVal^;
pudiVal := pudiVal + 1;
abyTx[6] := pudiVal^;
pudiVal := pudiVal + 1;
abyTx[7] := pudiVal^;
fbTcpWrite(xExecute := xConnect,hConnection := fbTcpClient.hConnection, udiTimeOut := 0, szSize := SIZEOF(abyTx), pData := ADR(abyTx));
ELSE
fbTcpWrite(xExecute := FALSE);
END_IF
xBlink := fbBlink.OUT;
fbTcpRead(xEnable := xRead AND xConnect, hConnection := fbTcpClient.hConnection, szSize := SIZEOF(abyRx), pData := ADR(abyRx), szCount => udiRead);
IF fbTcpRead.xReady THEN
IF (fbTcpRead.szCount = (gvlSetting.gc_wMaxTelegram + 1)) THEN
IF ((abyRx[0] = 65) AND (abyRx[1] = 67) AND (abyRx[2] = 75) AND (abyRx[3] = 58) AND (abyRx[4] = 32)) THEN // 'WD: ' = Watchdog-Telegram
udiLastAck := SysTimeRtc.SysTimeRtcGet(udiResult);
END_IF
END_IF
ELSIF fbTcpRead.xError THEN
fbTcpRead(xEnable := FALSE);
END_IF
IF NOT fbTcpClient.xActive AND NOT fbTcpClient.xBusy AND NOT fbTcpClient.xDone THEN
xConnect := TRUE;
ELSIF fbTcpClient.xDone THEN
xConnect := FALSE;
END_IF
udiNow := SysTimeRtc.SysTimeRtcGet(udiResult);
IF (udiNow > (udiLastAck + c_udiInterval)) THEN
xMissingAck := TRUE;
ELSE
xMissingAck := FALSE;
END_IF
- 修改 PLC_PRG 如下:
实现
TcpServer();
TcpClient();
- 将项目加载到控制器并启动它。
