1. 程式人生 > >C++ Builder下三種UDP通訊實現方法的比較 選擇自 findheart 的 Blog

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


 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);
    }
}

相關推薦

C++ BuilderUDP通訊實現方法比較 選擇 findheartBlog

 C++ Builder下三種UDP通訊實現方法的比較     選擇自 findheart 的 Blog  關鍵字   C++ Builder下三種UDP通訊實現方法的比較 出處      主要討論一下資料的接受:1.NMUDP控制元件   這個控制元件使用起來比較簡單,設定

生產者消費者併發模式實現方法

package cn.luxh.app.test; import java.util.LinkedList; import java.util.List; import java.util.Random; import java.util.concurrent.Executor; import java.u

傳統JSP,JSP+JavaBean,JSP+Servlet+JavaBean開發javaweb的方法比較

1.傳統的Javaweb中,JSP既負責資料展示,又負責業務邏輯處理和流程控制。簡化過程如下圖:                                                  

將文件拖曳到窗體上, 並獲取其完整路徑 【C++ Builder實現】轉

pat ext stc fff led CP tle 聲明 net 1. 在窗體的頭文件.h裏聲明處理函數和消息映射, 如: [cpp] view plain copy class TForm1 : public TForm {

uniGUI for C++ builder如何利用FastReport實現數據記錄本地打印

ces sof dbus 實現 Owner 查詢 設置 web 同時 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/dlboy2018/article/details/81040260 (中行雷威2018.7.14於杭州

python3在windows方法使用C擴充套件

一、前言         python有時候需要用到c或者c++的庫,這裡我們將介紹三種呼叫c擴充套件的方法。分別用swig,stypes,和python C擴充套件。三種方法各有優缺點,但第三種方法最為常用。我使用到的平臺為windows10,pytho

面試篇--android網路通訊機制(網路通訊方式)

HttpClient HttpClient是Apache對java中的HttpURLClient介面的封裝,主要引用org.apache.http.**。Google在2.3版本之前推薦使用HttpClient,因為這個封裝包安全性高,bug較少。 使用方法: impo

(作業系統實驗)n道批處理系統常見的作業排程演算法實現

單道和多道批處理作業排程演算法 批處理就是把一批量的作業放入批處理系統進行處理。主要有兩個過程: 把作業調入磁碟(外存)的輸入井中(等待被調入記憶體) 調入記憶體中被執行 根據批處理系統的道數,分為單道批處理系統和多道批處理系統: 單道批處理系統:一次只允

循環實現0-100相加的linux腳本

linux腳本1、 #!/bin/bash#0~100相加,for循環 declare -i ideclare -i sum for i in {1..100};dolet sum+=ilet i++done echo $sum2、 #!/bin/bash#0~100相加,until循環 declare -i

EF3:Entity Framework開發模式實現數據訪問

支持 代碼 sql blog flow cli guid 自動完成 main 前言 Entity Framework支持Database First、Model First和Code Only三種開發模式,各模式的開發流程大相徑庭,開發體驗完全不一樣。三種開發模式各有優缺

QUdpSocket-Qt使用Udp通訊實現服務端和客戶端

array tle sig post 客戶端 種類型 可用 進行 += 版權聲明:若無來源註明,Techie亮博客文章均為原創。 轉載請以鏈接形式標明本文標題和地址: 本文標題:QUdpSocket-Qt使用Udp通訊實現服務端和客戶端 本文地址:http://t

SSO單點登錄情況的實現方式詳解

否則 post請求 登錄用戶 搭建集群 本地 sub 簡單的 div nmp 單點登錄(SSO——Single Sign On)對於我們來說已經不陌生了。對於大型系統來說使用單點登錄可以減少用戶很多的麻煩。就拿百度來說吧,百度下面有很多的子系統——百度經驗、百度知道、百度文

Shader筆記十九——凹凸紋理實現

Normal Map 法線紋理是通過一張與漫反射紋理相對應的法線圖,儲存法線資訊,使用的時候對應紋理座標進行取樣,通過法線值影響光影計算的結果,從而產生凹凸效果。Normal Map可能是目前使用最為廣泛的一種凹凸貼圖技術了。之前的內容也有介紹過, https://zhua

C || 圖的四儲存結構實現

1. 陣列表示法: #include <stdio.h> #include <limits.h> #define INFINITY INT_MAX #define Maxvex 100 typedef struct graph {

SparkSQL中的Join及其實現(broadcast join、shuffle hash join和sort merge join)

1.小表對大表(broadcast join) 將小表的資料分發到每個節點上,供大表使用。executor儲存小表的全部資料,一定程度上犧牲了空間,換取shuffle操作大量的耗時,這在SparkSQL中稱作Broadcast Join Broadcast Jo

C# 委託的呼叫示例(同步呼叫、非同步呼叫、非同步回撥)

首先,通過程式碼定義一個委託和下面三個示例將要呼叫的方法: 程式碼如下: public delegate int AddHandler(int a,int b); public class 加法類 { public static int A

1、利用介面實現動態的建立物件[選做題] 1.1 建立4個類: 蘋果 香蕉 葡萄 園丁 1.2 在水果的構造方法中列印一句話. 以蘋果類為例

package javademo9; import java.util.Scanner; interface Fruit{ } class Apple implements Fruit { public Apple() { System.out.println("建立了一個蘋

我來學網路——資料通訊方式

對於點對點之間的通訊,按照訊息傳送的方向與時間關係,通訊方式可分為單工通訊、半雙工通訊及全雙工通訊三種。 單工通訊只支援資料在一個方向上傳輸,又稱為單向通訊。如無線電廣播和電視廣播都是單工通訊。 半雙工通訊允許資料在兩個方向上傳輸,但在同一時刻,只允許資料在一個方向上傳輸,它實際上是一種可切

50、多執行緒建立的方式之實現Runnable介面

實現Runnable介面建立執行緒 使用Runnable建立執行緒步驟: package com.sutaoyu.Thread; //1.自定義一個類實現java.lang包下的Runnable介面 class MyRunnable implements Runnable{ /

SSO單點登入情況的實現方式詳解

單點登入(SSO——Single Sign On)對於我們來說已經不陌生了。對於大型系統來說使用單點登入可以減少使用者很多的麻煩。就拿百度來說吧,百度下面有很多的子系統——百度經驗、百度知道、百度文庫等等,如果我們使用這些系統的時候,每一個系統都需要我們輸入使用者名稱和密碼登