织梦CMS - 轻松建站从此开始!

罗索

p2p打洞的功能封装(3)

jackyhwei 发布于 2011-08-08 09:34 点击:次 
#includestdafx.h #includeMySocket.h class CServerSocket: public CMySocket { public stUserListNodeGetUser( const char *userName); int Run(); private UserListm_userList; }; stUserListNode*CServerSocket:
TAG:

  • #include "stdafx.h"
  • #include "MySocket.h"
  • class CServerSocket : public CMySocket 
  • public
  •     stUserListNode GetUser(constchar* userName); 
  •     int Run(); 
  • private
  •     UserList m_userList; 
  • }; 
  •  
  • stUserListNode* CServerSocket::GetUser(constchar* userName) 
  •     for (UserList::iterator iter = m_userList; iter != m_userList.end(); ++iter) 
  •     { 
  •         if (strcmp((*iter)->userName, userName) == 0)
  •             return *iter; 
  •     } 
  •  
  •     throw Exception("not find this user"); 
  • int CServerSocket::Run() 
  •     try
  •     { 
  •         //InitWinSock();
  •          
  •         //SOCKET PrimaryUDP;
  •         m_socket = mksock(SOCK_DGRAM); 
  •  
  •         sockaddr_in local; 
  •         local.sin_family=AF_INET; 
  •         local.sin_port= htons(SERVER_PORT);  
  •         local.sin_addr.s_addr = htonl(INADDR_ANY); 
  •         int nResult=bind(m_socket,(sockaddr*)&local,sizeof(sockaddr)); 
  •         if(nResult == SOCKET_ERROR) 
  •             throw Exception("bind error"); 
  •  
  •         sockaddr_in sender; 
  •         stMessage recvbuf; 
  •         memset(&recvbuf,0,sizeof(stMessage)); 
  •  
  •         // 开始主循环.
  •         // 主循环负责下面几件事情:
  •         // 一:读取客户端登陆和登出消息,记录客户列表
  •         // 二:转发客户p2p请求
  •         for(;;) 
  •         { 
  •             int dwSender = sizeof(sender); 
  •             int ret = Recvfrom( (char *)&recvbuf, sizeof(stMessage)
  • , 0, (sockaddr *)&sender, &dwSender); 
  •             if(ret <= 0) 
  •             { 
  •                 printf("recv error"); 
  •                 continue
  •             } 
  •             else
  •             { 
  •                 int messageType = recvbuf.iMessageType; 
  •                 switch(messageType){/*处理收到的用户发来的消息*/
  •                 case LOGIN: 
  •                     { 
  • //  将这个用户的信息记录到用户列表中
  • printf("has a user login : %s\n", recvbuf.message.loginmember.userName); 
  • stUserListNode *currentuser = new stUserListNode(); 
  • strcpy(currentuser->userName, recvbuf.message.loginmember.userName); 
  • currentuser->ip = ntohl(sender.sin_addr.S_un.S_addr); 
  • currentuser->port = ntohs(sender.sin_port); 
  • ClientList.push_back(currentuser); 
  •  
  • // 把已经登陆的客户信息发送给新连的客户
  • int nodecount = (int)ClientList.size(); 
  • Sendto((constchar*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender
  • sizeof(sender)); 
  •  
  • for(UserList::iterator UserIterator=ClientList.begin(); 
  • UserIterator!=ClientList.end(); 
  • ++UserIterator) 
  • Sendto((constchar*)(*UserIterator), sizeof(stUserListNode), 0
  • , (const sockaddr*)&sender, sizeof(sender));  
  •  
  •                         break
  •                     } 
  •                 case LOGOUT: 
  •                     { 
  • // 将此客户信息删除
  • printf("has a user logout : %s\n", recvbuf.message.logoutmember.userName); 
  • UserList::iterator removeiterator = NULL; 
  • for(UserList::iterator UserIterator=ClientList.begin(); 
  • UserIterator!=ClientList.end(); ++UserIterator) 
  • if( strcmp( ((*UserIterator)->userName), recvbuf.message.logoutmember.userName) == 0 ) 
  • removeiterator = UserIterator; 
  • break
  • if(removeiterator != NULL) 
  • ClientList.remove(*removeiterator); 
  •                         break
  •                     } 
  •                 case P2PTRANS: 
  •                     { 
  • // 某个客户希望服务端向另外一个客户发送一个打洞消息
  • printf("%s wants to p2p %s\n",inet_ntoa(sender.sin_addr)
  • ,recvbuf.message.translatemessage.userName); 
  •  
  • stUserListNode node = GetUser(recvbuf.message.translatemessage.userName);//"TO"
  • sockaddr_in remote; 
  • remote.sin_family=AF_INET; 
  • remote.sin_port= htons(node.port);  
  • remote.sin_addr.s_addr = htonl(node.ip); 
  • in_addr tmp; 
  • tmp.S_un.S_addr = htonl(node.ip); 
  • printf("the address is %s,and port is %d\n",inet_ntoa(tmp), node.port); 
  • stP2PMessage transMessage; 
  • transMessage.iMessageType = P2PSOMEONEWANTTOCALLYOU; 
  • transMessage.iStringLen = ntohl(sender.sin_addr.S_un.S_addr); 
  • transMessage.Port = ntohs(sender.sin_port); 
  •                          
  • Sendto((constchar*)&transMessage, sizeof(transMessage), 0
  • , (const sockaddr *)&remote, sizeof(remote)); 
  •  
  •                         break
  •                     }
  •                 case GETALLUSER: 
  •                     { 
  • int command = GETALLUSER; 
  • Sendto((constchar*)&command, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender)); 
  • int nodecount = (int)ClientList.size(); 
  • Sendto((constchar*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender)); 
  • for(UserList::iterator UserIterator=ClientList.begin(); 
  • UserIterator!=ClientList.end(); 
  • ++UserIterator) 
  • Sendto((constchar*)(*UserIterator), sizeof(stUserListNode), 0
  • , (const sockaddr*)&sender, sizeof(sender));  
  •                         break
  •                     } 
  •                 } 
  •             } 
  •         } 
  •     } 
  •     catch(Exception &e) 
  •     { 
  •         printf(e.GetMessage()); 
  •         return 1; 
  •     } 
  •  
  •     return 0; 
  • #ifndef _MESSAGE_H_
  • #define _MESSAGE_H_
  •  
  • #include <list>
  • usingnamespace std; 
  • enum MSG_TYPE 
  •     /*控制消息*/
  •     LOGIN_MSG, 
  •     LOGOUT_MSG, 
  •     P2PTRANS_MSG, 
  •     GETUSER_MSG, 
  •     /*数据消息*/
  •     DATA_MSG 
  • }; 
  •  
  • struct stLoginMessage 
  •     char userName[10]; 
  •     char password[10]; 
  • }; 
  • // Client注销时发送的消息
  • struct stLogoutMessage 
  •     char userName[10]; 
  • }; 
  • // Client向服务器请求另外一个Client(userName)向自己方向发送UDP打洞消息
  • struct stP2PTranslate 
  •     char userName[10]; 
  • }; 
  • // 客户节点信息
  • struct stUserListNode 
  •     char userName[10]; 
  •     unsigned int ip; 
  •     unsigned short port; 
  • }; 
  • union MSG_BODY 
  •     stLoginMessage loginmember; 
  •     stLogoutMessage logoutmember; 
  •     stP2PTranslate translatemessage; 
  •     stUserListNode user; 
  • }; 
  • struct stMessage 
  •     MSG_TYPE msgType; 
  •     MSG_BODY msgBody; 
  • }; 
  • //======================================
  • // 下面的协议用于客户端之间的通信
  • //======================================
  • #define P2PMESSAGE 100               // 发送消息
  • #define P2PMESSAGEACK 101            // 收到消息的应答
  • #define P2PSOMEONEWANTTOCALLYOU 102  // 服务器向客户端发送的消息
  •                                      // 希望此客户端发送一个UDP打洞包
  • #define P2PTRASH        103          // 客户端发送的打洞包,接收端应该忽略此消息
  •  
  • // 客户端之间发送消息格式
  • struct stP2PMessage 
  •     int iMessageType; 
  •     int iStringLen;         // or IP address
  •     unsigned short Port;  
  • }; 
  • (shuizhiyun)
  • 本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201106/14567.html]
    本文出处:CSDN博客 作者:shuizhiyun
    顶一下
    (0)
    0%
    踩一下
    (0)
    0%
    ------分隔线----------------------------
    发表评论
    请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
    评价:
    表情:
    用户名: 验证码:点击我更换图片
    栏目列表
    将本文分享到微信
    织梦二维码生成器
    推荐内容