zoukankan      html  css  js  c++  java
  • ACE库udp发送和接收

    udp双方由于不需要建立连接的过程,所以一个可以连续发送,一个连续接收。

    由于接收不过来就会丢包,所以发送速度是接收速度的1/2来缓解接收压力(通过ACE_OS::sleep来实现)

    一、发送端

    头文件:

    class CTcCommunicator
    {
    public:
    CTcCommunicator();
    virtual ~CTcCommunicator();


    //strRemoteTp:"192.168.1.23"
    int SendMessage(const MESSAGE& msg, string strRemoteTp);
    int ReceiveMessage();

    private:
    ACE_INET_Addr m_adrLocal; //本地地址信息
    ACE_SOCK_Dgram m_peer; //通信通道

    };

    源文件:

    //因为这个类主要用来发送,所以ReceiveMessage()并没有实现

    CTcCommunicator::CTcCommunicator():m_peer(m_adrLocal)
    {

    }

    CTcCommunicator::~CTcCommunicator()
    {
    m_peer.close();
    }

    int CTcCommunicator::SendMessage( const MESSAGE& msg, string strRemoteTp)
    {

    //发送数据
    char buf[2048];

    memcpy(buf,&msg,sizeof(MESSAGE));

    strRemoteTp += ":4000"; //端口号
    ACE_INET_Addr tcAddr;
    tcAddr.string_to_addr(strRemoteTp.c_str()); // 形参格式:“192.168.1.23:4000”

    int nSendCount=m_peer.send(buf,sizeof(MESSAGE),tcAddr); //发送消息

    return nSendCount;

    }

    int CTcCommunicator::ReceiveMessage()
    {
    return 0;
    }

    使用:

    template <typename CONTAINER>
    bool CHiAtmpVolumeTask::SendMsg(const CONTAINER& container, MSG msgType, const string& strRemoteIp)
    {

    CTcCommunicator tcCommunicator;
    MESSAGE msg;
    memset(&msg, 0, sizeof(MESSAGE));
    msg.msg_header.nMsgType = msgType;

    bool bRet = true;

    CONTAINER::const_iterator iter = container.begin();
    for(; iter != container.end(); iter++)
    {
    memset(msg.msg_body.bDataBuf, 0, sizeof(msg.msg_body.bDataBuf));
    memcpy(msg.msg_body.bDataBuf, &(*iter), sizeof(*iter));
    int nSendCount = tcCommunicator.SendMessage(msg, strRemoteIp);
    if (nSendCount != -1)
    {
    ACE_OS::sleep(ACE_Time_Value(0,20000));  

    }
    else
    {
    bRet = false;

    }

    }

     return bRet;

    }

    二、接收端:

    下面的代码并不好,没有封装成类。

    接收端应该也像发送端一样封装成类,将

    //ACE_INET_Addr port_to_listen(4000); //绑定的端口
    //ACE_SOCK_Dgram peer(port_to_listen); //通信通道

    定义为成员变量,在构造函数中初始化。

    int CCommunication::ReceiveMsg(MESSAGE& msg, const ACE_SOCK_Dgram& peer)
    {

    //ACE_INET_Addr port_to_listen(4000); //绑定的端口
    //ACE_SOCK_Dgram peer(port_to_listen); //通信通道

    char buf[2048];
    ACE_INET_Addr remoteAddr; //远程地址

    memset(buf,0,sizeof(buf));
    //int nReceiveCount = peer.recv(buf,2048,remoteAddr); //接收消息,获取远程地址信息
    //int nReceiveCount=peer.recv(buf,2048,remoteAddr,0,&ACE_Time_Value(nServerOutTime));
    int nReceiveCount=peer.recv(buf,2048,remoteAddr,0,&ACE_Time_Value(0));

    if (nReceiveCount <= 0)
    {
    memset(&msg,0,sizeof(MESSAGE));

    //原路发送应答消息

    memcpy(buf,&answerMsg,sizeof(MESSAGE));
    peer.send(buf,sizeof(MESSAGE),remoteAddr);


    }

    memcpy(&msg,buf,sizeof(MESSAGE));

    return nReceiveCount;


    }

    使用:

    在一个线程函数中,不断接收数据。

    DWORD WINAPI CSSDlg::ReceiveBPMsgFunc( void* pParam )

    {

    CSSDlg* pDlg = (CDlg*)pParam;
    HANDLE hEvent = pDlg->GetEventHandle();
    CRITICAL_SECTION hcs = pDlg->GetCriticalSection();

    ACE_INET_Addr port_to_listen(4000); //绑定的端口
    ACE_SOCK_Dgram peer(port_to_listen); //通信通道

    MESSAGE recvMsg; //收到的消息

    while (TRUE)
    {

    int nReceiveCount = theApp.m_Comm.ReceiveMsgFromServer(recvMsg, peer);
    if (nReceiveCount != -1)
    {
    ACE_OS::sleep(ACE_Time_Value(0,10000));

    switch(recvMsg.msg_header.nMsgType)
    {
    case OUT:
    {
    ORDER stOrder;
    memset(&stOrder, 0, sizeof(ORDER));
    memcpy(&stOrder, recvMsg.msg_body.bDataBuf, sizeof(recvMsg.msg_body.bDataBuf));

    EnterCriticalSection(&hcs);

    do something;

    LeaveCriticalSection(&hcs);

    break;
    }


    default:
    break;

    }

    }

    if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0))
    {
    break;
    }

    }

    return 0;

    }

    三、线程

    头文件中的定义:

    HANDLE m_hThread;   //m_hThread 初始化为 INVALID_HANDLE_VALUE
    HANDLE m_hEvent;
    CRITICAL_SECTION m_csOrderCode;

    BOOL BeginReceiveMsgThread();
    void EndReceiveMsgThread();
    static DWORD WINAPI ReceiveBPMsgFunc(void* pParam);

    源文件:

    BOOL CSSDlg::BeginReceiveMsgThread()
    {
    /** 检测线程是否已经开启了 */
    if (m_hThread != INVALID_HANDLE_VALUE)
    {
    /** 线程已经开启 */
    return false;
    }

    //m_bExitThread = false;

    //自动置位(第二个参数), 第三个参数:true表示已触发,false未触发
    m_hEvent = CreateEvent (NULL,FALSE,FALSE,NULL); // 初始值为 nonsignaled ,并且每次触发后自动设置为nonsignaled
    InitializeCriticalSection(&m_csOrderCode);

    m_hThread = CreateThread(NULL,0, &CSSDlg::ReceiveBPMsgFunc, this, 0, NULL);

    if (!m_hThread)
    {
    return false;
    }
    /** 设置线程的优先级,高于普通线程 */
    /*if (!SetThreadPriority(m_hThread, THREAD_PRIORITY_ABOVE_NORMAL))
    {
    return false;
    }
    */
    return true;

    }

    void CSSDlg::EndReceiveMsgThread()
    {
    SetEvent(m_hEvent); //触发事件,设置为有信号状态,此时WaitForSingleObject返回WAIT_OBJECT_0,线程循环退出
    Sleep(10);
    DeleteCriticalSection(&m_csOrderCode);
    CloseHandle(m_hEvent);
    }

    另外WaitForSingleObject可以作为循环条件:

    while (WAIT_OBJECT_0 != WaitForSingleObject(hEvent, 1000))  //每隔1000毫秒读一次数据

    while (WAIT_OBJECT_0 != WaitForSingleObject(hEvent, 1))  //每隔1000毫秒读一次数据

  • 相关阅读:
    Android sensor 系统框架 (一)
    enc28j60网卡驱动模块添加进linux内核,Kconfig,Makefile配置过程
    Linux samba服务器配置
    为群晖加把锁:使用ssh密钥保障数据安全
    浦发银行网上银行U盾证书无法更新的解决办法
    克隆Linux系统的网卡设置
    Linux路由:CentOS6的多种玩法
    专心学LINUX:CentOS关闭屏幕自动锁定和睡眠
    群晖:关闭软路由利用双网卡桥接直连电脑上网
    Ceph之二----部署Ceph集群
  • 原文地址:https://www.cnblogs.com/nanzhi/p/8416768.html
Copyright © 2011-2022 走看看