Есть ли у 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, поэтому контрольные суммы рассчитываются (правильно).

Другие вопросы по тегам