MFC 油槽 一对多通信的实现

     因为油槽是基于广播的,服务器端做为接受点,客户端做为发送端;

     使用油槽实现进程间的通信。

     1. 服务器端创建油槽    重点字串说明  服务器和客户端

     HANDLE hMailslot=CreateMailslot(".//mailslot//mailslot",0,MAILSLOT_WAIT_FOREVER,NULL);
     if(INVALID_HANDLE_VALUE==hMailslot)
     {
        MessageBox("创建油槽失败!");
        return;
     }

     相当于是建立了一个新的文件,文件的地址是//./mailslot/mailslot :

    A:解释"/"是提示转义字符,后面一个/是需要的/反斜杠;

       所以字符串中“//”表示的是一个/;

    B:第一个mailslot表明是建立的一个油槽;  第二个是油槽的名字,可以自己选定;

    C:// ./Mailslot/name                       标定同一台机器上的一个本地邮槽
         //servername/Mailslot/name      标定名为servername的一个远程邮槽服务器
         // domainname/Mailslot/name    标定在指定的domain(域)内,使用特定name(名字)的所有邮槽
         //*/Mailslot/name                       标定系统主域内,标定特定name(名字)的所有邮槽


      实验证明 实验证明 : 同一个机器上.//很好通信;

     当访问远程,同一个局域网的计算机比如:  客户端:打开CreateFile(que//mailsot//mailsot",...:);

                                                               服务器:创建CReateMailslot(".//mailslot//mailslot");

      实验证明   主题的思想就是 服务器端 创建油槽;并且只有服务器端能够从这个油槽文件读出数据;

                     客户端 打开【创建好】的油槽文件,并且向里面写入数据。 从而油槽文件可以在服务器上被读出来;

     一句话,服务器创建文件,客户机打开并写入,服务器一直等着,然后读取出数据;

     而所谓的一对多的通信,重点就在C:.//mailslot//mailslot  中第一个参数的指定打开File的范围上;本文档的写入,都是用事实和实验来说明的;

 

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

 

 

 

 

     MFC实例   一对多的油槽通信

    服务器端:  在一个Dialog的类中,一个BUNTTON 按钮,一个编辑框用于显示广播,添加BUTTON的Class组建,建立On_btnclicked

    创建一个油槽;并且在一个死循环里,读出数据,并且把数据封装成WM_RECVDATA消息 ;  添加消息响应函数OnRecvData(WPARAM ,LPARAM),  在消息响应里面,把收到的数据显示在编辑框里;

    客户端:    也是在一个Dialog类,先打开服务器创建的油槽文件,然后向里面写入数据。从一个编辑框里面读入数据,然后用写文件的函数,写入;可以把历史的消息都显示到一个编辑框里。

 

      这个就是整个程序的思路.

      下面可以贴一下重点代码:


void CMSDlg::OnBtnRecv()        实验证明 重点1    //客户端 创建油槽。que是同一个局域网的主机名    网络上的待研究
{

HANDLE hMailslot=CreateFile("que//mailslot//mailslot",GENERIC_WRITE,
         FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

      if(INVALID_HANDLE_VALUE==hMailslot)
      {
          MessageBox("打開油槽失敗!");
          return;
      }

    CString strTime;                                       //时间的处理;
    CTime time = CTime::GetCurrentTime();  //得到一个当前时间;
    strTime=time.Format("%H:%M:%S");     //格式化为 20:30:10 小时:分钟:秒

/* CString strSend;
    CString strTemp;
    GetDlgItemText(IDC_EDIT_SEND,strSend);       //从IDC_EDIT_SEND取出发送的数据;
    GetDlgItemText(IDC_EDIT_HIS,strTemp);
    strTemp+="/r/n";
    strTemp+=strTime;                                           //将当前时间和发送的数据都显示到IDC_EDIT_HIS
    strTemp+="/r/n";
    strTemp+="cc:";
    strTemp+=strSend;*/                                      
   
    SetDlgItemText(IDC_EDIT_SEND,"");               //清空发送数据的编辑框
    SetDlgItemText(IDC_EDIT_HIS,strTemp);        //将历史消息都显示到IDC_EDIT_HIS编辑框

    strSend+="cc  廣播:";
   
    DWORD dwWrite;
    if(!WriteFile(hMailslot,strSend,strSend.GetLength()+1,&dwWrite,NULL))
    {
        MessageBox("写入失败!");
        CloseHandle(hMailslot);
        return;                                                      实验证明   重点2://写入数据到服务器的油槽。
    }

  
     CloseHandle(hMailslot);

}

==================================================================================

 

   服务器端    要先创建好油槽 才打开客户端

void CMSDlg::OnBtnRecv()
{
    // TODO: Add your control notification handler code here

                                                                实验证明   重点1: //创建油槽,注意此处为.表示是本地主机
    HANDLE hMailslot=CreateMailslot(".//mailslot//mailslot",0,
    MAILSLOT_WAIT_FOREVER,NULL);
    if(INVALID_HANDLE_VALUE==hMailslot)
    {
        MessageBox("创建油槽失败!");
        return;
    }


    char  buf[100];
    DWORD dwRead;
    int retval;
  while(TRUE)    重点2  //在一个死循环中,不断的读取数据到buf,并且封装成WM_RECVDATA,消息,而buf里的数据,被传到消息的
    {                             //LPARAM中。  可以在消息响应函数中通过形式参数,读到buf数据;

       retval=ReadFile(hMailslot,buf,100,&dwRead,NULL);
       if(!retval)
       {
        CloseHandle(hMailslot);
        MessageBox("读取数据失败!");
        break;   
       }
    
                                 实验证明    重点3 //形成用户自定义消息,设置消息参数;
    if(::PostMessage(m_hWnd,WM_RECVDATA,0,(LPARAM)buf))
    { 
        MessageBox("new message!");
    }
     
    }

    CloseHandle(hMailslot);

 

}

 

 

 

   顺便复习一下 利用自定义的消息 设定自定义的消息响应函数

A    在Dialog类的头文件上,#define WM_RECVDATA WM_USER+1 主要是使这个新的消息不会和别的消息重复了;

    在Dialog类的cpp文件中,在消息映射的宏定义里面

    BEGIN_MESSAGE_MAP(CMSDlg, CDialog)
    //{{AFX_MSG_MAP(CMSDlg)
    ON_WM_SYSCOMMAND()
    。。。。(省略一些通过类Classward添加的函数)

    //}}AFX_MSG_MAP

B   ON_MESSAGE(WM_RECVDATA,OnRecvData)                     / /这里添加自己的消息响应函数;
END_MESSAGE_MAP()

 

   在头文件中声明消息响应函数

   //{{AFX_MSG(CMSDlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnBtnRecv();
    afx_msg void OnBtnClose();
    //}}AFX_MSG
C    afx_msg void OnRecvData(WPARAM wparam,LPARAM lparam); 在头文件中声明消息响应函数

    DECLARE_MESSAGE_MAP()

 

 

 

 

 

到此  就完了 最后还做了下  Timer()

        自己简单的理解,就是SetTimer(1,2000,NULL),这个函数的作用,每隔一秒钟就是发射WM_timer 消息;

        然后,自己在ClassWard中,添加一个响应函数,ONTimer();

        因为每秒钟都会有函数响应,所以在做时间的时候,就可以每隔一秒,都会读出当前时间,看起来,就是秒数在动;

   所以实现这个时间动态显示的功能  先设定一个定时发射器,然后用on_timer()去读取当前时间,并且显示在对话框上;

   而SetTimer(1,2000,NULL) 1:是自己的发射器的编号,2000 是发射器的时间限制在2000ms;NULL是响应函数的地址,为空就是默认的On_timer();    而这个函数,放在对话框类的OnInitdialog()消息函数里面,就是窗口初始化的时候,就设定时间开始;

        然后

void CMSCDlg::OnTimer(UINT nIDEvent) //在这里可以拿到你SetTimer(1,。。,。。)第一个参数的ID;
{                                                                            //可以判断下是不是你设定的那个定时器;
    // TODO: Add your message handler code here and/or call default
 
     time = CTime::GetCurrentTime();
    SetDlgItemText(IDC_TIME,time.Format("%A, %B %d,%Y %H:%M:%S"));

    CDialog::OnTimer(nIDEvent);
}

 

 

  服务器端 客户端   多个服务器 使用*//mailslot//mailslot  实验就是能够广播

 

 

不过程序运行也是有一些问题。  在if(PostMessage())必须{实现MessageBox(“xxx”)函数} 不然死活都不会去调用相对应的消息响应函数 OnRecvData() ;  想要写一个线程函数,来发送读取的数据为消息;  也许能够解决这个问题,但是目前,觉得写到这里也行了,待进一步做~~

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值