DLL是否具有可能影响以太网功能的较低优先级?正在经历TCP重传

DLL是否具有可能影响以太网功能的较低优先级?正在经历TCP重传,dll,tcp,ethernet,modbus,retransmit-timeout,Dll,Tcp,Ethernet,Modbus,Retransmit Timeout,我有一些modbus以太网tcp通信,我正试图在DLL中进行。我从目标设备获得了大量TCP重传,如WireShark所示 (图中192.168.1.5为Modbus设备,192.168.1.72为计算机) 但是,如果将相同的代码直接插入到应用程序中,则不会出现通信错误 我想知道DLL是否具有某种较低的优先级,这会导致通信速度变慢,或者是否有人能够理解为什么这段代码在应用程序中运行时不会出现TCP问题,而不是在DLL中运行 以下是dll头: #ifndef __MAIN_H__ #define

我有一些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
\ifndef\uu MAIN\uh__
#定义主__
#包括
typedef void*eioTHandle;
#ifdef_uucplusplus
外部“C”
{
#恩迪夫
__declspec(dllexport)int_ustdcall eioConnect(无符号短ModelId,char*Ip,eioTHandle*Handle);
#ifdef_uucplusplus
}
#恩迪夫
#恩迪夫
以下是源文件:

#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;

}
#包括“main.h”
#包括
#包括
#包括
#定义EIO500_S 0
#定义EIO500_MS 1000
#定义eioERROR-1
#定义EIOSAccess 0
静态uint8_t m_UnitId=0xff;
静态插座m_插座;
BOOL WINAPI DllMain(HINSTANCE hinstDLL、DWORD fdreason、LPVOID lpReserved)
{
//根据调用的原因执行操作。
开关(FDSON)
{
案例DLL\u进程\u附加:
//为每个新进程初始化一次。
//返回FALSE以使DLL加载失败。
打破
案例DLL\u线程\u连接:
//执行特定于线程的初始化。
打破
案例DLL\u线程\u分离:
//执行特定于线程的清理。
打破
案例DLL\u进程\u分离:
//执行任何必要的清理。
打破
}
返回TRUE;//成功的DLL\u进程\u附加。
}
int_ustdcall eioConnect(无符号短ModelId,char*Ip,eioTHandle*Handle)
{
WSADATA Wsa;
服务器中的结构sockaddr_;
int结果;
字符缓冲区[256];
charinbuffer[256];
//联系--------------------------------------------------------------
if(WSAStartup(MAKEWORD(2,2),&Wsa)!=0)
{
返回错误;
}
m_Sock=socket(AF_INET、Sock流、IPPROTO_TCP);
if(m_Sock==无效的_SOCKET)
{
WSACleanup();
返回错误;
}
Server.sin_addr.s_addr=inet_addr(Ip);
Server.sinu family=AF\u INET;
Server.sin_port=htons(502);
if(连接(m_Sock,(struct sockaddr*)和服务器,sizeof(服务器))
==套接字(U错误)
{
封闭式插座(m_-Sock);
m_Sock=无效的_Sock;
WSACleanup();
返回错误;
}
// -------------------------------------------------------------------------
对于(int Ctr=0;Ctr<50000;Ctr++)
{
//发送命令--------------------------------------------------------
//发送-读取多线圈命令中有5个字节。
int NumBytes=5;
缓冲区[0]=0;
缓冲区[1]=0;
缓冲区[2]=0;
缓冲区[3]=0;
缓冲区[4]=0;
缓冲区[5]=NumBytes+1;//1表示单元id。
缓冲区[6]=m_UnitId;
//0=功能代码。
缓冲区[7]=0x01;
//1+2=地址。
缓冲区[8]=0;
缓冲区[9]=8;
//3+4=要读取的位数。
缓冲区[10]=0;
缓冲区[11]=8;
如果(发送(m_Sock,Buffer,NumBytes+7,0)=套接字错误)
{
继续;
}
// ---------------------------------------------------------------------
//等待接收----------------------------------------------------
WSAEVENT RecvEvent;
int Ret;
RecvEvent=WSACreateEvent();
WSAEventSelect(m_Sock、RecvEvent、FD_READ);
Ret=WSAWaitForMultipleEvents(1,&RecveEvent,TRUE,1000,FALSE);
wsarestevent(RecvEvent);
如果(Ret==WSA\u等待\u超时)
继续;
// -------------------------------------------------------------------------
//检查是否有任何回复。
recv(m_Sock,InBuffer,256,0);
}
//断开--------------------------------------------------------------
结果=关机(m_Sock,SD_SEND);
如果(结果==套接字错误)
{
封闭式插座(m_-Sock);
WSACleanup();
m_Sock=无效的_Sock;
返回错误;
}
//接收,直到对等方关闭连接。
而(recv(m_-Sock,Buffer,256,0)>0);
封闭式插座(m_-Sock);
WSACleanup();
m_Sock=无效的_Sock;
// ------------------------------------------------------------------------
返回EIOSACCESS;
}

我已经尽可能地简化了代码。通信处于测试的环路中。原始应用程序将从设备轮询此数据。

否。从网络的角度来看,以某种方式发送的TCP段没有区别。可能存在协议优先权(QoS),当链路饱和时可能导致数据包丢失


更可能的原因可能是校验和的问题:无效的校验和会导致数据包丢失,从而导致重新传输。从DLL调用API时,其工作方式可能略有不同,因此校验和是(正确的)。

但是为什么API通过DLL的工作方式与通过应用程序的工作方式不同呢?我忘了提到,在这两种情况下(应用程序和DLL),这都是一对一的连接。网络上唯一的设备是计算机和modbus设备。除了modbus通信之外,没有其他通信。从代码中可以看出,这是无线程的,因此整个数据包周期是线性的。没有配置QoS策略。对不起,我不是Windows开发人员,但我知道一些Win API有点奇怪。不过,您可以排除网络部分,它在API中。请验证正在重新发送的数据包上的校验和