pta程序设计平台丹东seo优化

web/2025/10/4 16:03:55/文章来源:
pta程序设计平台,丹东seo优化,商丘seo外包,国外最新创意产品网站有哪些方面NAT(Network AddressTranslators)#xff0c;网络地址转换#xff1a; 网络地址转换是在IP地址日益缺乏的情况下产生的#xff0c;它的主要目的就是为了能够地址重用。NAT分为两大类#xff0c;基本的NAT和NAPT(Network Address/Port Translator)。 最开始NAT是运行在路由器… NAT(Network AddressTranslators)网络地址转换    网络地址转换是在IP地址日益缺乏的情况下产生的它的主要目的就是为了能够地址重用。NAT分为两大类基本的NAT和NAPT(Network Address/Port Translator)。 最开始NAT是运行在路由器上的一个功能模块。      最先提出的是基本的NAT它的产生基于如下事实一个私有网络域中的节点中只有很少的节点需要与外网连接呵呵这是在上世纪90年代中期提出的。那么这个子网中其实只有少数的节点需要全球唯一的IP地址其他的节点的IP地址应该是可以重用的。    因此基本的NAT实现的功能很简单在子网内使用一个保留的IP子网段这些IP对外是不可见的。子网内只有少数一些IP地址可以对应到真正全球唯一的IP地址。如果这些节点需要访问外部网络那么基本NAT就负责将这个节点的子网内IP转化为一个全球唯一的IP然后发送出去。(基本的NAT会改变IP包中的原IP地址但是不会改变IP包中的端口)    关于基本的NAT可以参看RFC 1631        另外一种NAT叫做NAPT从名称上我们也可以看得出NAPT不但会改变经过这个NAT设备的IP数据报的IP地址还会改变IP数据报的TCP/UDP端口。基本NAT的设备可能我们见的不多呵呵我没有见到过NAPT才是我们真正讨论的主角。看下图                                ServerS1                                                 18.181.0.31:1235                                                               |          ^  Session 1 (A-S1) ^     |           |  18.181.0.31:1235 |     |            v 155.99.25.11:62000v     |                                         |                                     NAT                                 155.99.25.11                                      |          ^  Session 1 (A-S1) ^     |           |  18.181.0.31:1235 |     |           v  10.0.0.1:1234   v     |                                       |                                   Client A                                10.0.0.1:1234    有一个私有网络10.*.*.*ClientA是其中的一台计算机这个网络的网关一个NAT设备的外网IP是155.99.25.11(应该还有一个内网的IP地址比如10.0.0.10)。如果Client A中的某个进程这个进程创建了一个UDPSocket,这个Socket绑定1234端口想访问外网主机18.181.0.31的1235端口那么当数据包通过NAT时会发生什么事情呢    首先NAT会改变这个数据包的原IP地址改为155.99.25.11。接着NAT会为这个传输创建一个SessionSession是一个抽象的概念如果是TCP也许Session是由一个SYN包开始以一个FIN包结束。而UDP呢以这个IP的这个端口的第一个UDP开始结束呢呵呵也许是几分钟也许是几小时这要看具体的实现了并且给这个Session分配一个端口比如62000然后改变这个数据包的源端口为62000。所以本来是10.0.0.1:1234-18.181.0.31:1235的数据包到了互联网上变为了155.99.25.11:62000-18.181.0.31:1235。    一旦NAT创建了一个Session后NAT会记住62000端口对应的是10.0.0.1的1234端口以后从18.181.0.31发送到62000端口的数据会被NAT自动的转发到10.0.0.1上。注意这里是说18.181.0.31发送到62000端口的数据会被转发其他的IP发送到这个端口的数据将被NAT抛弃这样Client A就与Server S1建立以了一个连接。    下面是关键的部分了。    看看下面的情况     ServerS1                                    Server S2  18.181.0.31:1235                             138.76.29.7:1235        |                                            |        |                                            |        --------------------------------------------                               |    ^  Session 1(A-S1) ^     |     ^  Session 2 (A-S2)  ^    | 18.181.0.31:1235 |     |     |  138.76.29.7:1235  |    v 155.99.25.11:62000v     |     v 155.99.25.11:62000 v                               |                            Cone NAT                          155.99.25.11                               |    ^  Session 1(A-S1) ^     |     ^  Session 2 (A-S2)  ^    | 18.181.0.31:1235 |     |     |  138.76.29.7:1235  |   v  10.0.0.1:1234   v     |     v  10.0.0.1:1234   v                               |                            Client A                         10.0.0.1:1234    接上面的例子如果Client A的原来那个Socket(绑定了1234端口的那个UDP Socket)又接着向另外一个ServerS2发送了一个UDP包那么这个UDP包在通过NAT时会怎么样呢    这时可能会有两种情况发生一种是NAT再次创建一个Session并且再次为这个Session分配一个端口号比如62001。另外一种是NAT再次创建一个Session但是不会新分配一个端口号而是用原来分配的端口号62000。前一种NAT叫做SymmetricNAT后一种叫做ConeNAT。我们期望我们的NAT是第二种呵呵如果你的NAT刚好是第一种那么很可能会有很多P2P软件失灵。可以庆幸的是现在绝大多数的NAT属于后者即Cone NAT       好了我们看到通过NAT,子网内的计算机向外连结是很容易的NAT相当于透明的子网内的和外网的计算机不用知道NAT的情况。    但是如果外部的计算机想访问子网内的计算机就比较困难了而这正是P2P所需要的。    那么我们如果想从外部发送一个数据报给内网的计算机有什么办法呢首先我们必须在内网的NAT上打上一个“洞”也就是前面我们说的在NAT上建立一个Session这个洞不能由外部来打只能由内网内的主机来打。而且这个洞是有方向的比如从内部某台主机比如192.168.0.10向外部的某个IP(比如219.237.60.1)发送一个UDP包那么就在这个内网的NAT设备上打了一个方向为219.237.60.1的“洞”这就是称为UDP HolePunching的技术以后219.237.60.1就可以通过这个洞与内网的192.168.0.10联系了。但是其他的IP不能利用这个洞。     正题P2P了。有了上面的理论实现两个内网的主机通讯就差最后一步了.    现在我们来看看一个P2P软件的流程以下图为例                       Server S 219.237.60.1                          |                          |   --------------------------------------------   |                                            |  NAT A(外网IP:202.187.45.3)                NAT B (外网IP:187.34.1.56)   |  (内网IP:192.168.0.1)                     | (内网IP:192.168.0.1)   |                                            | Client A (192.168.0.20:4000)            Client B (192.168.0.10:40000)     首先ClientA登录服务器NAT A为这次的Session分配了一个端口60000那么Server S收到的ClientA的地址是202.187.45.3:60000这就是Client A的外网地址了。同样Client B登录Server SNATB给此次Session分配的端口是40000那么Server S收到的B的地址是187.34.1.56:40000。     此时ClientA与Client B都可以与Server S通信了。如果Client A此时想直接发送信息给Client B那么他可以从ServerS那儿获得B的公网地址187.34.1.56:40000是不是Client A向这个地址发送信息ClientB就能收到了呢答案是不行因为如果这样发送信息NATB会将这个信息丢弃因为这样的信息是不请自来的为了安全大多数NAT都会执行丢弃动作。现在我们需要的是在NATB上打一个方向为202.187.45.3即Client A的外网地址的洞那么ClientA发送到187.34.1.56:40000的信息,Client B就能收到了。这个打洞命令由谁来发呢呵呵当然是ServerS。    总结一下这个过程如果Client A想向Client B发送信息那么Client A发送命令给Server S请求ServerS命令Client B向Client A方向打洞。呵呵是不是很绕口不过没关系想一想就很清楚了何况还有源代码呢然后ClientA就可以通过Client B的外网地址与Client B通信了。        注意以上过程只适合于Cone NAT的情况如果是Symmetric NAT那么当Client B向ClientA打洞的端口已经重新分配了Client B将无法知道这个端口如果SymmetricNAT的端口是顺序分配的那么我们或许可以猜测这个端口号可是由于可能导致失败的因素太多我们不推荐这种猜测端口的方法。        下面是一个模拟P2P聊天的过程的源代码过程很简单P2PServer运行在一个拥有公网IP的计算机上P2PClient运行在两个不同的NAT后注意如果两个客户端运行在一个NAT后本程序很可能不能运行正常这取决于你的NAT是否支持loopbacktranslation详见http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt当然此问题可以通过双方先尝试连接对方的内网IP来解决但是这个代码只是为了验证原理并没有处理这些问题后登录的计算机可以获得先登录计算机的用户名后登录的计算机通过send usernamemessage的格式来发送消息。如果发送成功说明你已取得了直接与对方连接的成功。    程序现在支持三个命令send , getu , exit         send格式sendusername message    功能发送信息给username        getu格式getu    功能获得当前服务器用户列表        exit格式exit    功能注销与服务器的连接服务器不会自动监测客户是否吊线            代码很短相信很容易懂如果有什么问题可以给我发邮件zhouhuis22sina.com 或者在CSDN上发送短消息。同时欢迎转发此文但希望保留作者版权8-。         最后感谢CSDN网友PiggyXP 和 Seilfer的测试帮助 P2PServer.c [codeC] #pragma comment(lib, ws2_32.lib) #include windows.h #include ..\proto.h #include ..\Exception.h UserList ClientList; void InitWinSock() {  WSADATA wsaData;  if (WSAStartup(MAKEWORD(2, 2),wsaData) ! 0)  {   printf(Windows sockets 2.2 startup);   throw Exception();  }  else{   printf(Using %s (Status: %s)\n,    wsaData.szDescription,wsaData.szSystemStatus);   printf(with API versions %d.%d to%d.%d\n\n,    LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion),    LOBYTE(wsaData.wHighVersion),HIBYTE(wsaData.wHighVersion));    } } SOCKET mksock(int type) {  SOCKET sock socket(AF_INET, type, 0);  if (sock 0)  {        printf(create socket error);   throw Exception();  }  return sock; } stUserListNode GetUser(char *username) {  for(UserList::iteratorUserIteratorClientList.begin();      UserIterator!ClientList.end();       UserIterator)  {   if( strcmp(((*UserIterator)-userName), username) 0 )    return *(*UserIterator);  }  throw Exception(not find this user); } int main(int argc, char* argv[]) {  try{   InitWinSock();     SOCKET PrimaryUDP;   PrimaryUDP mksock(SOCK_DGRAM);   sockaddr_in local;   local.sin_familyAF_INET;   local.sin_port htons(SERVER_PORT);   local.sin_addr.s_addr htonl(INADDR_ANY);   intnResultbind(PrimaryUDP,(sockaddr*)local,sizeof(sockaddr));   if(nResultSOCKET_ERROR)    throw Exception(binderror);   sockaddr_in sender;   stMessage recvbuf;  memset(recvbuf,0,sizeof(stMessage));   // 开始主循环.   // 主循环负责下面几件事情:   // 一:读取客户端登陆和登出消息,记录客户列表   // 二:转发客户p2p请求   for(;;)   {    int dwSender sizeof(sender);    int ret recvfrom(PrimaryUDP,(char *)recvbuf, sizeof(stMessage), 0, (sockaddr*)sender, dwSender);    if(ret 0)    {     printf(recverror);    continue;    }    else    {     intmessageType recvbuf.iMessageType;    switch(messageType){     caseLOGIN:     {      //  将这个用户的信息记录到用户列表中      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(PrimaryUDP, (const char*)nodecount,sizeof(int), 0, (const sockaddr*)sender,sizeof(sender));      for(UserList::iterator UserIteratorClientList.begin();        UserIterator!ClientList.end();        UserIterator)      {       sendto(PrimaryUDP, (const char*)(*UserIterator),sizeof(stUserListNode), 0, (constsockaddr*)sender, sizeof(sender));      }      break;     }     caseLOGOUT:     {      // 将此客户信息删除      printf(has a user logout : %s\n,recvbuf.message.logoutmember.userName);      UserList::iterator removeiterator NULL;      for(UserList::iterator UserIteratorClientList.begin();       UserIterator!ClientList.end();       UserIterator)      {       if( strcmp( ((*UserIterator)-userName),recvbuf.message.logoutmember.userName) 0 )       {        removeiterator UserIterator;        break;       }      }      if(removeiterator ! NULL)       ClientList.remove(*removeiterator);      break;     }     caseP2PTRANS:     {      // 某个客户希望服务端向另外一个客户发送一个打洞消息      printf(%s wants to p2p%s\n,inet_ntoa(sender.sin_addr),recvbuf.message.translatemessage.userName);      stUserListNode node GetUser(recvbuf.message.translatemessage.userName);      sockaddr_in remote;      remote.sin_familyAF_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(PrimaryUDP,(const char*)transMessage,sizeof(transMessage), 0, (const sockaddr *)remote,sizeof(remote));      break;     }         caseGETALLUSER:     {      int command GETALLUSER;      sendto(PrimaryUDP, (const char*)command,sizeof(int), 0, (const sockaddr*)sender,sizeof(sender));      int nodecount (int)ClientList.size();      sendto(PrimaryUDP, (const char*)nodecount,sizeof(int), 0, (const sockaddr*)sender,sizeof(sender));      for(UserList::iterator UserIteratorClientList.begin();        UserIterator!ClientList.end();        UserIterator)      {       sendto(PrimaryUDP, (const char*)(*UserIterator),sizeof(stUserListNode), 0, (constsockaddr*)sender, sizeof(sender));      }      break;     }     }    }   }  }  catch(Exception e)  {   printf(e.GetMessage());   return 1;  }  return 0; } #pragma comment(lib,ws2_32.lib) #include windows.h #include ..\proto.h #include ..\Exception.h #include iostream using namespace std; UserList ClientList;   #define COMMANDMAXC 256 #defineMAXRETRY   5 SOCKET PrimaryUDP; char UserName[10]; char ServerIP[20]; bool RecvedACK; void InitWinSock() {  WSADATA wsaData;  if (WSAStartup(MAKEWORD(2, 2),wsaData) ! 0)  {   printf(Windows sockets 2.2 startup);   throw Exception();  }  else{   printf(Using %s (Status: %s)\n,    wsaData.szDescription,wsaData.szSystemStatus);   printf(with API versions %d.%d to%d.%d\n\n,    LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion),    LOBYTE(wsaData.wHighVersion),HIBYTE(wsaData.wHighVersion));  } } SOCKET mksock(int type) {  SOCKET sock socket(AF_INET, type, 0);  if (sock 0)  {        printf(create socket error);   throw Exception();  }  return sock; } stUserListNode GetUser(char *username) {  for(UserList::iteratorUserIteratorClientList.begin();      UserIterator!ClientList.end();       UserIterator)  {   if( strcmp(((*UserIterator)-userName), username) 0 )    return *(*UserIterator);  }  throw Exception(not find this user); } void BindSock(SOCKET sock) {  sockaddr_in sin;  sin.sin_addr.S_un.S_addr INADDR_ANY;  sin.sin_family AF_INET;  sin.sin_port 0;    if (bind(sock, (structsockaddr*)sin, sizeof(sin)) 0)   throw Exception(bind error); } void ConnectToServer(SOCKET sock,char *username, char*serverip) {  sockaddr_in remote;  remote.sin_addr.S_un.S_addr inet_addr(serverip);  remote.sin_family AF_INET;  remote.sin_port htons(SERVER_PORT);    stMessage sendbuf;  sendbuf.iMessageType LOGIN;  strncpy(sendbuf.message.loginmember.userName,username, 10);  sendto(sock, (constchar*)sendbuf, sizeof(sendbuf), 0, (constsockaddr*)remote,sizeof(remote));  int usercount;  int fromlen sizeof(remote);  int iread recvfrom(sock, (char*)usercount, sizeof(int), 0, (sockaddr*)remote, fromlen);  if(iread0)  {   throw Exception(Login error\n);  }  // 登录到服务端后接收服务端发来的已经登录的用户的信息  coutHaveusercountusers logined server:endl;  for(int i 0;iusercount;i)  {   stUserListNode *node new stUserListNode;   recvfrom(sock, (char*)node,sizeof(stUserListNode), 0, (sockaddr *)remote,fromlen);   ClientList.push_back(node);  coutUsername:node-userNameendl;   in_addr tmp;   tmp.S_un.S_addr htonl(node-ip);  coutUserIP:inet_ntoa(tmp)endl;  coutUserPort:node-portendl;  coutendl;  } } void OutputUsage() {  coutYou caninput you command:\n   CommandType:\send\,\exit\,\getu\\n   Example : sendUsername Message\n           exit\n           getu\n   endl; } bool SendMessageTo(char *UserName, char *Message) {  char realmessage[256];  unsigned int UserIP;  unsigned short UserPort;  bool FindUser false;  for(UserList::iteratorUserIteratorClientList.begin();      UserIterator!ClientList.end();      UserIterator)  {   if( strcmp(((*UserIterator)-userName), UserName) 0 )   {    UserIP (*UserIterator)-ip;    UserPort (*UserIterator)-port;    FindUser true;   }  }  if(!FindUser)   return false;  strcpy(realmessage, Message);  for(int i0;iMAXRETRY;i)  {   RecvedACK false;   sockaddr_in remote;   remote.sin_addr.S_un.S_addr htonl(UserIP);   remote.sin_family AF_INET;   remote.sin_port htons(UserPort);   stP2PMessage MessageHead;   MessageHead.iMessageType P2PMESSAGE;   MessageHead.iStringLen (int)strlen(realmessage)1;   int isend sendto(PrimaryUDP, (const char*)MessageHead, sizeof(MessageHead), 0, (constsockaddr*)remote, sizeof(remote));   isend sendto(PrimaryUDP, (const char*)realmessage, MessageHead.iStringLen, 0, (constsockaddr*)remote, sizeof(remote));     // 等待接收线程将此标记修改   for(int j0;j10;j)   {    if(RecvedACK)     returntrue;    else    Sleep(300);   }   // 没有接收到目标主机的回应认为目标主机的端口映射没有   // 打开那么发送请求信息给服务器要服务器告诉目标主机   // 打开映射端口UDP打洞   sockaddr_in server;   server.sin_addr.S_un.S_addr inet_addr(ServerIP);   server.sin_family AF_INET;   server.sin_port htons(SERVER_PORT);     stMessage transMessage;   transMessage.iMessageType P2PTRANS;  strcpy(transMessage.message.translatemessage.userName,UserName);   sendto(PrimaryUDP, (constchar*)transMessage, sizeof(transMessage), 0,(const sockaddr*)server, sizeof(server));   Sleep(100);// 等待对方先发送信息。  }  return false; } // 解析命令暂时只有exit和send命令 // 新增getu命令获取当前服务器的所有用户 void ParseCommand(char * CommandLine) {  if(strlen(CommandLine)4)   return;  char Command[10];  strncpy(Command, CommandLine, 4);  Command[4]\0;  if(strcmp(Command,exit)0)  {   stMessage sendbuf;   sendbuf.iMessageType LOGOUT;   strncpy(sendbuf.message.logoutmember.userName,UserName, 10);   sockaddr_in server;   server.sin_addr.S_un.S_addr inet_addr(ServerIP);   server.sin_family AF_INET;   server.sin_port htons(SERVER_PORT);   sendto(PrimaryUDP,(constchar*)sendbuf, sizeof(sendbuf), 0, (const sockaddr*)server, sizeof(server));   shutdown(PrimaryUDP, 2);   closesocket(PrimaryUDP);   exit(0);  }  else if(strcmp(Command,send)0)  {   char sendname[20];   char message[COMMANDMAXC];   int i;   for(i5;;i)   {    if(CommandLine[i]! )    sendname[i-5]CommandLine[i];    else    {    sendname[i-5]\0;     break;    }   }   strcpy(message,(CommandLine[i1]));   if(SendMessageTo(sendname, message))    printf(Send OK!\n);   else    printf(SendFailure!\n);  }  else if(strcmp(Command,getu)0)  {   int command GETALLUSER;   sockaddr_in server;   server.sin_addr.S_un.S_addr inet_addr(ServerIP);   server.sin_family AF_INET;   server.sin_port htons(SERVER_PORT);   sendto(PrimaryUDP,(constchar*)command, sizeof(command), 0, (const sockaddr*)server, sizeof(server));  } } // 接受消息线程 DWORD WINAPI RecvThreadProc(LPVOID lpParameter) {  sockaddr_in remote;  int sinlen sizeof(remote);  stP2PMessage recvbuf;  for(;;)  {   int iread recvfrom(PrimaryUDP, (char*)recvbuf, sizeof(recvbuf), 0, (sockaddr*)remote, sinlen);   if(iread0)   {    printf(recv error\n);    continue;   }   switch(recvbuf.iMessageType)   {   case P2PMESSAGE:    {     //接收到P2P的消息     char*comemessage new char[recvbuf.iStringLen];     int iread1 recvfrom(PrimaryUDP, comemessage, 256, 0, (sockaddr*)remote, sinlen);    comemessage[iread1-1] \0;    if(iread10)     throw Exception(Recv Message Error\n);     else     {     printf(Recv a Message:%s\n,comemessage);          stP2PMessage sendbuf;     sendbuf.iMessageType P2PMESSAGEACK;     sendto(PrimaryUDP, (const char*)sendbuf,sizeof(sendbuf), 0, (const sockaddr*)remote,sizeof(remote));     }     delete[]comemessage;     break;    }   case P2PSOMEONEWANTTOCALLYOU:    {     //接收到打洞命令向指定的IP地址打洞     printf(Recvp2someonewanttocallyou data\n);     sockaddr_inremote;    remote.sin_addr.S_un.S_addr htonl(recvbuf.iStringLen);    remote.sin_family AF_INET;    remote.sin_port htons(recvbuf.Port);     // UDPhole punching     stP2PMessagemessage;    message.iMessageType P2PTRASH;    sendto(PrimaryUDP, (const char *)message,sizeof(message), 0, (const sockaddr*)remote,sizeof(remote));                     break;    }   case P2PMESSAGEACK:    {     //发送消息的应答     RecvedACK true;     break;    }   case P2PTRASH:    {     //对方发送的打洞消息忽略掉。     //do nothing...     printf(Recvp2ptrash data\n);     break;    }   case GETALLUSER:    {     intusercount;     int fromlen sizeof(remote);     int iread recvfrom(PrimaryUDP, (char *)usercount,sizeof(int), 0, (sockaddr *)remote,fromlen);    if(iread0)     {     throw Exception(Login error\n);     }        ClientList.clear();    coutHaveusercountusers logined server:endl;     for(int i 0;iusercount;i)     {     stUserListNode *node new stUserListNode;     recvfrom(PrimaryUDP, (char*)node, sizeof(stUserListNode), 0,(sockaddr *)remote,fromlen);     ClientList.push_back(node);     coutUsername:node-userNameendl;     in_addr tmp;     tmp.S_un.S_addr htonl(node-ip);     coutUserIP:inet_ntoa(tmp)endl;     coutUserPort:node-portendl;     coutendl;     }     break;    }   }  } } int main(int argc, char* argv[]) {  try  {   InitWinSock();     PrimaryUDP mksock(SOCK_DGRAM);   BindSock(PrimaryUDP);   coutPleaseinput server ip:;   cinServerIP;   coutPleaseinput your name:;   cinUserName;   ConnectToServer(PrimaryUDP, UserName,ServerIP);   HANDLE threadhandle CreateThread(NULL, 0,RecvThreadProc, NULL, NULL, NULL);   CloseHandle(threadhandle);   OutputUsage();   for(;;)   {    charCommand[COMMANDMAXC];    gets(Command);    ParseCommand(Command);   }  }  catch(Exception e)  {   printf(e.GetMessage());   return 1;  }  return 0; } #ifndef __HZH_Exception__ #define __HZH_Exception__ #define EXCEPTION_MESSAGE_MAXLEN 256 #include string.h class Exception { private:  charm_ExceptionMessage[EXCEPTION_MESSAGE_MAXLEN]; public:  Exception(char *msg)  {   strncpy(m_ExceptionMessage, msg,EXCEPTION_MESSAGE_MAXLEN);  }  char *GetMessage()  {   return m_ExceptionMessage;  } }; #endif #pragma once #include list // 定义iMessageType的值 #define LOGIN 1 #define LOGOUT 2 #define P2PTRANS 3 #define GETALLUSER  4 // 服务器端口 #define SERVER_PORT 2280 // Client登录时向服务器发送的消息 struct stLoginMessage {  char userName[10];  char password[10]; }; // Client注销时发送的消息 struct stLogoutMessage {  char userName[10]; }; // Client向服务器请求另外一个Client(userName)向自己方向发送UDP打洞消息 struct stP2PTranslate {  char userName[10]; }; // Client向服务器发送的消息格式 struct stMessage {  int iMessageType;  union _message  {   stLoginMessage loginmember;   stLogoutMessage logoutmember;   stP2PTranslate translatemessage;  }message; }; // 客户节点信息 struct stUserListNode {  char userName[10];  unsigned int ip;  unsigned short port; }; // Server向Client发送的消息 struct stServerToClient {  int iMessageType;  union _message  {   stUserListNode user;  }message; }; // // 下面的协议用于客户端之间的通信 // #define P2PMESSAGE100              // 发送消息 #define P2PMESSAGEACK101           // 收到消息的应答 #define P2PSOMEONEWANTTOCALLYOU 102  //服务器向客户端发送的消息                                     // 希望此客户端发送一个UDP打洞包 #defineP2PTRASH       103         // 客户端发送的打洞包接收端应该忽略此消息 // 客户端之间发送消息格式 struct stP2PMessage {  int iMessageType;  intiStringLen;        // or IP address  unsigned short Port; };[/code] using namespace std; typedef liststUserListNode *UserList;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/86860.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国建设银行的网站用户名是什么意思wordpress移动版插件

字典 1.字典的定义2.字典数据的获取3.字典的嵌套4.嵌套字典的内容获取5.字典的常用操作6.常用操作总结7.遍历字典8.练习 1.字典的定义 同样使用{},不过存储的元素是一个一个的:键值对,语法如下 # 定义字典字面量 {key:value,key:value,...,…

wdcp搭建网站教程柳州市城乡建设局网站

wipeRefreshLayout字面意思就是下拉刷新的布局,继承自ViewGroup,在support v4兼容包下,但必须把你的support library的版本升级到19.1。 提到下拉刷新大家一定对ActionBarPullToRefresh比较熟悉,而如今google推出了更官方的下拉刷新组件,这无疑是对开发者来说比较好的消…

网站建设方面的文章WordPress手机缩略图设置

这是称为“ Functional Java by Example”的系列文章的第3部分。 我在本系列的每个部分中发展的示例是某种“提要处理程序”,用于处理文档。 在前面的部分中,我从一些原始代码开始,并应用了一些重构来描述“什么”而不是“如何”。 为了帮助…

网站的建设及维护的费用医院网站建设与维护题库

fluorinefx C# 版的开源rtmp服务器 - [其它资源] 版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://25swf.blogbus.com/logs/28529745.html fluorinefx支持的 .net 框架集有 1.1 2.0 3.5 以及 mono 1.2.4支持的东东Flex, Flash Remoting (RP…

简洁大气摄影网站在哪做网站不要钱

:构建便捷出行新体验 一、引言:探索打车系统小程序源码的重要性 在数字化快速发展的今天,打车系统小程序已成为我们日常生活中不可或缺的一部分。它以其便捷、高效的特点,极大地改变了我们的出行方式。而背后的关键,…

品牌展示型网站源码网店设计与装修的作用与意义

在这个数字化的时代,外卖小程序已经成为餐饮业的一项重要工具。在本文中,我们将通过一些简单而实用的技术代码,向您展示如何构建一个基本的外卖小程序。我们将使用微信小程序平台作为例子,但这些原理同样适用于其他小程序平台。 …

东莞想做网站找什么公司做网站实现图片自动压缩

实现这个游戏需要Easy_X 这个在我前面一篇C之番外篇爱心代码有程序教你怎么下载,大家可自行查看 然后就是需要植物大战僵尸的素材和音乐,需要的可以在评论区 首先是main.cpp //开发日志 //1导入素材 //2实现最开始的游戏场景 //3实现游戏顶部的工具栏…

dede替换网站模板电商网站的特点

在物联网(IoT)时代,随着智能设备的普及和万物互联的加速,隐私保护与数据安全成为了亟待解决的关键问题。以下是一些重要的隐私保护与数据安全策略,以确保在万物互联背景下信息的安全: 1. 加强设备安全&…

cco网站素材网站制作公司 云南

STM32 OTA-IAP设计方案 OTA是Over-the-Air的简写,即空中下载技术,通过网络远程给用户进行系统更新和升级。IAP是In Application Programming的简写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在…

主题网站设计欣赏dw做的网站怎么上传图片

随着网络技术的不断发展,网络安全威胁也在不断增加,勒索病毒攻击企业计算机服务器的事件时有发生,并且勒索病毒的加密形式也越来越复杂。近期,云天数据恢复中心陆续接到很多企业的求助,企业的计算机服务器遭到了mallox…

自己建设网站难不难哪个网站做不锈钢好

一、获得命令帮助 1.1、内部命令与外部命令 简单来说,在linux系统中有存储位置的命令为外部命令; 没有存储位置的为内部命令,可以理解为内部命令嵌入在linux的shell中,所以看不到。 type来判断到底为内部命令还是内部命令 [ro…

北京住房与城乡建设网站怎么查看网页源代码

在sbin文件夹下是start-all.sh可以运行的,但是到了别的文件夹下就不行了,于是想到了是文件路径问题,因为hadoop环境是和java环境一起配置的导致sbin写成了bin 解决办法: 打开.bashrc配置hadoop的环境变量 sudo vim ~/.bashrc …

古镇免费网站建设最好看免费观看高清大全猪蜜蜜剧本

适用于什么场景? 检索比较多的场景,例如学生成绩管理系统,老师对学生的成绩进行排名或查询操作 ArrayList有哪些特点? 1、ArrayList集合底层采用了数组数据结构,是Object类型 2、动态数组。ArrayList的默认初始容量…

传奇高端网站设计制作大庆网站建设优化

查看WEB服务器的连接数 https://technet.microsoft.com/en-us/sysinternals/bb897437 tcpView转载于:https://www.cnblogs.com/daishuguang/p/4973342.html

h5网站建设模板html5 网站源码

文章目录后端有关说明前端有关说明接口设计小程序注册/登录接口APP 注册/登录接口PC Web 端的注册/登录接口小程序注册/登录序列图校验 token后端有关说明 登录和注册的逻辑要独立抽取写成2个接口:注册接口、登录接口 小程序、APP、PC端的登录接口和注册接口要分开…

移动网站建设服务商重庆必去的十大景点

Android开发要点说明 商户在微信开放平台申请开发应用后,微信开放平台会生成APP的唯一标识APPID。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。 应用包名:是在APP项目配置文件And…

做拆分盘网站南充做网站略奥网络

第一道题:求有删除情况的最长回文子串 题目: 解题思路: 这个题严格意义上来说,删除了字符就谈不上回文串了,既然有删除,那估计考察的不是回文串,而是其他的,但是这个东西又有回文串的…

好网站建设公司服务子网站建设方案

分布式并发架构 微服务、Docker容器的基本原理、架构设计,以及应用场景。 缓存:Redis、Memcached、CDN、本地缓存 搜索引擎的选型:Lucene、Solr等选型与比较 应用服务器雪崩:长事务、SQL超时、同步接口引起的雪崩场景&#xff…

免费在线观看电影电视剧网站wordpress菜单对齐修改

探寻SQL的背后机制 前言 在数据领域,SQL(Structured Query Language)是一门广泛使用的语言,用于查询和处理数据。你可能已经使用过诸如MySQL、Hive、ClickHouse、Doris、Spark和Flink等工具来编写SQL查询。 每一种框架都提供了…

合肥工程建设交易中心网站国美在线网站建设费用

if语句是条件判断语句 格式为: if 条件:执行语句 elif 再一个条件:执行语句 else:执行语句注意: if 与elif后不要忘记冒号 例子: #Autor:Decade value156 value2int(input(number:)) #提示用户输入一个整数型的数字 if value1>value2: …