P2P UDP penetration NAT principle and implementation - Addition code

xiaoxiao2021-03-05  25

Shootingstars' articles and code have indeed brilliant, can't help it. Three wish documents, very clear structures. Exception.hproto.hp2pclient / p2pclient.cppp2pserver / p2pserver.cpp

/ * * * Exception class file name: Exception.h * * Date: 2004.5.5 * * Author: shootingstars (zhouhuis22@sina.com) * /

#ifndef __hzh_exception __ # define __hzh_exception__

#define exception_message_maxlen 256 # include "string.h"

Class Exception {private: char m_exceptionMaxlen [eXception_message_maxlen]; public: exception (char * msg) {strncpy (m_exceptionMessage, msg, eXception_message_maxlen);

Char * getMessage () {return m_exceptionMessage;}}; # ENDIF

/ * P2P program Transfer Protocol * * proto.h * * Date: 2004-5-21 * * Author: shootingstars (zhouhuis22@sina.com) * * /

#pragma overce # incrude

// Define the value of iMessageType #define login 1 # Define logout 2 # define p2ptrans 3 # Define getAllUser 4

// Server port #define server_port 2280

// Client When logging in to the message Struct StloginMessage {Char UserName [10]; CHAR Password [10];

Signing Struct StlogoutMessage {Char UserName [10];};

// Client requests another client (username) to send UDP hole messages in the direction Struct stp2ptranslate {char username [10];

// Client Strus; union _Message; stlogoutmessage logoutmensage;} message;

// Customer Node Information Struct StuserListNode {Char Username [10]; UNSIGNED IP; UNSIGNED SHORT Port;

// Server sent to the client Struct Stservlient {Int iMessageType; Union_Message {StuserListNode User;} message;

}

/ / ================================================================================================= // The following protocol is used for the client Communication // ====================================== # define p2pMessage 100 // Send Message #define p2pMessageack 101 // Receive a message from the message #define p2psomeOnEwantTocallyou 102 // The server sent to the client // hope this client sends a UDP tales #define p2ptrash 103 // client sending holes The receiving end should ignore this message // client to send message format struct stp2pMessage {Int iMessageType; int istringlen; // or ip address unsigned short port;

Using namespace std; typedef list userlist;

/ * P2P client programs * * File name: P2PClient.c * * Date: 2004-5-21 * * Author: shootingstars (zhouhuis22@sina.com) * * /

#pragma comment (Lib, "WS2_32.LIB")

#include "windows.h" #include "../proto.h"#include" ../exception.h"#include using namespace std;

UserList ClientList;

#define commandmaxc 256 # Define MaxRetry 5

Socket primaryudp; char username [10]; char Serverip [20];

Bool recvedack;

VoidinSock () {wsadata wsadata;

IF (WsaStartup (MakeWord (2, 2), & WSADATA! = 0) {Printf ("Windows Sockets 2.2 Startup); throw exception (" ");} else {printf (" Using% s) / N ", wsadata.szdescription, wsadata.szsystemStatus); Printf (" With API VersionS% D.% D TO% D.% D / N / N ", Lobyte (Wsadata.WVersion), Lobyte (wsadata.whighveions), hibyte (wsadata.whighveions);}}

Socket MKSock (INT TYPE) {Socket Sock = Socket (AF_INET, TYPE, 0); if (SOCK <0) {Printf ("Create Socket Error"); Throw Exception ("");} Return SOCK;

StuserListNode GetUser (USERLIST :: Iterator Useriterator = ClientList.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, (struct sockaddr *) & 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, SOCK, SIZEOF (Sendbuf), 0, (Const SockAddr *) & Remote, Sizeof (Remote));

INT usercount; int.comlen = sizeof (trans.); INT IREAD = Recvfrom (SOCK, (CHAR *) & UserCount, Sizeof (int), 0, (sockaddr *) & remote, & fromlen; if (iRead <= 0) {throw Exception ("Login error / n");

// After logging in to the server, receive the user's information from the logged in the server COUT << "" "<< usercount <<" UserCount << "UserCount <<" UserS logined Server: << endl; for (int i = 0; i < usercount; i ) {stUserListNode * node = new stUserListNode; recvfrom (sock, (char *) node, sizeof (stUserListNode), 0, (sockaddr *) & remote, & fromlen); ClientList.push_back (node); cout << "Username : "<< node-> username << Endl; in_addr tmp; tmp.s_un.s_addr = htonl (node-> ip); cout <<" Userip: << inet_ntoa (tmp) << Endl; cout << " Userport: "<< node-> port << endl; cout <<" << endl;}} void outputusage ()} void outputusage () {cout << "You can input you command: / n" << "Command Type: /" Send / ", /" exit / ", /" getu / "/ n" << "example: send username message / n" << "exit / n" << "getu / n" << Endl;}

/ * This is the main function: Send a message to a user (c) * process: send a message directly to the external network IP of a user, if this is not connected * So this message will not be sent, the sender waits for timeout . * Timeout, the sender will send a request information to the server. , char * Message) {char realmessage [256]; unsigned int UserIP; unsigned short UserPort; bool FindUser = false; for (UserList :: iterator UserIterator = ClientList.begin ();! UserIterator = ClientList.end (); Useriterator) {if ((* useriterator) -> username) == 0) {userip = (* useriterator) -> ip; userport = true;}}

IF (! finduser) Return False;

strcpy (realmessage, Message); for (int i = 0; i

// No response to the target host, think that the port mapping of the target host is not //, then send request information to the server, to tell the server to tell the target host // open mapping port (UDP hole) 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, Const Char *) & Transme, Sizeof (Transmessage), 0, (Const SockAddr *) & Server, SIZEOF (Server)); Sleep (100); // Waiting for the other party first send information. } Return False;

// Resolution command, temporarily only exit and send command // new Getu command, get all user void parseCommand (strn (commandline <4) {if (strncpy) {if (strncpy) {ix; (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, (const char *) & 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 (i = 5 ;; i ) {IF (CommandLine [i]! = ') SendName [i-5] = CommandLine [i]; else {sendname [i-5] =' / 0 '; Break;} } STRCPY (Message, & (CommandLine [i 1])); if (sendMessageto (SendName, Message)) Printf ("Send OK! / N"); Else Printf ("Send Failure! / N");} Else IF (strCMP (Command, "Getu") == 0) {int command = getAlluser; sockaddr_in server; server.sin_addr.s_un.s_addr = inet_addr (server); server.sin_family = AF_INET; Server.sin_Port = HTONS (Server_Port);

Sendto (Primaryudp, Const Char *) & Command, Sizeof (Command), 0, (Const SockAddr *) & Server, SizeOf (Server));}}

Accept message thread // DWORD WINAPI RecvThreadProc (LPVOID lpParameter) {sockaddr_in remote; int sinlen = sizeof (remote); stP2PMessage recvbuf; for (;;) {int iread = recvfrom (PrimaryUDP, (char *) & recvbuf, sizeof (recvbuf) , 0, & SINLEN); if (iRead <= 0) {Printf ("Recv Error / N"); Continue;} Switch (Recvbuf.IMessageType) {copy p2pMessage: {// receive p2p message char * comemessage = new char [recvbuf.iStringLen]; int iread1 = recvfrom (PrimaryUDP, comemessage, 256, 0, (sockaddr *) & remote, & sinlen); comemessage [iread1-1] = '/ 0'; if (iread1 <= 0) 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 suckaddr *) & remote, sizeof (transote));} delete [] commessage;

} Case P2PSOMEONEWANTTOCALLYOU: {// command receiving holes, holes printf ( "Recv p2someonewanttocallyou data / n") to the specified IP address; sockaddr_in remote; remote.sin_addr.S_un.S_addr = htonl (recvbuf.iStringLen); remote .sin_family = AF_INET; Remote.SIN_PORT = HTONS (Recvbuf.Port);

// UDP hole punching stP2PMessage message; message.iMessageType = P2PTRASH; sendto (PrimaryUDP, (const char *) & message, sizeof (message), 0, (const sockaddr *) & remote, sizeof (remote)); break;} case P2PMESSAGEACK : {// Recons for sending messages Recvedack = true; break;} case p2ptrash: {// The hole message sent by the other party is ignored. // do Nothing ... Printf ("Recv p2ptrash / n"); Break;} case getAllUser: {Int Usercount; int.comlen = sizeof (remote); int = recvfrom (primaryudp, (char *) & usercount, sizeof (int), 0, (SockAddr *) & remote, & fromlease; f (iRead <= 0) {throw exception ("login error / n");} clientlist.clear (); cout << "have" << Usercount << "Users logined server:" << endl; for (int i = 0; i username << Endl; in_addr tmp; tmp.s_un.s_addr = HTONL (Node-> IP); Cout << "Userip: << inet_ntoa (tmp) << endl; cout <<" Userport: << Node-> port << Endl; cout << "<< Endl;}}}}}}}

INT Main (int Argc, char * argv []) {Try {INITWINSOCK (); primaryudp = mksock (sock_dgram); bindsock (primaryudp);

COUT << "please input server ip:"; cin >> Serverip;

COUT << "please input your name:"; cin >> username;

ConnectToServer (Primaryudp, UserName, ServerIP);

HANDLE threadhandle = CreateThread (NULL, 0, RecvThreadProc, NULL, NULL, NULL); CloseHandle (threadhandle); OutputUsage (); for (;;) {char Command [COMMANDMAXC]; gets (Command); ParseCommand (Command);} } CatCH (E.GETMESSAGE ()); Return 1;} return 0;}

/ * P2P program server * * File name: P2PServer.c * * Date: 2004-5-21 * * Author: shootingstars (zhouhuis22@sina.com) * * / # pragma comment (lib, "ws2_32.lib")

#include "#include" ../proto.h"#include "../exception.h"

UserList ClientList;

VoidinSock () {wsadata wsadata;

IF (WsaStartup (MakeWord (2, 2), & WSADATA! = 0) {Printf ("Windows Sockets 2.2 Startup); throw exception (" ");} else {printf (" Using% s) / N ", wsadata.szdescription, wsadata.szsystemStatus); Printf (" With API VersionS% D.% D TO% D.% D / N / N ", Lobyte (Wsadata.WVersion), Lobyte (wsadata.whighveions), hibyte (wsadata.whighveions);}}

Socket MKSock (INT TYPE) {Socket Sock = Socket (AF_INET, TYPE, 0); if (SOCK <0) {Printf ("Create Socket Error"); Throw Exception ("");} Return SOCK;

StuserListNode GetUser (USERLIST :: Iterator Useriterator = ClientList.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_family = AF_INET; local.sin_port = htons (SERVER_PORT); local.sin_addr.s_addr = htonl (INADDR_ANY); int nResult = bind (PrimaryUDP, (sockaddr *) & local, sizeof (sockaddr)); if ( NRESULT == Socket_ERROR) Throw Exception ("Bind Error"); SockAddr_in Sender; Stimentage Recvbuf; Memset (& Recvbuf, 0, Sizeof (stmessage));

// Start the primary loop. // Main loop is responsible for the following things: // 1: Read the client login and logout message, record customer list // 2: Forward customers P2P request for (;;) {int dWsender = SIZEOF (SENDER); int RET = Recvfrom (Primaryudp, (char *) & recvbuf, sizeof (stmessage), 0, (sockaddr *) & sender, & dwsender); if (RET <= 0) {Printf ("Recv Error"); CONTINUE;} else {int messagepe = recvbuf.IMessageType; switch (message) {copy login: {// Record this user's information to 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);

// Send a customer information that has been logged in INT nodecount = (int) clientlist.size (); sendto (primaryudp, (const char *) & nodecount, sizeof (int), 0, (const socddr *) & sender, sizeof (sender)) For (UserList :: Iterator Useriterator = ClientList.begin (); useriterator! = Clientlist.end (); useriterator) {sendto (Primaryudp, (const char *) (* useriterator), sizeof (stuserlistnode), 0, (const sockaddr *) & sender, sizeof (sender);}

Break;} case logout: {// Remove this customer information ("HAS A User Logout: / 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;}} f (REMOVEITERATOR! = null) ClientList.remove (* removeiterator); Break;} case p2ptrans: {// A customer wants the server to send a hole message to another customer 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_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.i p); Printf ("The Address IS% S, AND Port), 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;} Case getAllUser: {int command = getAlluser; sendto (primaryudp, (const char *) & command, sizeof (int), 0, (const socdr *) & sender, sizeof (sender));

INT NodeCount = (int) ClientList.size (); sendto (primaryudp, (const char *) & nodecount, sizeof (int), 0, (const socddr *) & sender, sizeof (sender)); for (userlist :: itemator Userizer = ClientList.begin (); useriterator! = Clientlist.end (); useriterator) {sendto (Primaryudp, (const char *) (* useriterator), sizeof (stuserlistNode), 0, (const socddr *) & sender, Sizeof (sender);} Break;}}}}}}

} CatCH (Exception & E) {Printf (E.getMessage ()); Return 1;}

Return 0;}

转载请注明原文地址:https://www.9cbs.com/read-33192.html

New Post(0)