C++ Builder下三種UDP通訊實現方法的比較 選擇自 findheart 的 Blog

來源:互聯網
上載者:User
 

 C++ Builder下三種UDP通訊實現方法的比較     選擇自 findheart 的 Blog  
關鍵字   C++ Builder下三種UDP通訊實現方法的比較 
出處    
 
 主要討論一下資料的接受:
1.NMUDP控制項
   這個控制項使用起來比較簡單,設定監聽連接埠,然後響應DataReceived事件就可以了,例如:
void __fastcall TMoniter::NMUDPDataReceived(TComponent *Sender,
      int NumberBytes, AnsiString FromIP, int Port)
{
    /* 用一個標誌變數控制控制項受信後是否執行需要的操作 */
    if (recvFlag)
    {
        int rl;
        /* 用於接受資料的記憶體 */
        unsigned char rbuf[1024 * 9];

        /* 控制項的ReadBuffer方法,把接受到的資料存放區到rbuf */
        NMUDP -> ReadBuffer(rbuf , sizeof(rbuf) , rl);
        
        /* 字串結束 */
        rbuf[rl]=0;

        /* stream是事先定義的檔案指標 */
        if (stream != NULL)
        {
            /* 自編doLog函數,把接收資料寫入記錄檔 */
            doLog( false , rbuf ,rl );
        }
    }
}
這個控制項的優點是使用簡單、效率比較高,但是只支援2K的緩衝,所以上面開闢的9K記憶體是多餘的。2K的限制使我在項目中不得不放棄了這個控制項。

2.IdUDPServer控制項
  使用方法跟NMUDP差不多,響應UDPRead事件就可以了,例如:(注釋參考1)
void __fastcall TMoniter::IdUDPServer1UDPRead(TObject *Sender,
      TStream *AData, TIdSocketHandle *ABinding)
{
    if (recvFlag)
    {
        int r1;
        unsigned char rbuf[1024 * 9];

        r1 =  AData->Size;
        /* 接受到的資料是存放在資料流AData中的,把它們讀到rbuf裡去 */
        AData->Read(rbuf , r1);
        rbuf[r1] = 0;

        if (stream != NULL)
        {
            doLog( false , rbuf ,r1);
        }
    }
}
這個控制項支援了9K的緩衝,但是效率……我需要1秒鐘接收150個1K多的資料包並解碼後逐行顯示在StringGrid中,雖然主要是對StringGrid的描繪浪費時間,但IdUDPServer還是不能令人滿意。

3.迴歸自然吧——Socket
兩個控制項都不能滿足我的需要,那麼只能回頭考慮底層的socket(我的C不好,對這個方法現在還不是很明白,所以注釋很少,不過通過代碼能大約猜出其功能)。
先定義這三個東東:
SOCKET sock
WSADATA wsaData
SOCKADDR_IN sockaddr
然後在需要開始受信的地方進行socket初始化,這裡我用了一個按鈕:
   int  result;
   WORD wVersionRequested;

    wVersionRequested = MAKEWORD(1,1);
    if((result = WSAStartup(wVersionRequested,&wsaData))!=0)
    {
         Application->MessageBoxA("Socket Initial Error","Error",MB_OK);
         WSACleanup();
         return;
    }

    memset(&sockaddr,0,sizeof(sockaddr));
    /* 設定連接埠號碼     */
    sockaddr.sin_port=htons(3000);
    sockaddr.sin_family=AF_INET;
    sockaddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

    sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock == INVALID_SOCKET)
    {
        Application->MessageBoxA("Socket Open failed","Error",MB_OK);
        WSACleanup();
        return;
    }

    result = bind(sock,(LPSOCKADDR)&sockaddr,sizeof sockaddr);
    if(result == SOCKET_ERROR)
    {
        Application->MessageBoxA("Bind Error","Error",MB_OK);
        WSACleanup();
        return;
    }

    /* 自寫函數getFileReady開啟一個記錄檔等待記錄資料 */
    if( !getFileReady() )
    {
        WSACleanup();
        return;
    }

    /* 把StringGrid編輯地區清理一下 */
    sgLog -> RowCount    = 2;
    sgLog -> Rows[1] -> Clear();
    sgLog -> Cells[0][1] = "1";
    lineCount            =  1;

    /* 啟動線程,接受資料 */
    recvFlag = true;
    tudpr    = new TUDPR(true);
    tudpr->Resume();
}
TUDPR是負責受信的線程,其類定義如下:
class TUDPR : public TThread
{            
private:
protected:
    void __fastcall Execute();
public:
    __fastcall TUDPR(bool CreateSuspended);
};

線程內的完整處理如下:
#include <vcl.h>
#pragma hdrstop
#include <winsock.h>

#include "TUDPR.h"
#include "Monitor.h"

extern int         m_sendRcvFlag;
extern SOCKET      sock;
extern WSADATA     wsaData;
extern SOCKADDR_IN sockaddr;

#pragma package(smart_init)

__fastcall TUDPR::TUDPR(bool CreateSuspended)
    : TThread(CreateSuspended)
{
}

void __fastcall TUDPR::Execute()
{
    int           result;
    unsigned char rbuf[SNDRCVDATALEN];

    /* 受信標誌變數為真時接收資料 */
    while(recvFlag)
    {
        result = recvfrom(sock,
                          rbuf,
                          SNDRCVDATALEN,
                          0,
                          NULL,
                          NULL
                          );
        if( !recvFlag )
        {
            break;
        }
        if(result == SOCKET_ERROR)
        {
            Application->MessageBoxA("Receive Error","Error",MB_OK);
            WSACleanup();
            return;
        }

        rbuf[result]  = 0;
       /* 參考1中的doLog注釋 */ 
       Moniter -> doLog(false , rbuf , result);
    }
}

第三種方法在效率上可以滿足要求了,但是需要管理線程,實現起來也明顯要麻煩許多。

作者Blog:http://blog.csdn.net/findheart/ ;

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.