├── .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
--------------------------------------------------------------------------------