基于请求代理的中间件模型

 对象请求代理体系结构是一种崭新的技术,它以CORBA为代表。在这里,我们实现了一个基于请求代理体系结构的简单模型,藉此说明中间件的工作原理。

  系统由三个模块组成:客户端、服务器和代理。即Client,Server和Agent。实现方法是使用Winsock编程技术(有关Winsock编程的技术可以参考相关文献),编程环境是VC++6.0。

  首先作如下定义:

  #define DataLength 80 file://定义数据长度

  #define AgentPort 14000//定义代理的端口号

  #define DefaultClientPort 12000//定义客户端的端口号

  #define DefaultServerPort 13000//定义服务器的端口号

  系统工作原理如下是:客户端、服务器和代理各有一个独立的IP地址和端口号(IP地址和端口号的组合可以确定客户端程序、服务程序和代理服务器的通信地址)。我们要实现的是客户端和服务器之间的信息交互,但是现在面临这样的问题:客户端和服务器的地址以及端口都是可变的,它们并不固定,因此在信息交互之前,客户端无法知道服务器的地址,服务器也并不知道客户端的地址。唯一确定的是代理服务器程序的IP地址和端口号,它是不变的。

  系统实现的方式如下:客户端启动时首先向代理服务器注册自己的信息,主要是自己的IP地址和端口号,如果此时服务器已经注册,则代理服务器将服务器的地址信息传递给客户端,否则客户端等待。(系统工作原理如下图所示)



  服务器启动时也首先向代理服务器注册自己的信息,如果此时客户端已经注册,则代理服务器将客户端的地址信息传递给服务器(很多情况下并不需要这样的操作,因为总是客户端向服务器发送请求服务的信号)。

  客户端得到服务器的地址信息之后,就可以直接和服务器进行交互,这样,代理服务器就可以退出系统,甚至关掉。这是在CORBA中比较典型的一种代理方式。

  在另外一种情况下:如果希望服务器能够在不影响客户端程序的前提下随时扩展,那么可以要求客户端程序在发送服务请求时,直接发给代理服务器,然后由代理服务器进行一定的权限审查,然后转发给服务器。服务器返回的结果也由代理服务器转发给客户端。这是目前常见的WWW代理服务器的一般工作方式。在这样的情况下,本例也是可以适应的,只要在程序中加以限制即可。

本例的关键代码如下:

  代理服务器:

  初始化处理:

  BOOL CAgent_ZhyDlg::OnInitDialog()

  {

   CDialog::OnInitDialog();

   // Add "About..." menu item to system menu.

   // IDM_ABOUTBOX must be in the system command range.

   ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

   ASSERT(IDM_ABOUTBOX < 0xF000);

   CMenu* pSysMenu = GetSystemMenu(FALSE);

   if (pSysMenu != NULL)

    {

     CString strAboutMenu;

     strAboutMenu.LoadString(IDS_ABOUTBOX);

     if (!strAboutMenu.IsEmpty())

     {

      pSysMenu->AppendMenu(MF_SEPARATOR);

      pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

     }

    }

   // Set the icon for this dialog. The framework does this automatically

   // when the application's main window is not a dialog

   SetIcon(m_hIcon, TRUE); // Set big icon

   SetIcon(m_hIcon, FALSE); // Set small icon

   // TODO: Add extra initialization here

   COleVariant LocalPort,LocalIPAddress;

   LocalPort.vt=VT_I2;

   LocalPort.intVal=AgentPort;

   LocalIPAddress.vt=VT_BSTR;

   file://LocalIPAddress.bstrVal=SysAllocString(L"90.0.0.111");

   LocalIPAddress=m_ReceiveSocket.GetLocalIP();

   m_ReceiveSocket.SetProtocol(1);

   m_ReceiveSocket.Bind(LocalPort,LocalIPAddress);

   Socket_ID=m_ReceiveSocket.GetSocketHandle();

   if(Socket_ID==INVALID_SOCKET)

    {

      AfxMessageBox("Invalid socket!");

    }

   LocalHostName=m_ReceiveSocket.GetLocalHostName();

   HasGotServerAddress=FALSE;

   HasGotClientAddress=FALSE;

   ServerIPAddressAsString="";

   ClientIPAddressAsstring="";

   ServerPortAsstring="";

   ClientPortAsstring="";

   return TRUE; // return TRUE unless you set the focus to a control

  }

  接收到数据报(使用UDP协议)

  void CAgent_ZhyDlg::OnDataArrivalWinsock1(long bytesTotal)

   {

    if (!HasStopped)

     {

       // TODO: Add your control notification handler code here

       char FAR * buf;int length; char SourceAddress[20];

       Socket_ID=m_ReceiveSocket.GetSocketHandle();

       buf=( char FAR *)malloc(80);

       sockaddr_in srcsockaddr,tempsock;

       length=sizeof(sockaddr);

       int ReceivedNumber=recvfrom(Socket_ID,(char *)buf,80,0,(sockaddr *)&srcsockaddr,&length);

       if (ReceivedNumber>=1)

        {

          buf[ReceivedNumber]=0;

         }

       memcpy((void *)&tempsock,(void *)&srcsockaddr,sizeof(sockaddr));

       length=sizeof(sockaddr);

       strcpy(SourceAddress,inet_ntoa(tempsock.sin_addr));

       CString SourcePortAsstring,BytesTotalAsString;

       SourcePortAsstring.Format("%d",ntohs(tempsock.sin_port));

       BytesTotalAsString.Format("%d",bytesTotal);

       if (ntohs(tempsock.sin_port)==DefaultClientPort) file://Client information

        {

          HasGotClientAddress=TRUE;

         ClientPortAsstring=SourcePortAsstring;

         ClientIPAddressAsstring=SourceAddress;

         }//数据包源地址之端口号和客户端缺省端口相符,取得客户端地址

       if (ntohs(tempsock.sin_port)==DefaultServerPort) // Server information

        {

         HasGotServerAddress=TRUE;

         ServerPortAsstring=SourcePortAsstring;

         ServerIPAddressAsString=SourceAddress;

        }//数据包源地址之端口号和服务器缺省端口相符,取得服务器端地址

       m_Edit=m_Edit+"Message from : "+SourceAddress+" Port: "+SourcePortAsstring+" BytesTotal : "+BytesTotalAsString+"/r/n"+"Message : "+buf+"/r/n/r/n";//将收到的信息显示出来

       free(buf);

       UpdateData(FALSE);

      }

     }

  将客户端地址发送给服务器:

   void CAgent_ZhyDlg::OnBUTTONSendToServer()

    {

     // TODO: Add your control notification handler code here

     file://send client information to server

     if (HasGotClientAddress)

      {
     
       if (HasGotServerAddress)

        {

         Socket_ID=m_ReceiveSocket.GetSocketHandle();

         if(Socket_ID==INVALID_SOCKET)

          {

            AfxMessageBox("Illegal Socket ID");

            closesocket(Socket_ID);

           }

         LPHOSTENT hp;

         hp=gethostbyname(LocalHostName);

         if(hp==0)

          {

            AfxMessageBox("Illegal agent name");


            closesocket(Socket_ID);


           }

          SOCKADDR_IN m_sockAddr,DestinationAddress;

          memcpy(&m_sockAddr.sin_addr,(char FAR*)hp->h_addr,hp->h_length);

          char FAR * Send_Buffer;

          int bufferLength;

          Send_Buffer=( char FAR *)malloc(100);

          strcpy(Send_Buffer,"ClientIP: "+ClientIPAddressAsstring+"/r/nClientPort: "+ClientPortAsstring);

          bufferLength=strlen(Send_Buffer);

          m_sockAddr.sin_family=AF_INET;

          m_sockAddr.sin_port=htons(AgentPort);

          DestinationAddress.sin_addr.S_un.S_addr=inet_addr(ServerIPAddressAsString);

          DestinationAddress.sin_family=AF_INET;

          DestinationAddress.sin_port=htons(DefaultServerPort);

          sendto(Socket_ID,Send_Buffer,bufferLength,0,

          (struct sockaddr FAR *)&DestinationAddress,

          sizeof(DestinationAddress));

          file://发送到目标地址

          AfxMessageBox("Information of client's IP address & port available,/r/n successfully sent to server!");

          }else {

            AfxMessageBox("None information of server's IP address & port available,/r/n Can not send client information!");}

          }else {AfxMessageBox("None information of client's IP address & port available,/r/n Can not send to server!");}

         }

  将服务器地址发送给客户端

   void CAgent_ZhyDlg::OnBUTTONSendToClient()

    {

      // TODO: Add your control notification handler code here

      file://send server infomation to client

      if (HasGotServerAddress)

       {

        if (HasGotClientAddress)

        {

         Socket_ID=m_ReceiveSocket.GetSocketHandle();

         if(Socket_ID==INVALID_SOCKET)

          {

           AfxMessageBox("Illegal Socket ID");

           closesocket(Socket_ID); }

         LPHOSTENT hp;

         hp=gethostbyname(LocalHostName);

         if(hp==0)

          {

           AfxMessageBox("Illegal agent name");

           closesocket(Socket_ID);

          }

         SOCKADDR_IN m_sockAddr,DestinationAddress;

         memcpy(&m_sockAddr.sin_addr,(char FAR*)hp->h_addr,hp->h_length);

         char FAR * Send_Buffer;

         int bufferLength;

         Send_Buffer=( char FAR *)malloc(100);

         strcpy(Send_Buffer,"ServerIP: "+ServerIPAddressAsString+"/r/nServerPort: "+ServerPortAsstring);

         bufferLength=strlen(Send_Buffer);

         m_sockAddr.sin_family=AF_INET;

         m_sockAddr.sin_port=htons(AgentPort);

         DestinationAddress.sin_addr.S_un.S_addr=inet_addr(ClientIPAddressAsstring);

         DestinationAddress.sin_family=AF_INET;

         DestinationAddress.sin_port=htons(DefaultClientPort);

         sendto(Socket_ID,Send_Buffer,bufferLength,0,

         (struct sockaddr FAR *)&DestinationAddress,

         sizeof(DestinationAddress)); file://send server's ip & port information to client

         AfxMessageBox("Information of server's IP address & port available,/r/n successfully sent to client!");

         }else {

           AfxMessageBox("None information of client's IP address & port available,/r/n Can not send server information!");}

         }else {
           AfxMessageBox("None information of server's IP address & port available,/r/n Can not send to client!");}

         }

  以上是代理服务器的一些关键代码,这些代码已经经过调试通过,感兴趣的朋友可以直接使用。另外客户端和服务器端的处理方式和代理服务器类似,不过稍微简化一些。可以参考代理服务器的代码实现客户端和服务器的代码,在此不作赘述。

  以上实现的就是目前比较先进的请求-代理体系结构的基本模型,它是一种基于ORB的中间件模型。采用的实现手段是基于Winsock的网络编程技术。当然这仅仅是一个简单的模型,它远远没有达到实用化的程度。然而重要的不是实现,而是这种思想。大家只要了解和把握了这种思想,也就掌握了中间件技术的基本思想。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值