diff --git a/src/modbus-rtu.c b/src/modbus-rtu.c index b7749230c..cdde85f0f 100644 --- a/src/modbus-rtu.c +++ b/src/modbus-rtu.c @@ -11,6 +11,7 @@ #include #ifndef _MSC_VER #include +#include #endif #include "modbus-private.h" #include @@ -1134,6 +1135,8 @@ _modbus_rtu_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_t { int s_rc; #if defined(_WIN32) + FD_ZERO(&rset); + FD_SET(ctx->s, &rset); s_rc = win32_ser_select( &((modbus_rtu_t *) ctx->backend_data)->w_ser, length_to_read, tv); if (s_rc == 0) { @@ -1145,18 +1148,32 @@ _modbus_rtu_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_t return -1; } #else - while ((s_rc = select(ctx->s + 1, rset, NULL, NULL, tv)) == -1) { - if (errno == EINTR) { - if (ctx->debug) { - fprintf(stderr, "A non blocked signal was caught\n"); - } - /* Necessary after an error */ - FD_ZERO(rset); - FD_SET(ctx->s, rset); - } else { - return -1; - } - } + struct pollfd fds; + + // 初始化pollfd结构(对应FD_ZERO和FD_SET) + fds.fd = ctx->s; // 要监控的文件描述符 + fds.events = POLLIN; // 监控读事件 + fds.revents = 0; // 初始化返回事件 + + // 转换超时时间为毫秒(根据tv计算) + int timeout_ms = (tv != NULL) ? (tv->tv_sec * 1000 + tv->tv_usec / 1000) : -1; + + // 替换select循环,处理EINTR信号中断 + while ((s_rc = poll(&fds, 1, timeout_ms)) == -1) { + if (errno == EINTR) { + if (ctx->debug) { + fprintf(stderr, "A non blocked signal was caught\n"); + } + // 信号中断后重新初始化(对应原FD_ZERO和FD_SET) + fds.revents = 0; // 重置返回事件 + // 无需重新设置fd和events,因为它们未改变 + // 超时时间如果是相对时间,可能需要重新计算(根据实际需求) + } else { + // 其他错误,与原逻辑一致 + return -1; + } + } + if (s_rc == 0) { /* Timeout */ diff --git a/src/modbus-tcp.c b/src/modbus-tcp.c index 0c571097a..f30056db3 100644 --- a/src/modbus-tcp.c +++ b/src/modbus-tcp.c @@ -45,6 +45,7 @@ # include # include # include +#include #endif #if !defined(MSG_NOSIGNAL) @@ -290,6 +291,7 @@ static int _connect(int sockfd, struct timeval tv = *ro_tv; /* Wait to be available in writing */ +#ifdef _WIN32 FD_ZERO(&wset); FD_SET(sockfd, &wset); rc = select(sockfd + 1, NULL, &wset, NULL, &tv); @@ -297,7 +299,17 @@ static int _connect(int sockfd, /* Timeout or fail */ return -1; } - + #else + struct pollfd fds; + + int i32TimeOutMic = tv.tv_sec * 1000 + tv.tv_usec / 1000; + fds.fd = sockfd; + fds.events = POLLOUT; + int i32Ret = poll(&fds, 1, i32TimeOutMic); + if (i32Ret <= 0) { + return -1; + } +#endif /* The connection is established if SO_ERROR and optval are set to 0 */ rc = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen); if (rc == 0 && optval == 0) { @@ -482,12 +494,26 @@ static int _modbus_tcp_flush(modbus_t *ctx) tv.tv_sec = 0; tv.tv_usec = 0; +#ifdef _WIN32 FD_ZERO(&rset); FD_SET(ctx->s, &rset); rc = select(ctx->s + 1, &rset, NULL, NULL, &tv); if (rc == -1) { return -1; } +#else + struct pollfd fds; + int i32TimeOutMic = tv.tv_sec * 1000 + tv.tv_usec / 1000; + fds.fd = ctx->s; + fds.events = POLLIN; + fds.revents = 0; + int i32Ret = poll(&fds, 1, i32TimeOutMic); + if (i32Ret == -1) { + return -1; + } + +#endif + if (rc == 1) { /* There is data to flush */ @@ -764,7 +790,8 @@ static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read) { int s_rc; - while ((s_rc = select(ctx->s + 1, rset, NULL, NULL, tv)) == -1) { +#ifdef _WIN32 + while ((s_rc = select(ctx->s + 1, rset, NULL, NULL, tv)) == -1) { if (errno == EINTR) { if (ctx->debug) { fprintf(stderr, "A non blocked signal was caught\n"); @@ -776,6 +803,30 @@ _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_t return -1; } } +#else + struct timeval ttv = *tv; + struct pollfd fds; + int i32TimeOutMic = ttv.tv_sec * 1000 + ttv.tv_usec / 1000; + fds.fd = ctx->s; + fds.events = POLLIN; + fds.revents = 0; + while ((s_rc = poll(&fds, 1, i32TimeOutMic)) == -1) { + if (errno == EINTR) { + if (ctx->debug) { + fprintf(stderr, "A non blocked signal was caught\n"); + } + // 信号中断后重新初始化(对应原FD_ZERO和FD_SET) + fds.revents = 0; // 重置返回事件 + // 无需重新设置fd和events,因为它们未改变 + // 超时时间如果是相对时间,可能需要重新计算(根据实际需求) + } else { + // 其他错误,与原逻辑一致 + return -1; + } + } +#endif + + if (s_rc == 0) { errno = ETIMEDOUT; diff --git a/src/modbus.c b/src/modbus.c index 0360d5ccd..92c4cb2a9 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -23,6 +23,8 @@ #include "modbus-private.h" #include "modbus.h" +static debuglog g_debuglog = NULL; + /* Internal use */ #define MSG_LENGTH_UNDEFINED -1 @@ -169,6 +171,15 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length) msg_length = ctx->backend->send_msg_pre(msg, msg_length); + if (g_debuglog) { + char buf[2048]; + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "send:"); + for (int i = 0; i < msg_length; i++) { + snprintf(buf + 5 + i * 3, sizeof(buf) - 1, "%.2X ", msg[i]); + } + g_debuglog(buf); + } if (ctx->debug) { for (i = 0; i < msg_length; i++) printf("[%.2X]", msg[i]); @@ -376,8 +387,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) } /* Add a file descriptor to the set */ - FD_ZERO(&rset); - FD_SET(ctx->s, &rset); + //FD_ZERO(&rset); + //FD_SET(ctx->s, &rset); /* We need to analyse the message step by step. At the first step, we want * to reach the function code because all packets contain this @@ -517,6 +528,15 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) if (ctx->debug) printf("\n"); + if (g_debuglog) { + char buf[2048]; + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "recv:"); + for (int i = 0; i < msg_length; i++) { + snprintf(buf + 5 + i * 3, sizeof(buf) - 1, "%.2X ", msg[i]); + } + g_debuglog(buf); + } return ctx->backend->check_integrity(ctx, msg, msg_length); } @@ -2067,4 +2087,7 @@ size_t strlcpy(char *dest, const char *src, size_t dest_size) return (s - src - 1); /* count does not include NUL */ } +void register_debuglog(debuglog pf) { + g_debuglog = pf; +} #endif diff --git a/src/modbus.h b/src/modbus.h index 55ef08a0d..3a071ba63 100644 --- a/src/modbus.h +++ b/src/modbus.h @@ -21,6 +21,12 @@ #include "modbus-version.h" +#ifdef _WIN32 +#include +#include +#pragma comment ( lib, "ws2_32.lib" ) +#endif + #if defined(_MSC_VER) # if defined(DLLBUILD) /* define DLLBUILD when building the DLL */ @@ -324,6 +330,9 @@ MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest); #include "modbus-rtu.h" #include "modbus-tcp.h" +typedef void(*debuglog)(const char*); +void MODBUS_API register_debuglog(debuglog pf); + MODBUS_END_DECLS #endif /* MODBUS_H */ diff --git a/src/win32/modbus-9.sln b/src/win32/modbus-9.sln index b84f0f5a7..88b82f99c 100644 --- a/src/win32/modbus-9.sln +++ b/src/win32/modbus-9.sln @@ -1,7 +1,9 @@  -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual C++ Express 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "modbus", "modbus.vcproj", "{498E0845-C7F4-438B-8EDE-EF7FC9A74430}" +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34622.214 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "modbus", "modbus.vcxproj", "{498E0845-C7F4-438B-8EDE-EF7FC9A74430}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,4 +19,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {25E862B0-A6DB-4CB1-A1B9-F4DFB41A726C} + EndGlobalSection EndGlobal