├── .gitignore ├── LICENSE ├── README.md ├── client ├── client.sln ├── client.vcxproj ├── client.vcxproj.filters ├── p2pClient.cpp └── protocal.h └── server ├── Makefile ├── p2p_server.cpp └── protocal.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | 31 | 32 | #other 33 | /client/Debug/* 34 | /client/x64 35 | *.db 36 | *.vs 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 MacroGu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # p2p_comm 2 | p2p通信的示例, server 运行在 linux 下, client 运行在 windows,注意两个client能够通信前提是都要登陆server, 并且在自己的client列表中,且在完成打洞之后 3 | -------------------------------------------------------------------------------- /client/client.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "client.vcxproj", "{1A9D375B-97E9-419A-9C02-353B4E265E19}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {1A9D375B-97E9-419A-9C02-353B4E265E19}.Debug|x64.ActiveCfg = Debug|x64 17 | {1A9D375B-97E9-419A-9C02-353B4E265E19}.Debug|x64.Build.0 = Debug|x64 18 | {1A9D375B-97E9-419A-9C02-353B4E265E19}.Debug|x86.ActiveCfg = Debug|Win32 19 | {1A9D375B-97E9-419A-9C02-353B4E265E19}.Debug|x86.Build.0 = Debug|Win32 20 | {1A9D375B-97E9-419A-9C02-353B4E265E19}.Release|x64.ActiveCfg = Release|x64 21 | {1A9D375B-97E9-419A-9C02-353B4E265E19}.Release|x64.Build.0 = Release|x64 22 | {1A9D375B-97E9-419A-9C02-353B4E265E19}.Release|x86.ActiveCfg = Release|Win32 23 | {1A9D375B-97E9-419A-9C02-353B4E265E19}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /client/client.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {1A9D375B-97E9-419A-9C02-353B4E265E19} 23 | Win32Proj 24 | client 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 101 | Level3 102 | Disabled 103 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | 105 | 106 | Console 107 | true 108 | 109 | 110 | 111 | 112 | Level3 113 | 114 | 115 | MaxSpeed 116 | true 117 | true 118 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | 120 | 121 | Console 122 | true 123 | true 124 | true 125 | 126 | 127 | 128 | 129 | Level3 130 | 131 | 132 | MaxSpeed 133 | true 134 | true 135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 136 | 137 | 138 | Console 139 | true 140 | true 141 | true 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /client/client.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /client/p2pClient.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MacroGu/p2p_comm/82f23fe278451c78940c266c0f1c60f91b4ab143/client/p2pClient.cpp -------------------------------------------------------------------------------- /client/protocal.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MacroGu/p2p_comm/82f23fe278451c78940c266c0f1c60f91b4ab143/client/protocal.h -------------------------------------------------------------------------------- /server/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | rm -rf core.* 3 | rm -rf p2p_server 4 | g++ -g -std=c++11 p2p_server.cpp -o p2p_server 5 | 6 | clean: 7 | rm -rf p2p_server 8 | -------------------------------------------------------------------------------- /server/p2p_server.cpp: -------------------------------------------------------------------------------- 1 | #include "protocal.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | UserList ClientList;//客户节点列表 16 | int PrimaryUDP; 17 | 18 | stUserListNode GetUser(char *userName); 19 | 20 | 21 | int main(int argc, char **argv) 22 | { 23 | PrimaryUDP = socket(AF_INET, SOCK_DGRAM, 0); 24 | if (PrimaryUDP < 0) 25 | { 26 | std::cout << "创建 socket 失败!" << std::endl; 27 | return 0; 28 | } 29 | 30 | sockaddr_in addr; 31 | addr.sin_family = AF_INET; 32 | addr.sin_port = htons(SERVER_PORT); 33 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 34 | if (bind(PrimaryUDP, (struct sockaddr*)&addr, sizeof(addr)) < 0) 35 | { 36 | std::cout << "bind socket failed!" << std::endl; 37 | return 0; 38 | } 39 | 40 | sockaddr_in sender; 41 | char buf[MAX_PACKET_SIZE] = {0}; 42 | 43 | // 开始主循环 44 | // 1。读取客户端登陆和登出消息,记录客户端节点列表 45 | for ( ; ; ) 46 | { 47 | stCommMsg* mRecvMsg = (stCommMsg*)buf; 48 | socklen_t nLen = sizeof (sender); 49 | int ret = recvfrom(PrimaryUDP, (char*)mRecvMsg , MAX_PACKET_SIZE, 0, (sockaddr*)&sender, &nLen); 50 | 51 | if (ret < 0) 52 | { 53 | std::cout << "recv error " << std::endl; 54 | continue; 55 | } 56 | else 57 | { 58 | unsigned int mMsgType = mRecvMsg->uiMsgType; 59 | switch (mMsgType) 60 | { 61 | case LOGIN: 62 | { 63 | std::cout << "has a client login, user name: " << mRecvMsg->cMyName << std::endl; 64 | stUserListNode* currentUser = new stUserListNode; 65 | memcpy(currentUser->userName, mRecvMsg->cMyName,MAX_NAME_SIZE); 66 | currentUser->uiIP = ntohl(sender.sin_addr.s_addr); 67 | currentUser->usPORT = ntohs(sender.sin_port); 68 | ClientList.push_back(currentUser); // do not exclude same name user 69 | 70 | char sendBuf[MAX_PACKET_SIZE] = {0}; 71 | stCommMsg* sendbuf = (stCommMsg*) sendBuf; 72 | // 服务器应答消息 73 | sendbuf->uiMsgType = GETALLUSER; 74 | for (auto ClientList_iter = ClientList.begin(); ClientList_iter != ClientList.end(); ++ClientList_iter) 75 | { 76 | memcpy(sendbuf->userList[sendbuf->userNums].userName, (*ClientList_iter)->userName,MAX_NAME_SIZE); 77 | sendbuf->userList[sendbuf->userNums].uiIP = (*ClientList_iter)->uiIP; 78 | sendbuf->userList[sendbuf->userNums].usPORT = (*ClientList_iter)->usPORT; 79 | ++sendbuf->userNums; 80 | } 81 | 82 | sendto(PrimaryUDP, (const char*)sendbuf, sendbuf->getSize(),0, 83 | (const sockaddr*)&sender, sizeof(sender)); 84 | break; 85 | } 86 | case LOGOUT: 87 | { 88 | std::cout << "has a client logout, name:" << mRecvMsg->cMyName << std::endl; 89 | for (auto ClientList_iter = ClientList.begin(); ClientList_iter != ClientList.end(); ++ClientList_iter) 90 | { 91 | if (strcmp((*ClientList_iter)->userName, mRecvMsg->cMyName) == 0) 92 | { 93 | ClientList_iter = ClientList.erase(ClientList_iter); 94 | } 95 | } 96 | 97 | break; 98 | } 99 | case GETALLUSER: 100 | { 101 | char sendBuf[MAX_PACKET_SIZE] = {0}; 102 | stCommMsg* sendbuf = (stCommMsg*) sendBuf; 103 | // 服务器应答消息 104 | sendbuf->uiMsgType = GETALLUSER; 105 | for (auto ClientList_iter = ClientList.begin(); ClientList_iter != ClientList.end(); ++ClientList_iter) 106 | { 107 | memcpy(sendbuf->userList[sendbuf->userNums].userName, (*ClientList_iter)->userName,MAX_NAME_SIZE); 108 | sendbuf->userList[sendbuf->userNums].uiIP = (*ClientList_iter)->uiIP; 109 | sendbuf->userList[sendbuf->userNums].usPORT = (*ClientList_iter)->usPORT; 110 | ++sendbuf->userNums; 111 | } 112 | 113 | sendto(PrimaryUDP, (const char*)sendbuf, sendbuf->getSize(),0, 114 | (const sockaddr*)&sender, sizeof(sender)); 115 | unsigned int nodecount = ClientList.size(); 116 | std::cout << "want get all user list" << nodecount << std::endl; 117 | 118 | break; 119 | } 120 | case P2PTRANS: 121 | { 122 | //某个客户希望服务器向另一客户发送一“打洞”消息 123 | std::cout << mRecvMsg->cMyName << " wants to p2p with :" << mRecvMsg->cToName << std::endl; 124 | stUserListNode user=GetUser(mRecvMsg->cToName); 125 | 126 | sockaddr_in remote; 127 | remote.sin_family=AF_INET; 128 | remote.sin_port=htons(user.usPORT); 129 | remote.sin_addr.s_addr=htonl(user.uiIP); 130 | 131 | in_addr temp; 132 | temp.s_addr=htonl(user.uiIP); 133 | printf("the address is %s,and the port is %d\n",inet_ntoa(temp),user.usPORT); 134 | 135 | stCommMsg mTransMsg; 136 | mTransMsg.uiMsgType = P2PSOMEONEWANTTOCALLYOU; 137 | mTransMsg.transMsg.uiIP = ntohl(sender.sin_addr.s_addr); 138 | mTransMsg.transMsg.usPORT = ntohs(sender.sin_port); 139 | 140 | sendto(PrimaryUDP, (const char*)&mTransMsg, sizeof(stCommMsg),0,(const sockaddr*)&remote,sizeof(remote)); 141 | 142 | break; 143 | } 144 | } 145 | 146 | } 147 | 148 | } 149 | 150 | 151 | return 0; 152 | } 153 | 154 | stUserListNode GetUser(char *userName) 155 | { 156 | for (auto ClientList_iter = ClientList.begin(); ClientList_iter != ClientList.end(); ++ClientList_iter) 157 | { 158 | if (strcmp((*ClientList_iter)->userName, userName) == 0) 159 | return *(*ClientList_iter); 160 | } 161 | 162 | std::cout << "can not find user: " << userName << std::endl; 163 | 164 | exit(0); 165 | } 166 | -------------------------------------------------------------------------------- /server/protocal.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MacroGu/p2p_comm/82f23fe278451c78940c266c0f1c60f91b4ab143/server/protocal.h --------------------------------------------------------------------------------