Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 29 additions & 12 deletions src/modbus-rtu.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <string.h>
#ifndef _MSC_VER
#include <unistd.h>
#include <poll.h>
#endif
#include "modbus-private.h"
#include <assert.h>
Expand Down Expand Up @@ -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) {
Expand All @@ -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 */
Expand Down
55 changes: 53 additions & 2 deletions src/modbus-tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
# include <netinet/tcp.h>
# include <arpa/inet.h>
# include <netdb.h>
#include <poll.h>
#endif

#if !defined(MSG_NOSIGNAL)
Expand Down Expand Up @@ -290,14 +291,25 @@ 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);
if (rc <= 0) {
/* 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) {
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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");
Expand All @@ -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;
Expand Down
27 changes: 25 additions & 2 deletions src/modbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "modbus-private.h"
#include "modbus.h"

static debuglog g_debuglog = NULL;

/* Internal use */
#define MSG_LENGTH_UNDEFINED -1

Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
9 changes: 9 additions & 0 deletions src/modbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@

#include "modbus-version.h"

#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#pragma comment ( lib, "ws2_32.lib" )
#endif

#if defined(_MSC_VER)
# if defined(DLLBUILD)
/* define DLLBUILD when building the DLL */
Expand Down Expand Up @@ -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 */
11 changes: 8 additions & 3 deletions src/win32/modbus-9.sln
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -17,4 +19,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {25E862B0-A6DB-4CB1-A1B9-F4DFB41A726C}
EndGlobalSection
EndGlobal