Как получить высокоскоростной пакет UDP полностью? - PullRequest
0 голосов
/ 07 июня 2018

У меня есть UDP-сервер, который непрерывно отправляет данные.Я хочу получить все пакеты, отправленные сервером.

На стороне сервера у меня есть два потока.Один поток непрерывно читает данные из файла и переводит их в режим deque.Другой поток читает данные из очереди и непрерывно отправляет клиенту UDP.Код клиента непрерывно получает данные с сервера.

У меня есть переменные для хранения количества байтов, отправленных в коде сервера, и количества байтов, полученных в коде клиента.Существует огромная разница между ними.Сервер отправляет около 93 МБ, но клиент получает только 3 - 5 МБ.

Как я могу получить все данные, отправленные сервером?

Найдите код сервера и клиента ниже.

Код сервера:

#define MAX_BUFFER_SIZE 1400

typedef struct
{
    T_UCHAR buffer[MAX_BUFFER_SIZE];
    DWORD buf_size;
}RAWDATA_LOG;

deque<RAWDATA_LOG>  m_RawdataLog;   

void TransmitContinuous()
{
    if (m_sock_type_tcp == SOCK_UDP)
    {
        fileReadComplete=false;
        //start data transmission thread
        pWin_thread=AfxBeginThread(StartDataTransmitThread, (LPVOID) this);
        ReadFromFile();
    }   

}


void ReadFromFile()
{
    int bytesRead=0;
    m_no_of_bytes = MAX_BUFFER_SIZE;
    BYTE input_buf[MAX_BUFFER_SIZE]={'\0'};


    GetDlgItemText(IDEBC_FILENAME,m_fileInput);


    m_InputFile=NULL;
    /*opening the file to read*/
    m_InputFile = _tfopen(m_fileInput,L"rb");
    if(m_InputFile == NULL)
    {
        AfxMessageBox(L"Unable to open the Input file");
    }
    else
    {

        while(!feof(m_InputFile))
        {
            bytesRead=fread(input_buf,1,m_no_of_bytes,m_InputFile);

            writeRawdataToDeque(input_buf,m_no_of_bytes);
            noofBytesReadfromFile+=bytesRead;

        }
        fileReadComplete=true;
    }
}


void writeRawdataToDeque(T_UCHAR *buffer,T_S32 size)
{

    T_S32 temp_size = size;
    T_S32 size_counter = 0;
    RAWDATA_LOG temp_rawDataStruct;

    while(temp_size>0)
    {
        if(temp_size <= MAX_BUFFER_SIZE)
        {
            memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],temp_size);
            temp_rawDataStruct.buf_size = temp_size;
            noofBytesWrittentoDeque+=temp_size;

        }
        else
        {
            memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],sizeof(temp_rawDataStruct.buffer));
            temp_rawDataStruct.buf_size = MAX_BUFFER_SIZE;
            noofBytesWrittentoDeque+=MAX_BUFFER_SIZE;
        }

        CSingleLock datalock(&m_Cs_RawDataLog);
        datalock.Lock();
        m_RawdataLog.push_back(temp_rawDataStruct);
        datalock.Unlock();


        memset(&temp_rawDataStruct,0,sizeof(temp_rawDataStruct));
        size_counter += MAX_BUFFER_SIZE;
        temp_size = temp_size - MAX_BUFFER_SIZE;
    }                                               
}

unsigned int StartDataTransmitThread (LPVOID param)
{

    RAWDATA_LOG temp_rawDataBuf;
    int byesWritten=0;
    CString tmpStr;

    while(1)
    {

        if(!m_RawdataLog.empty())
        {
            CSingleLock datalock(&m_Cs_RawDataLog);
            datalock.Lock();
            temp_rawDataBuf = m_RawdataLog.front();
            m_RawdataLog.pop_front();
            datalock.Unlock();

            //transmit the data through socket  
            byesWritten=WritetoClient(clientIp,clientPort,(const LPBYTE)&temp_rawDataBuf, MAX_BUFFER_SIZE);

            noofBytesTransmitted+=byesWritten;

        }
        else
        {
            if(fileReadComplete == true)
            {

                break;
            }
        }       
    }

    return true;
}



bool CreateServer(char ipaddr[],int port)
{
    sockaddr_in ServerSockAddr;
    WORD m_wVersionRequested;
    WSADATA m_wsaData;
    int m_wsaErr;

    ServerSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
    ServerSockAddr.sin_family = AF_INET;
    ServerSockAddr.sin_port = htons(2011);


     m_wVersionRequested = MAKEWORD(2, 2);          
     m_wsaErr = WSAStartup(m_wVersionRequested, &m_wsaData);
     if (m_wsaErr != 0) 
     {
        /* Tell the user that we could not find a usable */
        /* Winsock DLL.                                  */
        MessageBox(L"WSAStartup failed with error:" + m_wsaErr);
        return 1;
     }

    SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (INVALID_SOCKET != sock)
    {


        if ( SOCKET_ERROR == bind(sock,(struct sockaddr *) & ServerSockAddr, sizeof(ServerSockAddr)))
        {
            int b= GetLastError();
            closesocket( sock );
            return false;
        }
    }
    else
    {
        closesocket( sock );
        return false;
    }

    m_hComm = (HANDLE) sock;
}


int WritetoClient(char ipaddr[],int port,BYTE buf[],int len)
{

     sockaddr_in clientSockAddr;
     int res=0;


      SOCKET s = (SOCKET) m_hComm;

      clientSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
      clientSockAddr.sin_family = AF_INET;
      clientSockAddr.sin_port = htons(port);

      res = sendto( s, (const char *)buf, len, 0, (SOCKADDR  *) &clientSockAddr, sizeof(clientSockAddr));

      return res;
}

Код клиента:

#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32")

#define BUFSIZE 1000000

int _tmain(int argc, _TCHAR* argv[])
{
    SOCKET sockfd;
    int  portno, n;
    int serverlen;
    struct sockaddr_in serveraddr;
    struct hostent *server;
    char *hostname;
    char buf[BUFSIZE];
    int BytesReceived=0;
    int buff_size=1000000;

    WORD m_wVersionRequested;
    WSADATA m_wsaData;
    int m_wsaErr;

     m_wVersionRequested = MAKEWORD(2, 2);          
     m_wsaErr = WSAStartup(m_wVersionRequested, &m_wsaData);
     if (m_wsaErr != 0) 
         {
        /* Tell the user that we could not find a usable */
        /* Winsock DLL.                                  */
        printf("WSAStartup failed with error:");
        return 1;
     }

    /* socket: create the socket */
    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sockfd < 0) 
    {

        printf("ERROR opening socket");
    }


    else
    {
        /* build the server's Internet address */

        serveraddr.sin_family = AF_INET;

        serveraddr.sin_port = htons(2010);
        serveraddr.sin_addr.s_addr=inet_addr("192.168.11.80");



        /* send the message to the server */
        serverlen = sizeof(serveraddr);

        setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,(char *)(&buff_size), sizeof(buff_size));

        if ( SOCKET_ERROR == bind(sockfd,(struct sockaddr *) & serveraddr, sizeof(serveraddr)))
        {
            printf("Bind Error");
            int a = GetLastError();
            printf("Error ID:%d",a);
        }
        else
        {

            printf("Reading From Server:\n");

            while(1)
            {


                n = recvfrom(sockfd, buf, sizeof(buf), 0,(struct sockaddr *) &serveraddr, &serverlen);

                if (n < 0) 
                {
                    printf("ERROR in recvfrom\n");
                    int b = GetLastError();
                    printf("Error ID:%d\n",b);
                }
                else
                {

                    BytesReceived+=n;

                    TRACE("\nTotal Bytes Received:%d\n",BytesReceived);
                }

            }
        }
    }
    getchar();
    return 0;



}

1 Ответ

0 голосов
/ 07 июня 2018

Я вижу пару проблем с вашим кодом.

На стороне сервера вы привязываете сокет сервера к 192.168.11.80 И вы также отправляете пакеты на 192.168.11.80 вместо их отправкив зависимости от того, какой IP-адрес указан в параметре ipaddr функции WritetoClient().

На стороне клиента вы bind() выводите клиентский сокет на сервер IPадрес.

Эта настройка будет работать только в том случае, если клиент и сервер работают на одном компьютере.Он не будет работать между несколькими компьютерами, подключенными через сеть.

Вам необходимо привязать клиента к IP-адресу, локальному для собственной машины клиента , а не к IP-адресу сервера.А вашему серверу необходимо отправлять пакеты на IP-адрес, с которым клиент фактически связан.

Если вы хотите, чтобы ваш клиент получал данные только с IP-адреса сервера, а не с других машин, которые могут произойтидля отправки данных по той же сети вы можете дополнительно connect() сокет клиента на IP-адрес сервера (да, вы можете использовать connect() с UDP).

bind() - для установления сокеталокальный IP-адрес.connect() предназначен для установки удаленного / равноправного IP-адреса сокета.

Поскольку вы (возможно) неправильно привязываете сокет клиента и / или (потенциально) не отправляете на правильный IP-адрес, вы, вероятно, получаетеданные, которые вы не ожидаете откуда-то еще.Это может объяснить большое расхождение, которое вы видите.Я бы предложил, чтобы ваш клиент выводил данные, которые он фактически получает, чтобы вы могли убедиться, что он получает то, что вы ожидаете, например:

n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &serveraddr, &serverlen);
if (n == SOCKET_ERROR) 
{
    int b = WSAGetLastError();
    printf("ERROR in recvfrom\nError ID:%d\n",b);
}
else
{
    BytesReceived += n;
    TRACE("\nMessage Received from %s:%hu: '%.*s'", inet_ntoa(serveraddr.sin_addr), ntohs(serveraddr.sin_port), n, buf);
    TRACE("\nTotal Bytes Received: %d\n", BytesReceived);
}
...