Есть ли у DLL более низкий приоритет, который может повлиять на функциональность Ethernet? Испытание TCP-повторных передач
У меня есть некоторые связи Modbus TCP, которые я пытаюсь сделать в DLL. Я получаю многочисленные повторные TCP-передачи от целевого устройства, как видно из WireShark.
(На этом изображении 192.168.1.5 - устройство Modbus. 192.168.1.72 - компьютер)
Однако, когда тот же код вставляется непосредственно в приложение, ошибок связи не возникает.
Мне интересно, имеют ли DLL-файлы какой-то более низкий приоритет, который может вызывать более медленную связь, или кто-то может иметь какое-либо представление о том, почему этот код будет работать без проблем с TCP в приложении, но не в DLL.
Вот заголовок dll:
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
typedef void *eioTHandle;
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) int __stdcall eioConnect( unsigned short ModelId, char *Ip, eioTHandle *Handle );
#ifdef __cplusplus
}
#endif
#endif
А вот и исходный файл:
#include "main.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdint.h>
#define EIO500_S 0
#define EIO500_MS 1000
#define eioERROR -1
#define eioSUCCESS 0
static uint8_t m_UnitId = 0xff;
static SOCKET m_Sock;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved )
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
int __stdcall eioConnect( unsigned short ModelId, char *Ip, eioTHandle *Handle )
{
WSADATA Wsa;
struct sockaddr_in Server;
int Result;
char Buffer[256];
char InBuffer[256];
// CONNECTION --------------------------------------------------------------
if (WSAStartup(MAKEWORD(2,2), &Wsa) != 0)
{
return eioERROR;
}
m_Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_Sock == INVALID_SOCKET)
{
WSACleanup();
return eioERROR;
}
Server.sin_addr.s_addr = inet_addr(Ip);
Server.sin_family = AF_INET;
Server.sin_port = htons(502);
if (connect(m_Sock, (struct sockaddr *)&Server, sizeof(Server))
== SOCKET_ERROR)
{
closesocket(m_Sock);
m_Sock = INVALID_SOCKET;
WSACleanup();
return eioERROR;
}
// -------------------------------------------------------------------------
for (int Ctr = 0; Ctr < 50000; Ctr++)
{
// SEND COMMAND --------------------------------------------------------
// 5 bytes in a Send Read Multiple Coils command.
int NumBytes = 5;
Buffer[0] = 0;
Buffer[1] = 0;
Buffer[2] = 0;
Buffer[3] = 0;
Buffer[4] = 0;
Buffer[5] = NumBytes + 1; // 1 for unit id.
Buffer[6] = m_UnitId;
// 0 = Function code.
Buffer[7] = 0x01;
// 1+2 = Address.
Buffer[8] = 0;
Buffer[9] = 8;
// 3+4 = Number of bits to read.
Buffer[10] = 0;
Buffer[11] = 8;
if (send(m_Sock, Buffer, NumBytes + 7, 0) == SOCKET_ERROR)
{
continue;
}
// ---------------------------------------------------------------------
// WAIT FOR RECEIVE ----------------------------------------------------
WSAEVENT RecvEvent;
int Ret;
RecvEvent = WSACreateEvent();
WSAEventSelect( m_Sock, RecvEvent, FD_READ );
Ret = WSAWaitForMultipleEvents(1, &RecvEvent, TRUE, 1000, FALSE);
WSAResetEvent(RecvEvent);
if (Ret == WSA_WAIT_TIMEOUT)
continue;
// -------------------------------------------------------------------------
// Check for any reply.
recv(m_Sock, InBuffer, 256, 0);
}
// DISCONNECT --------------------------------------------------------------
Result = shutdown(m_Sock, SD_SEND);
if (Result == SOCKET_ERROR)
{
closesocket(m_Sock);
WSACleanup();
m_Sock = INVALID_SOCKET;
return eioERROR;
}
// Receive until the peer closes the connection.
while (recv(m_Sock, Buffer, 256, 0) > 0);
closesocket(m_Sock);
WSACleanup();
m_Sock = INVALID_SOCKET;
// ------------------------------------------------------------------------
return eioSUCCESS;
}
Я максимально упростил код. Сообщение находится в цикле для тестирования. Исходное приложение будет опрашивать эти данные с устройства.
1 ответ
Нет. С точки зрения сети, нет никакой разницы в сегментах TCP, отправленных так или иначе. Хотя может существовать приоритет протокола (QoS), который может вызывать отбрасывание пакетов при насыщении каналов.
Более вероятной причиной может быть проблема с контрольными суммами: неверные контрольные суммы вызывают отбрасывание пакетов, что, в свою очередь, вызывает повторные передачи. Возможно, API работает немного иначе, когда вызывается из DLL, поэтому контрольные суммы рассчитываются (правильно).