分享
 
 
 

C++ Builder下三种UDP通信实现方法的比较

王朝c/c++·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

主要讨论一下数据的接受:

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

}

}

第三种方法在效率上可以满足要求了,但是需要管理线程,实现起来也明显要麻烦许多。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有