Commit c7a6ffb357dd0f31e0ab61f4462af2ee84f355db
1 parent
fe8d9de6
New slave able to manage many connections on uniprocessor architecture
- new functions modbus_slave_init_listen_tcp, modbus_slave_accept_tcp, modbus_slave_slave_receive. - removed printf in modbus.c: 'Connection closed' - new slave test, bandwith-slave-many-up - updated build scripts - updated MIGRATION document file
Showing
10 changed files
with
277 additions
and
84 deletions
MIGRATION
| 1 | +============================= | |
| 2 | +Migration from the 2.0 series | |
| 3 | +============================= | |
| 4 | + | |
| 5 | +modbus_init_listen_tcp() has been renamed to modbus_slave_listen_tcp() and | |
| 6 | +requires a new argument, the maximal number of connections: | |
| 7 | + | |
| 8 | +int modbus_slave_init_tcp(modbus_param_t *mb_param, int nb_connection); | |
| 9 | + | |
| 10 | + | |
| 11 | +New function modbus_slave_accept_tcp() to etablish a new connection (previously | |
| 12 | +in modbus_init_listen_tcp()): | |
| 13 | + | |
| 14 | +int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket); | |
| 15 | + | |
| 16 | + | |
| 17 | +modbus_listen() has been renamed to modbus_slave_receive() and requires a new | |
| 18 | +argument, the socket file descriptor to listen on. If the sockfd is -1, the | |
| 19 | +internal fd of modbus_param_t is used: | |
| 20 | + | |
| 21 | +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, | |
| 22 | + uint8_t *query, int *query_length); | |
| 23 | + | |
| 24 | + | |
| 1 | 25 | =================================== |
| 2 | 26 | Migration notes from the 1.2 series |
| 3 | 27 | =================================== | ... | ... |
modbus/modbus.c
| ... | ... | @@ -498,7 +498,7 @@ static int receive_msg(modbus_param_t *mb_param, |
| 498 | 498 | tv.tv_usec = TIME_OUT_BEGIN_OF_TRAME; |
| 499 | 499 | state = COMPLETE; |
| 500 | 500 | } |
| 501 | - | |
| 501 | + | |
| 502 | 502 | length_to_read = msg_length_computed; |
| 503 | 503 | |
| 504 | 504 | select_ret = 0; |
| ... | ... | @@ -515,7 +515,6 @@ static int receive_msg(modbus_param_t *mb_param, |
| 515 | 515 | read_ret = recv(mb_param->fd, p_msg, length_to_read, 0); |
| 516 | 516 | |
| 517 | 517 | if (read_ret == 0) { |
| 518 | - printf("Connection closed\n"); | |
| 519 | 518 | return CONNECTION_CLOSED; |
| 520 | 519 | } else if (read_ret < 0) { |
| 521 | 520 | /* The only negative possible value is -1 */ |
| ... | ... | @@ -524,7 +523,7 @@ static int receive_msg(modbus_param_t *mb_param, |
| 524 | 523 | return PORT_SOCKET_FAILURE; |
| 525 | 524 | } |
| 526 | 525 | |
| 527 | - /* Sums bytes received */ | |
| 526 | + /* Sums bytes received */ | |
| 528 | 527 | (*p_msg_length) += read_ret; |
| 529 | 528 | |
| 530 | 529 | /* Display the hex code of each character received */ |
| ... | ... | @@ -590,6 +589,28 @@ static int receive_msg(modbus_param_t *mb_param, |
| 590 | 589 | return 0; |
| 591 | 590 | } |
| 592 | 591 | |
| 592 | +/* Listens for any query from a modbus master in TCP, requires the socket file | |
| 593 | + descriptor etablished with the master device in argument or -1 to use the | |
| 594 | + internal one of modbus_param_t. | |
| 595 | + | |
| 596 | + Returns: | |
| 597 | + - 0 if OK, or a negative error number if the request fails | |
| 598 | + - query, message received | |
| 599 | + - query_length, length in bytes of the message */ | |
| 600 | +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, | |
| 601 | + uint8_t *query, int *query_length) | |
| 602 | +{ | |
| 603 | + int ret; | |
| 604 | + | |
| 605 | + if (sockfd != -1) { | |
| 606 | + mb_param->fd = sockfd; | |
| 607 | + } | |
| 608 | + | |
| 609 | + /* The length of the query to receive isn't known. */ | |
| 610 | + ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length); | |
| 611 | + | |
| 612 | + return ret; | |
| 613 | +} | |
| 593 | 614 | |
| 594 | 615 | /* Receives the response and checks values (and checksum in RTU). |
| 595 | 616 | |
| ... | ... | @@ -757,6 +778,7 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft, |
| 757 | 778 | |
| 758 | 779 | /* Manages the received query. |
| 759 | 780 | Analyses the query and constructs a response. |
| 781 | + | |
| 760 | 782 | If an error occurs, this function construct the response |
| 761 | 783 | accordingly. |
| 762 | 784 | */ |
| ... | ... | @@ -948,21 +970,6 @@ void modbus_manage_query(modbus_param_t *mb_param, const uint8_t *query, |
| 948 | 970 | modbus_send(mb_param, response, resp_length); |
| 949 | 971 | } |
| 950 | 972 | |
| 951 | -/* Listens any message on a socket or file descriptor. | |
| 952 | - Returns: | |
| 953 | - - 0 if OK, or a negative error number if the request fails | |
| 954 | - - query, message received | |
| 955 | - - query_length, length in bytes of the message */ | |
| 956 | -int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_length) | |
| 957 | -{ | |
| 958 | - int ret; | |
| 959 | - | |
| 960 | - /* The length of the query to receive isn't known. */ | |
| 961 | - ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length); | |
| 962 | - | |
| 963 | - return ret; | |
| 964 | -} | |
| 965 | - | |
| 966 | 973 | /* Reads IO status */ |
| 967 | 974 | static int read_io_status(modbus_param_t *mb_param, int slave, int function, |
| 968 | 975 | int start_addr, int nb, uint8_t *data_dest) |
| ... | ... | @@ -1628,10 +1635,6 @@ static int modbus_connect_tcp(modbus_param_t *mb_param) |
| 1628 | 1635 | int option; |
| 1629 | 1636 | struct sockaddr_in addr; |
| 1630 | 1637 | |
| 1631 | - addr.sin_family = AF_INET; | |
| 1632 | - addr.sin_port = htons(mb_param->port); | |
| 1633 | - addr.sin_addr.s_addr = inet_addr(mb_param->ip); | |
| 1634 | - | |
| 1635 | 1638 | mb_param->fd = socket(AF_INET, SOCK_STREAM, 0); |
| 1636 | 1639 | if (mb_param->fd < 0) { |
| 1637 | 1640 | return mb_param->fd; |
| ... | ... | @@ -1661,7 +1664,10 @@ static int modbus_connect_tcp(modbus_param_t *mb_param) |
| 1661 | 1664 | if (mb_param->debug) { |
| 1662 | 1665 | printf("Connecting to %s\n", mb_param->ip); |
| 1663 | 1666 | } |
| 1664 | - | |
| 1667 | + | |
| 1668 | + addr.sin_family = AF_INET; | |
| 1669 | + addr.sin_port = htons(mb_param->port); | |
| 1670 | + addr.sin_addr.s_addr = inet_addr(mb_param->ip); | |
| 1665 | 1671 | ret = connect(mb_param->fd, (struct sockaddr *)&addr, |
| 1666 | 1672 | sizeof(struct sockaddr_in)); |
| 1667 | 1673 | if (ret < 0) { |
| ... | ... | @@ -1784,60 +1790,64 @@ void modbus_mapping_free(modbus_mapping_t *mb_mapping) |
| 1784 | 1790 | free(mb_mapping->tab_input_registers); |
| 1785 | 1791 | } |
| 1786 | 1792 | |
| 1787 | -/* Listens for any query from a modbus master in TCP */ | |
| 1788 | -int modbus_init_listen_tcp(modbus_param_t *mb_param) | |
| 1793 | +/* Listens for any query from one or many modbus masters in TCP */ | |
| 1794 | +int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection) | |
| 1789 | 1795 | { |
| 1790 | - int ret; | |
| 1791 | 1796 | int new_socket; |
| 1797 | + int yes; | |
| 1792 | 1798 | struct sockaddr_in addr; |
| 1793 | - socklen_t addrlen; | |
| 1794 | - | |
| 1795 | - addr.sin_family = AF_INET; | |
| 1796 | - /* If the modbus port is < to 1024, we need the setuid root. */ | |
| 1797 | - addr.sin_port = htons(mb_param->port); | |
| 1798 | - addr.sin_addr.s_addr = INADDR_ANY; | |
| 1799 | - memset(&(addr.sin_zero), '\0', 8); | |
| 1800 | 1799 | |
| 1801 | 1800 | new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
| 1802 | 1801 | if (new_socket < 0) { |
| 1803 | 1802 | perror("socket"); |
| 1804 | - exit(1); | |
| 1805 | - } else { | |
| 1806 | - printf("Socket OK\n"); | |
| 1803 | + return -1; | |
| 1807 | 1804 | } |
| 1808 | 1805 | |
| 1809 | - ret = bind(new_socket, (struct sockaddr *)&addr, | |
| 1810 | - sizeof(struct sockaddr_in)); | |
| 1811 | - if (ret < 0) { | |
| 1806 | + yes = 1; | |
| 1807 | + if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR, | |
| 1808 | + (char *) &yes, sizeof(yes)) < 0) { | |
| 1809 | + perror("setsockopt"); | |
| 1810 | + close(new_socket); | |
| 1811 | + return -1; | |
| 1812 | + } | |
| 1813 | + | |
| 1814 | + memset(&addr, 0, sizeof(addr)); | |
| 1815 | + addr.sin_family = AF_INET; | |
| 1816 | + /* If the modbus port is < to 1024, we need the setuid root. */ | |
| 1817 | + addr.sin_port = htons(mb_param->port); | |
| 1818 | + addr.sin_addr.s_addr = INADDR_ANY; | |
| 1819 | + if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { | |
| 1812 | 1820 | perror("bind"); |
| 1813 | 1821 | close(new_socket); |
| 1814 | - exit(1); | |
| 1815 | - } else { | |
| 1816 | - printf("Bind OK\n"); | |
| 1822 | + return -1; | |
| 1817 | 1823 | } |
| 1818 | 1824 | |
| 1819 | - ret = listen(new_socket, 1); | |
| 1820 | - if (ret != 0) { | |
| 1825 | + if (listen(new_socket, nb_connection) < 0) { | |
| 1821 | 1826 | perror("listen"); |
| 1822 | 1827 | close(new_socket); |
| 1823 | - exit(1); | |
| 1824 | - } else { | |
| 1825 | - printf("Listen OK\n"); | |
| 1828 | + return -1; | |
| 1826 | 1829 | } |
| 1827 | 1830 | |
| 1831 | + return new_socket; | |
| 1832 | +} | |
| 1833 | + | |
| 1834 | +int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket) | |
| 1835 | +{ | |
| 1836 | + struct sockaddr_in addr; | |
| 1837 | + socklen_t addrlen; | |
| 1838 | + | |
| 1828 | 1839 | addrlen = sizeof(struct sockaddr_in); |
| 1829 | - mb_param->fd = accept(new_socket, (struct sockaddr *)&addr, &addrlen); | |
| 1840 | + mb_param->fd = accept(*socket, (struct sockaddr *)&addr, &addrlen); | |
| 1830 | 1841 | if (mb_param->fd < 0) { |
| 1831 | 1842 | perror("accept"); |
| 1832 | - close(new_socket); | |
| 1833 | - new_socket = 0; | |
| 1834 | - exit(1); | |
| 1843 | + close(*socket); | |
| 1844 | + *socket = 0; | |
| 1835 | 1845 | } else { |
| 1836 | 1846 | printf("The client %s is connected\n", |
| 1837 | 1847 | inet_ntoa(addr.sin_addr)); |
| 1838 | 1848 | } |
| 1839 | 1849 | |
| 1840 | - return new_socket; | |
| 1850 | + return mb_param->fd; | |
| 1841 | 1851 | } |
| 1842 | 1852 | |
| 1843 | 1853 | /** Utils **/ | ... | ... |
modbus/modbus.h
| ... | ... | @@ -279,12 +279,25 @@ int modbus_mapping_new(modbus_mapping_t *mb_mapping, |
| 279 | 279 | /* Frees the 4 arrays */ |
| 280 | 280 | void modbus_mapping_free(modbus_mapping_t *mb_mapping); |
| 281 | 281 | |
| 282 | -/* Initializes the modbus_param_t structure for a TCP slave (server) */ | |
| 283 | -int modbus_init_listen_tcp(modbus_param_t *mb_param); | |
| 282 | +/* Listens for any query from one or many modbus masters in TCP. | |
| 284 | 283 | |
| 285 | -/* Listens for any query from a modbus master in TCP | |
| 286 | - Not tested in RTU communication. */ | |
| 287 | -int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_length); | |
| 284 | + Returns: socket | |
| 285 | + */ | |
| 286 | +int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection); | |
| 287 | + | |
| 288 | +/* Waits for a connection */ | |
| 289 | +int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket); | |
| 290 | + | |
| 291 | +/* Listens for any query from a modbus master in TCP, requires the socket file | |
| 292 | + descriptor etablished with the master device in argument. | |
| 293 | + | |
| 294 | + Returns: | |
| 295 | + - 0 if OK, or a negative error number if the request fails | |
| 296 | + - query, message received | |
| 297 | + - query_length, length in bytes of the message | |
| 298 | +*/ | |
| 299 | +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, | |
| 300 | + uint8_t *query, int *query_length); | |
| 288 | 301 | |
| 289 | 302 | /* Manages the received query. |
| 290 | 303 | Analyses the query and constructs a response. | ... | ... |
tests/Makefile.am
| ... | ... | @@ -5,8 +5,9 @@ noinst_PROGRAMS = \ |
| 5 | 5 | random-test-master \ |
| 6 | 6 | unit-test-slave \ |
| 7 | 7 | unit-test-master \ |
| 8 | - bench-bandwidth-slave \ | |
| 9 | - bench-bandwidth-master | |
| 8 | + bandwidth-slave-one \ | |
| 9 | + bandwidth-slave-many-up \ | |
| 10 | + bandwidth-master | |
| 10 | 11 | |
| 11 | 12 | common_ldflags = \ |
| 12 | 13 | $(top_builddir)/modbus/libmodbus.la |
| ... | ... | @@ -23,11 +24,14 @@ unit_test_slave_LDADD = $(common_ldflags) |
| 23 | 24 | unit_test_master_SOURCES = unit-test-master.c unit-test.h |
| 24 | 25 | unit_test_master_LDADD = $(common_ldflags) |
| 25 | 26 | |
| 26 | -bench_bandwidth_slave_SOURCES = bench-bandwidth-slave.c | |
| 27 | -bench_bandwidth_slave_LDADD = $(common_ldflags) | |
| 27 | +bandwidth_slave_one_SOURCES = bandwidth-slave-one.c | |
| 28 | +bandwidth_slave_one_LDADD = $(common_ldflags) | |
| 28 | 29 | |
| 29 | -bench_bandwidth_master_SOURCES = bench-bandwidth-master.c | |
| 30 | -bench_bandwidth_master_LDADD = $(common_ldflags) | |
| 30 | +bandwidth_slave_many_up_SOURCES = bandwidth-slave-many-up.c | |
| 31 | +bandwidth_slave_many_up_LDADD = $(common_ldflags) | |
| 32 | + | |
| 33 | +bandwidth_master_SOURCES = bandwidth-master.c | |
| 34 | +bandwidth_master_LDADD = $(common_ldflags) | |
| 31 | 35 | |
| 32 | 36 | INCLUDES = -I$(top_srcdir) |
| 33 | 37 | CLEANFILES = *~ | ... | ... |
tests/bench-bandwidth-master.c renamed to tests/bandwidth-master.c
| ... | ... | @@ -33,7 +33,7 @@ uint32_t gettime(void) |
| 33 | 33 | { |
| 34 | 34 | struct timeval tv; |
| 35 | 35 | gettimeofday (&tv, NULL); |
| 36 | - | |
| 36 | + | |
| 37 | 37 | return (uint32_t) tv.tv_sec * G_USEC_PER_SEC + tv.tv_usec; |
| 38 | 38 | } |
| 39 | 39 | |
| ... | ... | @@ -61,7 +61,7 @@ int main(void) |
| 61 | 61 | /* Allocate and initialize the memory to store the status */ |
| 62 | 62 | tab_rp_status = (uint8_t *) malloc(MAX_STATUS * sizeof(uint8_t)); |
| 63 | 63 | memset(tab_rp_status, 0, MAX_STATUS * sizeof(uint8_t)); |
| 64 | - | |
| 64 | + | |
| 65 | 65 | /* Allocate and initialize the memory to store the registers */ |
| 66 | 66 | tab_rp_registers = (uint16_t *) malloc(MAX_REGISTERS * sizeof(uint16_t)); |
| 67 | 67 | memset(tab_rp_registers, 0, MAX_REGISTERS * sizeof(uint16_t)); |
| ... | ... | @@ -78,7 +78,7 @@ int main(void) |
| 78 | 78 | |
| 79 | 79 | rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start); |
| 80 | 80 | printf("Transfert rate in points/seconds:\n"); |
| 81 | - printf("* %'d points/s\n", rate); | |
| 81 | + printf("* %'d points/s\n", rate); | |
| 82 | 82 | printf("\n"); |
| 83 | 83 | |
| 84 | 84 | bytes = NB_LOOPS * (nb_points / 8) + ((nb_points % 8) ? 1 : 0); |
| ... | ... | @@ -88,7 +88,7 @@ int main(void) |
| 88 | 88 | printf("* %.3f ms for %d bytes\n", elapsed, bytes); |
| 89 | 89 | printf("* %'d KiB/s\n", rate); |
| 90 | 90 | printf("\n"); |
| 91 | - | |
| 91 | + | |
| 92 | 92 | /* TCP: Query and reponse header and values */ |
| 93 | 93 | bytes = 12 + 9 + (nb_points / 8) + ((nb_points % 8) ? 1 : 0); |
| 94 | 94 | printf("Values and TCP Modbus overhead:\n"); |
| ... | ... | @@ -111,7 +111,7 @@ int main(void) |
| 111 | 111 | |
| 112 | 112 | rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start); |
| 113 | 113 | printf("Transfert rate in points/seconds:\n"); |
| 114 | - printf("* %'d registers/s\n", rate); | |
| 114 | + printf("* %'d registers/s\n", rate); | |
| 115 | 115 | printf("\n"); |
| 116 | 116 | |
| 117 | 117 | bytes = NB_LOOPS * nb_points * sizeof(uint16_t); |
| ... | ... | @@ -121,7 +121,7 @@ int main(void) |
| 121 | 121 | printf("* %.3f ms for %d bytes\n", elapsed, bytes); |
| 122 | 122 | printf("* %'d KiB/s\n", rate); |
| 123 | 123 | printf("\n"); |
| 124 | - | |
| 124 | + | |
| 125 | 125 | /* TCP:Query and reponse header and values */ |
| 126 | 126 | bytes = 12 + 9 + (nb_points * sizeof(uint16_t)); |
| 127 | 127 | printf("Values and TCP Modbus overhead:\n"); |
| ... | ... | @@ -133,11 +133,11 @@ int main(void) |
| 133 | 133 | printf("\n"); |
| 134 | 134 | |
| 135 | 135 | /* Free the memory */ |
| 136 | - free(tab_rp_status); | |
| 136 | + free(tab_rp_status); | |
| 137 | 137 | free(tab_rp_registers); |
| 138 | 138 | |
| 139 | 139 | /* Close the connection */ |
| 140 | 140 | modbus_close(&mb_param); |
| 141 | - | |
| 141 | + | |
| 142 | 142 | return 0; |
| 143 | 143 | } | ... | ... |
tests/bandwidth-slave-many-up.c
0 → 100644
| 1 | +/* | |
| 2 | + * Copyright © 2009 Stéphane Raimbault <stephane.raimbault@gmail.com> | |
| 3 | + * | |
| 4 | + * This program is free software: you can redistribute it and/or modify | |
| 5 | + * it under the terms of the GNU General Public License as published by | |
| 6 | + * the Free Software Foundation; either version 3 of the License, or | |
| 7 | + * (at your option) any later version. | |
| 8 | + * | |
| 9 | + * This program is distributed in the hope that it will be useful, | |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + * GNU General Public License for more details. | |
| 13 | + * | |
| 14 | + * You should have received a copy of the GNU General Public License | |
| 15 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | + */ | |
| 17 | + | |
| 18 | +#include <stdio.h> | |
| 19 | +#include <unistd.h> | |
| 20 | +#include <string.h> | |
| 21 | +#include <stdlib.h> | |
| 22 | +#include <errno.h> | |
| 23 | +#include <signal.h> | |
| 24 | + | |
| 25 | +#include <modbus/modbus.h> | |
| 26 | + | |
| 27 | +#define NB_CONNECTION 5 | |
| 28 | +int slave_socket; | |
| 29 | +modbus_mapping_t mb_mapping; | |
| 30 | + | |
| 31 | +static void close_sigint(int dummy) | |
| 32 | +{ | |
| 33 | + shutdown(slave_socket, SHUT_RDWR); | |
| 34 | + close(slave_socket); | |
| 35 | + modbus_mapping_free(&mb_mapping); | |
| 36 | + | |
| 37 | + exit(dummy); | |
| 38 | +} | |
| 39 | + | |
| 40 | +int main(void) | |
| 41 | +{ | |
| 42 | + int master_socket; | |
| 43 | + modbus_param_t mb_param; | |
| 44 | + int ret; | |
| 45 | + fd_set refset; | |
| 46 | + fd_set rdset; | |
| 47 | + | |
| 48 | + /* Maximum file descriptor number */ | |
| 49 | + int fdmax; | |
| 50 | + | |
| 51 | + modbus_init_tcp(&mb_param, "127.0.0.1", 1502); | |
| 52 | + | |
| 53 | + ret = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0); | |
| 54 | + if (ret == FALSE) { | |
| 55 | + printf("Memory allocation failure\n"); | |
| 56 | + exit(1); | |
| 57 | + } | |
| 58 | + | |
| 59 | + slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION); | |
| 60 | + | |
| 61 | + signal(SIGINT, close_sigint); | |
| 62 | + | |
| 63 | + /* Clear the reference set of socket */ | |
| 64 | + FD_ZERO(&refset); | |
| 65 | + /* Add the slave socket */ | |
| 66 | + FD_SET(slave_socket, &refset); | |
| 67 | + | |
| 68 | + /* Keep track of the max file descriptor */ | |
| 69 | + fdmax = slave_socket; | |
| 70 | + | |
| 71 | + for (;;) { | |
| 72 | + rdset = refset; | |
| 73 | + if (select(fdmax+1, &rdset, NULL, NULL, NULL) == -1) { | |
| 74 | + perror("Slave select() failure."); | |
| 75 | + close_sigint(1); | |
| 76 | + } | |
| 77 | + | |
| 78 | + /* Run through the existing connections looking for data to be | |
| 79 | + * read */ | |
| 80 | + for (master_socket = 0; master_socket <= fdmax; master_socket++) { | |
| 81 | + | |
| 82 | + if (FD_ISSET(master_socket, &rdset)) { | |
| 83 | + if (master_socket == slave_socket) { | |
| 84 | + /* A client is asking a new connection */ | |
| 85 | + socklen_t addrlen; | |
| 86 | + struct sockaddr_in clientaddr; | |
| 87 | + int newfd; | |
| 88 | + | |
| 89 | + /* Handle new connections */ | |
| 90 | + addrlen = sizeof(clientaddr); | |
| 91 | + memset(&clientaddr, 0, sizeof(clientaddr)); | |
| 92 | + newfd = accept(slave_socket, (struct sockaddr *)&clientaddr, &addrlen); | |
| 93 | + if (newfd == -1) { | |
| 94 | + perror("Server accept() error"); | |
| 95 | + } else { | |
| 96 | + FD_SET(newfd, &refset); | |
| 97 | + | |
| 98 | + if (newfd > fdmax) { | |
| 99 | + /* Keep track of the maximum */ | |
| 100 | + fdmax = newfd; | |
| 101 | + } | |
| 102 | + printf("New connection from %s:%d on socket %d\n", | |
| 103 | + inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port, newfd); | |
| 104 | + } | |
| 105 | + } else { | |
| 106 | + /* An already connected master has sent a new query */ | |
| 107 | + uint8_t query[MAX_MESSAGE_LENGTH]; | |
| 108 | + int query_size; | |
| 109 | + | |
| 110 | + ret = modbus_slave_receive(&mb_param, master_socket, query, &query_size); | |
| 111 | + if (ret == 0) { | |
| 112 | + modbus_manage_query(&mb_param, query, query_size, &mb_mapping); | |
| 113 | + } else { | |
| 114 | + /* Connection closed by the client, end of server */ | |
| 115 | + printf("Connection closed on socket %d\n", master_socket); | |
| 116 | + shutdown(master_socket, SHUT_RDWR); | |
| 117 | + close(master_socket); | |
| 118 | + | |
| 119 | + /* Remove from reference set */ | |
| 120 | + FD_CLR(master_socket, &refset); | |
| 121 | + | |
| 122 | + if (master_socket == fdmax) { | |
| 123 | + fdmax--; | |
| 124 | + } | |
| 125 | + } | |
| 126 | + } | |
| 127 | + } | |
| 128 | + } | |
| 129 | + } | |
| 130 | + | |
| 131 | + return 0; | |
| 132 | +} | ... | ... |
tests/bench-bandwidth-slave.c renamed to tests/bandwidth-slave-one.c
| ... | ... | @@ -37,13 +37,14 @@ int main(void) |
| 37 | 37 | exit(1); |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | - socket = modbus_init_listen_tcp(&mb_param); | |
| 41 | - | |
| 40 | + socket = modbus_slave_listen_tcp(&mb_param, 1); | |
| 41 | + modbus_slave_accept_tcp(&mb_param, &socket); | |
| 42 | + | |
| 42 | 43 | while (1) { |
| 43 | 44 | uint8_t query[MAX_MESSAGE_LENGTH]; |
| 44 | 45 | int query_size; |
| 45 | 46 | |
| 46 | - ret = modbus_listen(&mb_param, query, &query_size); | |
| 47 | + ret = modbus_slave_receive(&mb_param, -1, query, &query_size); | |
| 47 | 48 | if (ret == 0) { |
| 48 | 49 | modbus_manage_query(&mb_param, query, query_size, &mb_mapping); |
| 49 | 50 | } else if (ret == CONNECTION_CLOSED) { | ... | ... |
tests/random-test-slave.c
| ... | ... | @@ -37,13 +37,14 @@ int main(void) |
| 37 | 37 | exit(1); |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | - socket = modbus_init_listen_tcp(&mb_param); | |
| 41 | - | |
| 40 | + socket = modbus_slave_listen_tcp(&mb_param, 1); | |
| 41 | + modbus_slave_accept_tcp(&mb_param, &socket); | |
| 42 | + | |
| 42 | 43 | while (1) { |
| 43 | 44 | uint8_t query[MAX_MESSAGE_LENGTH]; |
| 44 | 45 | int query_size; |
| 45 | 46 | |
| 46 | - ret = modbus_listen(&mb_param, query, &query_size); | |
| 47 | + ret = modbus_slave_receive(&mb_param, -1, query, &query_size); | |
| 47 | 48 | if (ret == 0) { |
| 48 | 49 | modbus_manage_query(&mb_param, query, query_size, &mb_mapping); |
| 49 | 50 | } else if (ret == CONNECTION_CLOSED) { | ... | ... |
tests/unit-test-slave.c
| ... | ... | @@ -59,13 +59,14 @@ int main(void) |
| 59 | 59 | UT_INPUT_REGISTERS_TAB[i];; |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | - socket = modbus_init_listen_tcp(&mb_param); | |
| 63 | - | |
| 62 | + socket = modbus_slave_listen_tcp(&mb_param, 1); | |
| 63 | + modbus_slave_accept_tcp(&mb_param, &socket); | |
| 64 | + | |
| 64 | 65 | while (1) { |
| 65 | 66 | uint8_t query[MAX_MESSAGE_LENGTH]; |
| 66 | 67 | int query_size; |
| 67 | 68 | |
| 68 | - ret = modbus_listen(&mb_param, query, &query_size); | |
| 69 | + ret = modbus_slave_receive(&mb_param, -1, query, &query_size); | |
| 69 | 70 | if (ret == 0) { |
| 70 | 71 | if (((query[HEADER_LENGTH_TCP + 4] << 8) + query[HEADER_LENGTH_TCP + 5]) |
| 71 | 72 | == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) { | ... | ... |
tests/wscript
| ... | ... | @@ -28,15 +28,22 @@ def build(bld): |
| 28 | 28 | obj.inst_var = 0 |
| 29 | 29 | |
| 30 | 30 | obj = bld.create_obj('cc', 'program') |
| 31 | - obj.source = 'bench-bandwidth-slave.c' | |
| 31 | + obj.source = 'bandwidth-slave-one.c' | |
| 32 | 32 | obj.includes = '. ..' |
| 33 | 33 | obj.uselib_local = 'modbus' |
| 34 | - obj.target = 'bench-bandwidth-slave' | |
| 34 | + obj.target = 'bandwidth-slave-one' | |
| 35 | 35 | obj.inst_var = 0 |
| 36 | 36 | |
| 37 | 37 | obj = bld.create_obj('cc', 'program') |
| 38 | - obj.source = 'bench-bandwidth-master.c' | |
| 38 | + obj.source = 'bandwidth-slave-many-up.c' | |
| 39 | 39 | obj.includes = '. ..' |
| 40 | 40 | obj.uselib_local = 'modbus' |
| 41 | - obj.target = 'bench-bandwidth-master' | |
| 41 | + obj.target = 'bandwidth-slave-many-up' | |
| 42 | + obj.inst_var = 0 | |
| 43 | + | |
| 44 | + obj = bld.create_obj('cc', 'program') | |
| 45 | + obj.source = 'bandwidth-master.c' | |
| 46 | + obj.includes = '. ..' | |
| 47 | + obj.uselib_local = 'modbus' | |
| 48 | + obj.target = 'bandwidth-master' | |
| 42 | 49 | obj.inst_var = 0 | ... | ... |