stephane / libmodbus

A Modbus library for Linux, Mac OS, FreeBSD and Windows
http://libmodbus.org
GNU Lesser General Public License v2.1
3.3k stars 1.71k forks source link

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

Open oazradSPOC opened 3 years ago

oazradSPOC commented 3 years ago

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><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><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 #include #include //#ifndef _MSC_VER //#endif #include #include //#include "unit-test.h" #include 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; }
suresh-dersec commented 10 months ago

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

Chadlucc commented 2 months ago

i meet it too, is it a bug?