Chat Example Client.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. // ----------------------------------------------------------------------
  11. // RakNet version 1.0
  12. // Filename ChatExample.cpp
  13. // Very basic chat engine example
  14. // ----------------------------------------------------------------------
  15. #include "MessageIdentifiers.h"
  16. #include "RakPeerInterface.h"
  17. #include "RakNetStatistics.h"
  18. #include "RakNetTypes.h"
  19. #include "BitStream.h"
  20. #include "PacketLogger.h"
  21. #include <assert.h>
  22. #include <cstdio>
  23. #include <cstring>
  24. #include <stdlib.h>
  25. #include "RakNetTypes.h"
  26. #ifdef _WIN32
  27. #include "Kbhit.h"
  28. #include "WindowsIncludes.h" // Sleep
  29. #else
  30. #include "Kbhit.h"
  31. #include <unistd.h> // usleep
  32. #endif
  33. #include "Gets.h"
  34. #if LIBCAT_SECURITY==1
  35. #include "SecureHandshake.h" // Include header for secure handshake
  36. #endif
  37. // We copy this from Multiplayer.cpp to keep things all in one file for this example
  38. unsigned char GetPacketIdentifier(RakNet::Packet *p);
  39. int main(void)
  40. {
  41. RakNet::RakNetStatistics *rss;
  42. // Pointers to the interfaces of our server and client.
  43. // Note we can easily have both in the same program
  44. RakNet::RakPeerInterface *client=RakNet::RakPeerInterface::GetInstance();
  45. // client->InitializeSecurity(0,0,0,0);
  46. //RakNet::PacketLogger packetLogger;
  47. //client->AttachPlugin(&packetLogger);
  48. // Holds packets
  49. RakNet::Packet* p;
  50. // GetPacketIdentifier returns this
  51. unsigned char packetIdentifier;
  52. // Just so we can remember where the packet came from
  53. bool isServer;
  54. // Record the first client that connects to us so we can pass it to the ping function
  55. RakNet::SystemAddress clientID=RakNet::UNASSIGNED_SYSTEM_ADDRESS;
  56. // Crude interface
  57. // Holds user data
  58. char ip[64], serverPort[30], clientPort[30];
  59. // A client
  60. isServer=false;
  61. printf("This is a sample implementation of a text based chat client.\n");
  62. printf("Connect to the project 'Chat Example Server'.\n");
  63. printf("Difficulty: Beginner\n\n");
  64. // Get our input
  65. puts("Enter the client port to listen on");
  66. Gets(clientPort,sizeof(clientPort));
  67. if (clientPort[0]==0)
  68. strcpy(clientPort, "0");
  69. puts("Enter IP to connect to");
  70. Gets(ip, sizeof(ip));
  71. client->AllowConnectionResponseIPMigration(false);
  72. if (ip[0]==0)
  73. strcpy(ip, "127.0.0.1");
  74. // strcpy(ip, "natpunch.jenkinssoftware.com");
  75. puts("Enter the port to connect to");
  76. Gets(serverPort,sizeof(serverPort));
  77. if (serverPort[0]==0)
  78. strcpy(serverPort, "1234");
  79. // Connecting the client is very simple. 0 means we don't care about
  80. // a connectionValidationInteger, and false for low priority threads
  81. RakNet::SocketDescriptor socketDescriptor(atoi(clientPort),0);
  82. socketDescriptor.socketFamily=AF_INET;
  83. client->Startup(8,&socketDescriptor, 1);
  84. client->SetOccasionalPing(true);
  85. #if LIBCAT_SECURITY==1
  86. char public_key[cat::EasyHandshake::PUBLIC_KEY_BYTES];
  87. FILE *fp = fopen("publicKey.dat","rb");
  88. fread(public_key,sizeof(public_key),1,fp);
  89. fclose(fp);
  90. #endif
  91. #if LIBCAT_SECURITY==1
  92. RakNet::PublicKey pk;
  93. pk.remoteServerPublicKey=public_key;
  94. pk.publicKeyMode=RakNet::PKM_USE_KNOWN_PUBLIC_KEY;
  95. bool b = client->Connect(ip, atoi(serverPort), "Rumpelstiltskin", (int) strlen("Rumpelstiltskin"), &pk)==RakNet::CONNECTION_ATTEMPT_STARTED;
  96. #else
  97. RakNet::ConnectionAttemptResult car = client->Connect(ip, atoi(serverPort), "Rumpelstiltskin", (int) strlen("Rumpelstiltskin"));
  98. RakAssert(car==RakNet::CONNECTION_ATTEMPT_STARTED);
  99. #endif
  100. printf("\nMy IP addresses:\n");
  101. unsigned int i;
  102. for (i=0; i < client->GetNumberOfAddresses(); i++)
  103. {
  104. printf("%i. %s\n", i+1, client->GetLocalIP(i));
  105. }
  106. printf("My GUID is %s\n", client->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString());
  107. puts("'quit' to quit. 'stat' to show stats. 'ping' to ping.\n'disconnect' to disconnect. 'connect' to reconnnect. Type to talk.");
  108. char message[2048];
  109. // Loop for input
  110. while (1)
  111. {
  112. // This sleep keeps RakNet responsive
  113. #ifdef _WIN32
  114. Sleep(30);
  115. #else
  116. usleep(30 * 1000);
  117. #endif
  118. if (kbhit())
  119. {
  120. // Notice what is not here: something to keep our network running. It's
  121. // fine to block on Gets or anything we want
  122. // Because the network engine was painstakingly written using threads.
  123. Gets(message,sizeof(message));
  124. if (strcmp(message, "quit")==0)
  125. {
  126. puts("Quitting.");
  127. break;
  128. }
  129. if (strcmp(message, "stat")==0)
  130. {
  131. rss=client->GetStatistics(client->GetSystemAddressFromIndex(0));
  132. StatisticsToString(rss, message, 2);
  133. printf("%s", message);
  134. printf("Ping=%i\n", client->GetAveragePing(client->GetSystemAddressFromIndex(0)));
  135. continue;
  136. }
  137. if (strcmp(message, "disconnect")==0)
  138. {
  139. printf("Enter index to disconnect: ");
  140. char str[32];
  141. Gets(str, sizeof(str));
  142. if (str[0]==0)
  143. strcpy(str,"0");
  144. int index = atoi(str);
  145. client->CloseConnection(client->GetSystemAddressFromIndex(index),false);
  146. printf("Disconnecting.\n");
  147. continue;
  148. }
  149. if (strcmp(message, "shutdown")==0)
  150. {
  151. client->Shutdown(100);
  152. printf("Shutdown.\n");
  153. continue;
  154. }
  155. if (strcmp(message, "startup")==0)
  156. {
  157. bool b = client->Startup(8,&socketDescriptor, 1)==RakNet::RAKNET_STARTED;
  158. if (b)
  159. printf("Started.\n");
  160. else
  161. printf("Startup failed.\n");
  162. continue;
  163. }
  164. if (strcmp(message, "connect")==0)
  165. {
  166. printf("Enter server ip: ");
  167. Gets(ip, sizeof(ip));
  168. if (ip[0]==0)
  169. strcpy(ip, "127.0.0.1");
  170. printf("Enter server port: ");
  171. Gets(serverPort,sizeof(serverPort));
  172. if (serverPort[0]==0)
  173. strcpy(serverPort, "1234");
  174. #if LIBCAT_SECURITY==1
  175. bool b = client->Connect(ip, atoi(serverPort), "Rumpelstiltskin", (int) strlen("Rumpelstiltskin"), &pk)==RakNet::CONNECTION_ATTEMPT_STARTED;
  176. #else
  177. bool b = client->Connect(ip, atoi(serverPort), "Rumpelstiltskin", (int) strlen("Rumpelstiltskin"))==RakNet::CONNECTION_ATTEMPT_STARTED;
  178. #endif
  179. if (b)
  180. puts("Attempting connection");
  181. else
  182. {
  183. puts("Bad connection attempt. Terminating.");
  184. exit(1);
  185. }
  186. continue;
  187. }
  188. if (strcmp(message, "ping")==0)
  189. {
  190. if (client->GetSystemAddressFromIndex(0)!=RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  191. client->Ping(client->GetSystemAddressFromIndex(0));
  192. continue;
  193. }
  194. if (strcmp(message, "getlastping")==0)
  195. {
  196. if (client->GetSystemAddressFromIndex(0)!=RakNet::UNASSIGNED_SYSTEM_ADDRESS)
  197. printf("Last ping is %i\n", client->GetLastPing(client->GetSystemAddressFromIndex(0)));
  198. continue;
  199. }
  200. // message is the data to send
  201. // strlen(message)+1 is to send the null terminator
  202. // HIGH_PRIORITY doesn't actually matter here because we don't use any other priority
  203. // RELIABLE_ORDERED means make sure the message arrives in the right order
  204. client->Send(message, (int) strlen(message)+1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true);
  205. }
  206. // Get a packet from either the server or the client
  207. for (p=client->Receive(); p; client->DeallocatePacket(p), p=client->Receive())
  208. {
  209. // We got a packet, get the identifier with our handy function
  210. packetIdentifier = GetPacketIdentifier(p);
  211. // Check if this is a network message packet
  212. switch (packetIdentifier)
  213. {
  214. case ID_DISCONNECTION_NOTIFICATION:
  215. // Connection lost normally
  216. printf("ID_DISCONNECTION_NOTIFICATION\n");
  217. break;
  218. case ID_ALREADY_CONNECTED:
  219. // Connection lost normally
  220. printf("ID_ALREADY_CONNECTED with guid %" PRINTF_64_BIT_MODIFIER "u\n", p->guid);
  221. break;
  222. case ID_INCOMPATIBLE_PROTOCOL_VERSION:
  223. printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
  224. break;
  225. case ID_REMOTE_DISCONNECTION_NOTIFICATION: // Server telling the clients of another client disconnecting gracefully. You can manually broadcast this in a peer to peer enviroment if you want.
  226. printf("ID_REMOTE_DISCONNECTION_NOTIFICATION\n");
  227. break;
  228. case ID_REMOTE_CONNECTION_LOST: // Server telling the clients of another client disconnecting forcefully. You can manually broadcast this in a peer to peer enviroment if you want.
  229. printf("ID_REMOTE_CONNECTION_LOST\n");
  230. break;
  231. case ID_REMOTE_NEW_INCOMING_CONNECTION: // Server telling the clients of another client connecting. You can manually broadcast this in a peer to peer enviroment if you want.
  232. printf("ID_REMOTE_NEW_INCOMING_CONNECTION\n");
  233. break;
  234. case ID_CONNECTION_BANNED: // Banned from this server
  235. printf("We are banned from this server.\n");
  236. break;
  237. case ID_CONNECTION_ATTEMPT_FAILED:
  238. printf("Connection attempt failed\n");
  239. break;
  240. case ID_NO_FREE_INCOMING_CONNECTIONS:
  241. // Sorry, the server is full. I don't do anything here but
  242. // A real app should tell the user
  243. printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
  244. break;
  245. case ID_INVALID_PASSWORD:
  246. printf("ID_INVALID_PASSWORD\n");
  247. break;
  248. case ID_CONNECTION_LOST:
  249. // Couldn't deliver a reliable packet - i.e. the other system was abnormally
  250. // terminated
  251. printf("ID_CONNECTION_LOST\n");
  252. break;
  253. case ID_CONNECTION_REQUEST_ACCEPTED:
  254. // This tells the client they have connected
  255. printf("ID_CONNECTION_REQUEST_ACCEPTED to %s with GUID %s\n", p->systemAddress.ToString(true), p->guid.ToString());
  256. printf("My external address is %s\n", client->GetExternalID(p->systemAddress).ToString(true));
  257. break;
  258. case ID_CONNECTED_PING:
  259. case ID_UNCONNECTED_PING:
  260. printf("Ping from %s\n", p->systemAddress.ToString(true));
  261. break;
  262. default:
  263. // It's a client, so just show the message
  264. printf("%s\n", p->data);
  265. break;
  266. }
  267. }
  268. }
  269. // Be nice and let the server know we quit.
  270. client->Shutdown(300);
  271. // We're done with the network
  272. RakNet::RakPeerInterface::DestroyInstance(client);
  273. return 0;
  274. }
  275. // Copied from Multiplayer.cpp
  276. // If the first byte is ID_TIMESTAMP, then we want the 5th byte
  277. // Otherwise we want the 1st byte
  278. unsigned char GetPacketIdentifier(RakNet::Packet *p)
  279. {
  280. if (p==0)
  281. return 255;
  282. if ((unsigned char)p->data[0] == ID_TIMESTAMP)
  283. {
  284. RakAssert(p->length > sizeof(RakNet::MessageID) + sizeof(RakNet::Time));
  285. return (unsigned char) p->data[sizeof(RakNet::MessageID) + sizeof(RakNet::Time)];
  286. }
  287. else
  288. return (unsigned char) p->data[0];
  289. }
粤ICP备19079148号