libmodbus
libmodbus copied to clipboard
Implementing server getting 'ERROR Connection reset by peer: read'
Dear libmodbus,
I have been working on a Moxa UC-8100A-ME. I’m using the linux side of this box. ‘Linux version 4.4.0-cip-uc8100a-me (root@d7b36943a46d) (gcc version 6.3.0 20170516 (Debian 6.3.0-18) ) #12 Tue Dec 11 14:53:48 CST 2018’ libmodbus-3.0.6
I’m working on a c program that will act as a serve. My problem is when a master is connected and cycles power either my code is hanging or I get:
Waiting for a indication... <00><00><00><00><00><06><FF><03><00><00><00><02> [00][00][00][00][00][07][FF][03][04][00][00][00][00] Waiting for a indication... <00><00><00><00><00><06><FF><03><00><00><00><02> [00][00][00][00][00][07][FF][03][04][00][00][00][00] Waiting for a indication... ERROR Connection reset by peer: read 08:09:55 TRACE prnt_drive_comm.c:182: Quit the slave loop at 'modbus_receive' error: Connection reset by peer 08:09:55 TRACE prnt_drive_comm.c:217: Out of the slave loop 08:09:55 TRACE prnt_drive_comm.c:221: closing the modbus slave socket.
At that point my only choice is to restart the c program. and the master reconnects. How can I handle a master shutting down communication gracefully? and being able to re-establish comms with the master?
I have used your library as a master many times but this is my first round in using it as a server. Any help is of a great value to me.
Here is my code:
/*
- slave.c - a MODBUS slave
-
sudo gcc -Wall -lmodbus -o slave slave.c
*/
#include <stdio.h> #include <unistd.h> #include <string.h> //#ifndef _MSC_VER //#endif #include <stdlib.h> #include <errno.h> //#include "unit-test.h" #include <modbus/modbus.h>
const int MAX_NB_COILS = 0; const int MAX_NB_INPUTS = 0; const int MAX_NB_HOLDING_REGISTERS = 101; const int MAX_NB_INPUT_REGISTERS = 0;
int main(void){ int i; int s = -1; modbus_t *ctx; modbus_mapping_t *mb_mapping;
uint8_t *query;
uint16_t WellOptics_Request = 0; //this is the register monitored for request from well optics
//int header_length;
int rc;
//ctx = modbus_new_tcp("192.168.1.5", 502);
//ctx = modbus_new_tcp_pi("127.0.0.1", "502");
ctx = modbus_new_tcp_pi("::0", "502");
query = malloc(MODBUS_TCP_MAX_ADU_LENGTH); //modbus-tcp.h ; MODBUS_TCP_MAX_ADU_LENGTH = 260
//header_length = modbus_get_header_length(ctx);
modbus_set_debug(ctx, 0);
if (ctx == NULL) {
fprintf(stderr, "Unable to allocate libmodbus context\n");
return -1;
}
//-------------------
//MAPPING
// Allocates 4 arrays to store bits, input bits, registers and inputs
// registers. The pointers are stored in modbus_mapping structure.
//
// The modbus_mapping_new() function shall return the new allocated structure if
// successful. Otherwise it shall return NULL and set errno to ENOMEM. */
//-------------------
mb_mapping = modbus_mapping_new(MAX_NB_COILS, MAX_NB_INPUTS, MAX_NB_HOLDING_REGISTERS, MAX_NB_INPUT_REGISTERS); //modbus.h ; $
if (mb_mapping == NULL) {
fprintf(stderr, "Failed to allocate the mapping: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
//-------------------
//Must initialize regs here
//-------------------
//tab_bits
printf("Initializing tab_bits MAX_NB_COILS = %d \n", MAX_NB_COILS);
for (int i = 0; i < MAX_NB_COILS; i++){
//printf("%d\n", i);
mb_mapping->tab_bits[i] = 0;
}
//tab_input_bits
printf("Initializing tab_bits MAX_NB_INPUTS = %d \n", MAX_NB_INPUTS);
for (int i = 0; i < MAX_NB_INPUTS; i++){
//printf("%d\n", i);
mb_mapping->tab_input_bits[i] = 0;
}
//tab_registers
printf("Initializing tab_bits MAX_NB_HOLDING_REGISTERS = %d \n", MAX_NB_HOLDING_REGISTERS);
for (int i = 0; i < MAX_NB_HOLDING_REGISTERS; i++){
//printf("%d\n", i);
mb_mapping->tab_registers[i] = 0;
}
//tab_input_registers
printf("Initializing tab_bits MAX_NB_INPUT_REGISTERS = %d \n", MAX_NB_INPUT_REGISTERS);
for (int i = 0; i < MAX_NB_INPUT_REGISTERS; i++){
//printf("%d\n", i);
mb_mapping->tab_input_registers[i] = 0;
}
s = modbus_tcp_pi_listen(ctx, 1);
modbus_tcp_pi_accept(ctx, &s);
for (;;) {
do {
rc = modbus_receive(ctx, query);
/* Filtered queries return 0 */
} while (rc == 0);
//rc = modbus_receive(ctx, query);
/* The connection is not closed on errors which require on reply such as
bad CRC in RTU. */
if (rc == -1 && errno != EMBBADCRC){
/* Quit */
break;
}
//printing the values of the registers after every receive
printf("SLAVE: tab_registers[] =\t");
for (i = 0; i != 11; i++){ // looks like 1..n index
printf("%d ", mb_mapping->tab_registers[i]);
}
printf("\n");
if (mb_mapping->tab_registers[0] != WellOptics_Request){
printf("Reg 40001 changed value to %d\n ", mb_mapping->tab_registers[0]);
}
//calling the reply command
rc = modbus_reply(ctx, query, rc, mb_mapping);
if (rc == -1){
/* Connection closed by the client or error */
break;
}
}
printf("Quit the loop: %s\n", modbus_strerror(errno));
if (s != -1){
close(s);
}
modbus_mapping_free(mb_mapping);
free(query);
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
I just tried this, and it worked for me:
Use goto in the
if (rc == -1 && errno != EMBBADCRC){ /* Quit */ goto start; } Add this start label before modbus_tcp_pi_accept(ctx, &s);
start: modbus_tcp_pi_accept(ctx, &s);