cipio -- Streaming I/O over EtherNet/IP

This module allows reading inputs and setting outputs directly on an I/O Bus Terminal, such as the Beckhoff BK9105 or the Phoenix Contact FL IL 24 BK ETH/IP-PAC, using the Common Industrial Protocol (CIP) encapsulated by EtherNet/IP. Multicast Network support must be enabled on the UNIX system in order to receive streaming inputs.


Open Parameters


cipio <address>[:port] Input=<bytes>[,interval,conc] Output=<bytes>[,interval,conc]

<address> is an IP Address ( or a Hostname (a30c2001) of the EtherNet/IP interface on the network.  PLCIO will attempt to connect to this host using TCP port 44818 or [port], if specified.

The “Input=<bytes>” and “Output=<bytes>” parameters must be specified. These parameters set the size of the streaming input and output packets for each plc_receive( ) and plc_write( ). Packet sizes directly correlate to the number and types of I/O modules available on the device, however, different model devices could allocate more data or pack structures differently for the same amount of I/O than others. Consult the device manufacturer’s documentation for the correct values to be used here.

An optional packet interval may be specified in interval for both input and output. With inputs, the interval determines how often the I/O device will send an input packet to the PLCIO application. The output interval, on the other hand, generally informs the I/O device how often the PLCIO application will send an output packet. The application is free to send updates faster than the output interval.  However, if the remote device does not receive an output packet within 4 times the output interval, the device will close the connection and reset its outputs back to power-on defaults.

Packet intervals are specified in milliseconds. An optional us, ms, or s can be appended to the number to specify microseconds, milliseconds, or seconds, respectively. The default intervals for both input and output is 1 second.

* Note: The I/O device terminates the connection if no output packets are received within 10 seconds of the connection being opened, regardless of the output interval specified.

An optional connection endpoint may be specified in conc for both input and output. This parameter addresses the instance on the device that processes input and output packets, which can vary between device models.  Consult the device manufacturer’s documentation for the correct values to be used here. The default input and output connection endpoints are 101 and 102, respectively.



The default timeout for connecting to an I/O bus Terminal is 5 seconds. This can be changed in the PLCIO Configuration File.


Open Examples

plc_open("cipio Input=6 Output=8");  /* 3 input words, 4 output words */
plc_open("cipio Input=6,2s Output=8");  /* Two seconds between inputs */
plc_open("cipio Input=6,2s Output=8,1s,100");  /* Set output endpoint */



Communications with an I/O device are different than with a PLC, in that each packet received contains the entire input state of the device. This includes all digital and analog inputs and also the state of other on-board modules, such as timers or counters. Similarly, each packet sent must contain the entire output state, which is refreshed to all digital and analog outputs on the device when received.  In order to change the state of a single output, the PLCIO application must also fill in the previous values of all other outputs in the output packet.

The data buffer in an input and output packet is composed of an array of 16-bit words. Although the behavior may differ across device models, each I/O module on the device will generally register one or more 16-bit words in either the input or output buffer.  The application programmer must determine, through experimentation or documentation, the location (offset) and size of each I/O module in the buffer.

All I/O packets are transmitted over UDP with no acknowledgment of receipt. Due to the nature of UDP, packets can sometimes (although rarely) be duplicated, received in reverse order, or lost altogether.  PLCIO makes no decision regarding packet order and forwards all received packets to the application for further analysis. An application wanting to detect lapses in packet ordering can monitor the j_sequence member of the returned PLCSLAVE object (see below). For output packets, however, there is no way to detect when a single packet fails to reach its destination.

If no output packets reach their destination within 4 times the specified output interval, the remote device will close the connection. This state can be detected by the PLCIO application because it will no longer be receiving input packets in the requested packet interval. In this state, the only way to resume connectivity is to close and reopen the I/O device.

To receive input packets, call either the plc_read( ) function with j_op set to 0 and pc_addr set to NULL, or the plc_receive( ) function with j_op set to PLC_STREAM_INPUT.  plc_reply( ) should not be called after a received packet. The PLCSLAVE object returned from plc_receive( ) will have its j_type member set to PLC_STREAM_INPUT and its j_sequence member filled in from the EtherNet/IP layer.

Send an output packet by calling the plc_write( ) function with j_op set to 0 and pc_addr set to NULL. Because no acknowledgment is emitted upon receipt, the j_timeout field is not applicable.

Multicast Networking

I/O devices generally use Multicast Networking to transmit input packets. For PLCIO to receive streaming input, the UNIX system must be configured to subscribe to and receive Multicast packets.

On systems with multiple Ethernet interfaces, Multicast packets by default are only received on the interface corresponding to the default gateway. If a different interface is desired for communication, then a specific route must be added for Multicast: network with subnet mask Here is an example on how to do this in Linux for interface “eth1” (note that this is temporary until the system is rebooted—consult your system documentation on how to make this permanent):

route add –net netmask dev eth1

Programming Examples

short ai_data[6]={0, 0, 0, 0x3fff, 0, 0x0001};
j_result=plc_write(ptr, 0, NULL, ai_data, 12, 0, PLC_CVT_WORD);


short ai_buffer[6];
j_result=plc_read(ptr, 0, NULL, ai_buffer, 12, 3000, PLC_CVT_WORD);


static int j_last_sequence;
short ai_buffer[6];

j_result=plc_receive(ptr, PLC_STREAM_INPUT, &slave, ai_buffer, 12, 3000);

/* If successful, convert each 16-bit word to host byte-order */
if(j_result != -1)
plc_conv(ptr, PLC_TOCPU, ai_buffer, slave.j_length, PLC_CVT_WORD);

/* Print a warning if we had data loss */
if(slave.j_sequence != 0 && slave.j_sequence != j_last_sequence+1)
fprintf(stderr, "Warning: Wrong packet order in the input stream.\n");

/* Remember current sequence number */
j_last_sequence = slave.j_sequence;


* Warning: If the application exits without calling plc_close( ), the remote I/O device continues to wait for packets until the output interval timeout elapses.  The application cannot reconnect during this time.


Additional Errors



A communications error occurred while opening the CIP command to the PLC.  The error-status byte is stored in plc_ptr->aj_errorval[0].  The 2-byte routing-error code is stored in plc_ptr->aj_errorval[1].



During plc_open( ), the remote I/O device failed to provide a valid IP Address for sending output packets or a Multicast Address for receiving input packets.

PLCE_CIP_RPI_EXCEEDED 204 Attempted to send an output packet after 4 times the output interval has elapsed.