libmodbus icon indicating copy to clipboard operation
libmodbus copied to clipboard

Implementing server getting 'ERROR Connection reset by peer: read'

Open oazradSPOC opened this issue 4 years ago • 2 comments

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;

}

oazradSPOC avatar Nov 13 '20 01:11 oazradSPOC

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);

suresh-dersec avatar Aug 19 '23 13:08 suresh-dersec