《C++ Builder下三种UDP通信实现方法的比较》由会员分享,可在线阅读,更多相关《C++ Builder下三种UDP通信实现方法的比较(6页珍藏版)》请在金锄头文库上搜索。
1、C+ Builder下三种UDP通信实现方法的比较 出处 主要讨论一下数据的接受:1.NMUDP控件这个控件使用起 来比较简单,设定监听端口,然后响应DataReceived 事件就可以了,例如:void _fastcall TMoniter:NMUDPDataReceived(TComponent *Sender,int NumberBytes, AnsiString FromIP, int Port)/* 用一个标志变量控制控件受信后是否执行需要的操作 */if (recvFlag)int rl;/* 用于接受数据的内存 */unsigned char rbuf1024 * 9; /* 控
2、件的ReadBuffer 方法,把接受到的数据存储到rbuf */NMUDP - ReadBuffer(rbuf , sizeof(rbuf) , rl);/* 字符串结束 */rbufrl=0;/* stream是事先定义的文件指针 */if (stream != NULL)/* 自编doLog函数,把接收数据写入日志文件 */doLog( false , rbuf ,rl ;这个控件的优点是使用简单、效率比较高,但是只支持2K的缓冲,所以上面开辟的9K 内存是多余的。2K的限制使我在 项目中不得不放弃了 这个控件。2.IdUDPServer控件使用方法跟NMUDP差不多,响应UDPRead
3、事件就可以了,例如:(注 释参考1)void _fastcall TMoniter:IdUDPServer1UDPRead(TObject *Sender, TStream *AData, TIdSocketHandle *ABinding)if (recvFlag)int r1;unsigned char rbuf1024 * 9;r1 = AData-Size;/* 接受到的数据是存放在 数据流AData中的,把它们读到rbuf里去 */AData-Read(rbuf , r1);rbufr1 = 0;if (stream != NULL)doLog( false , rbuf ,r1);
4、这个控件支持了9K的缓冲,但是效率 我需要1秒钟接收150个1K多的数据包并解码后逐行显示在StringGrid中,虽然主要是对StringGrid的描绘浪费时间,但IdUDPServer还是不能令人满意。3.回 归自然 吧 Socket两个控件都不能满足我的需要,那么只能回头考虑底层的socket(我的C不好,对这个方法现在还不是很明白,所以注释很少,不过通过代码能大约猜出其功能)。先定义这三个东东:SOCKET sockWSADATA wsaDataSOCKADDR_IN sockaddr然后在需要开始受信的地方进行socket初始化,这里我用了一个按钮:int result;WORD w
5、VersionRequested;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.si
6、n_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
7、_OK);WSACleanup();return;/* 自写函数getFileReady打开一个日志文件等待记录数据 */if( !getFileReady() WSACleanup();return;/* 把StringGrid编辑区域清理一下 */sgLog - RowCount = 2; sgLog - Rows1 - Clear();sgLog - Cells01 = 1;lineCount = 1;/* 启动线程,接受数据 */recvFlag = true;tudpr = new TUDPR(true);tudpr-Resume();TUDPR是负责受信的线程,其类定义如下:cla
8、ss TUDPR : public TThread private:protected:void _fastcall Execute();public:_fastcall TUDPR(bool CreateSuspended);线程内的完整处理如下:#include #pragma hdrstop#include #include TUDPR.h#include Monitor.hextern int m_sendRcvFlag;extern SOCKET sock;extern WSADATA wsaData;extern SOCKADDR_IN sockaddr;#pragma packa
9、ge(smart_init)_fastcall TUDPR:TUDPR(bool CreateSuspended): TThread(CreateSuspended)void _fastcall TUDPR:Execute()int result;unsigned char rbufSNDRCVDATALEN;/* 受信标志变量为真时接收数据 */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;rbufresult = 0;/* 参考1中的doLog注释 */ Moniter - doLog(false , rbuf , result);第三种方法在效率上可以满足要求了,但是需要管理线程,实现起来也明显要麻烦许多。