RflySimSDK v3.08
RflySimSDK说明文档
载入中...
搜索中...
未找到
rfly_udp.h
1#pragma once
2
3#if defined(__linux__) || defined(__APPLE__)
4#include <netinet/in.h>
5#include <arpa/inet.h>
6#include <sys/socket.h>
7#include <sys/types.h>
8#include <sys/ioctl.h>
9#include <unistd.h>
10#include <netdb.h>
11#include <fcntl.h>
12#include <ifaddrs.h>
13#define nonblockingsocket(s) {unsigned long ctl = 1;}
14#elif _WIN32
15#include <winsock2.h>
16#include <ws2tcpip.h>
17#pragma comment(lib,"ws2_32.lib")
18#include <iphlpapi.h>
19#pragma comment(lib, "iphlpapi.lib")
20#define nonblockingsocket(s) {unsigned long ctl = 1;ioctlsocket( s, FIONBIO, &ctl );}
21#endif
22
23#include <string>
24#include <functional>
25#include <cerrno>
26#include <thread>
27#include <iostream>
28#include <algorithm>
29
30#define FDR_UNUSED(expr){ (void)(expr); }
31#define FDR_ON_ERROR std::function<void(int, std::string)> onError = [](int errorCode, std::string errorMessage){FDR_UNUSED(errorCode); FDR_UNUSED(errorMessage)}
32
33#ifndef BUFFER_SIZE_RFLY
34#define BUFFER_SIZE_RFLY 1024
35#endif
36
37
38
40{
41public:
42 enum SocketType
43 {
44 TCP = SOCK_STREAM,
45 UDP = SOCK_DGRAM
46 };
47 sockaddr_in address;
48 //char udpBuf[BUFFER_SIZE_RFLY+1];
49 //std::string RecvIP;
50 //uint16_t RecvPort;
51 std::string remoteAddress() const { return ipToString(this->address); }
52 int remotePort() const { return ntohs(this->address.sin_port); }
53 int fileDescriptor() const { return this->sock; }
54
55protected:
56 int sock = 0;
57
58 bool hasSetNoblock=false;
59
60
61
62 //bool isStopRec=false;
63
64 // Get std::string value of the IP from a `sockaddr_in` address struct
65 static std::string ipToString(const sockaddr_in& addr)
66 {
67 char ip[INET_ADDRSTRLEN];
68
69 struct sockaddr_in in;
70 memset(&in, 0, sizeof(in));
71 in.sin_family = AF_INET;
72 memcpy(&in.sin_addr, &(addr.sin_addr), sizeof(struct in_addr));
73 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), ip, INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
74
75 return std::string(ip);
76 }
77
78 static bool isVirtualMachineAdapter(const std::string& adapterName) {
79 std::vector<std::string> vmKeywords = {
80 "VMware", "VirtualBox", "Hyper-V", "QEMU"
81 };
82 for (const auto& keyword : vmKeywords) {
83 if (adapterName.find(keyword) != std::string::npos) {
84 return true;
85 }
86 }
87 return false;
88 }
89
90 // 函数用于获取静态 IP 地址,排除虚拟机网络
91 static std::vector<std::string> getStaticIPAddresses() {
92 std::vector<std::string> staticIPs;
93#ifdef _WIN32
94 ULONG outBufLen = 0;
95 // 首次调用以获取所需的缓冲区大小
96 if (GetAdaptersInfo(NULL, &outBufLen) == ERROR_BUFFER_OVERFLOW) {
97 PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)malloc(outBufLen);
98 if (pAdapterInfo) {
99 // 再次调用以获取适配器信息
100 if (GetAdaptersInfo(pAdapterInfo, &outBufLen) == NO_ERROR) {
101 PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
102 while (pAdapter) {
103 std::string adapterName = pAdapter->Description;
104 // 检查是否为虚拟机网络
105 if (!isVirtualMachineAdapter(adapterName)) {
106 // 检查是否为静态分配的 IP
107 if (pAdapter->DhcpEnabled == FALSE) {
108 IP_ADDR_STRING* pIpAddr = &pAdapter->IpAddressList;
109 while (pIpAddr) {
110 staticIPs.emplace_back(pIpAddr->IpAddress.String);
111 pIpAddr = pIpAddr->Next;
112 }
113 }
114 }
115 pAdapter = pAdapter->Next;
116 }
117 }
118 free(pAdapterInfo);
119 }
120 }
121
122#endif
123 return staticIPs;
124 }
125
126 BaseSocket(FDR_ON_ERROR, SocketType sockType = TCP, int socketId = -1)
127 {
128 if (socketId == -1)
129 {
130 this->sock = (int)socket(AF_INET, sockType, 0);
131
132 if ( this->sock == -1 )
133 {
134 onError(errno, "Socket creating error.");
135 }
136 }
137 else
138 {
139 this->sock = socketId;
140 }
141 int rcvBufSize=102400*10;
142#ifndef __linux__
143 setsockopt(this->sock, SOL_SOCKET, SO_RCVBUF, (char*)&rcvBufSize, sizeof(rcvBufSize));
144 rcvBufSize=102400*10;
145 setsockopt(this->sock, SOL_SOCKET, SO_SNDBUF, (char*)&rcvBufSize, sizeof(rcvBufSize));
146#else
147 setsockopt(this->sock, SOL_SOCKET, SO_RCVBUF, &rcvBufSize, sizeof(rcvBufSize));
148 rcvBufSize=102400*10;
149 setsockopt(this->sock, SOL_SOCKET, SO_SNDBUF, &rcvBufSize, sizeof(rcvBufSize));
150#endif
151
152
153
154 }
155 virtual ~BaseSocket(){}
156};
157
158
159class UDPSocket : public BaseSocket
160{
161public:
162 std::function<void(std::string, std::string, uint16_t)> onMessageReceived;
163 std::function<void(const char*, size_t, std::string, uint16_t)> onRawMessageReceived;
164 bool isUseConnect = false;
165 //std::thread* mT;
166
167 void Close() {
168
169#ifndef __linux__
170 closesocket(this->sock);
171#else
172 shutdown(this->sock, SHUT_RDWR);
173 close(this->sock);
174#endif
175 }
176
177
178 explicit UDPSocket(bool useConnect = false, FDR_ON_ERROR, int socketId = -1): BaseSocket(onError, SocketType::UDP, socketId)
179 {
180 this->isUseConnect=useConnect;
181
182 }
183
184 void StartRecvThread()
185 {
186
187 if (this->isUseConnect)
188 {
189 std::thread t(Receive, this); // usage with Connect()
190 t.detach();
191 }
192 else
193 {
194 std::thread t(ReceiveFrom, this);
195 t.detach();
196 }
197
198 //this->isStopRec=false;
199 }
200
201 // Send raw bytes to a spesific `host` & `port` with no connection
202 int SendTo(const char* bytes, size_t byteslength, const char* host, uint16_t port, FDR_ON_ERROR)
203 {
204 sockaddr_in hostAddr;
205
206 //int status;
207 if((hostAddr.sin_addr.s_addr =inet_addr(host))==INADDR_NONE){
208 onError(errno, "SendTo: Invalid address. Address type not supported.");
209 }
210
211 // struct addrinfo hints, *res, *it;
212 // memset(&hints, 0, sizeof(hints));
213 // hints.ai_family = AF_INET;
214 // hints.ai_socktype = SOCK_DGRAM;
215
216 // int status;
217 // if ((status = getaddrinfo(host, NULL, &hints, &res)) != 0)
218 // {
219 // onError(errno, "Invalid address." + std::string(gai_strerror(status)));
220 // return -1;
221 // }
222
223 // for (it = res; it != NULL; it = it->ai_next)
224 // {
225 // if (it->ai_family == AF_INET)
226 // { // IPv4
227 // memcpy((void* )(&hostAddr), (void* )it->ai_addr, sizeof(sockaddr_in));
228 // break; // for now, just get first ip (ipv4).
229 // }
230 // }
231
232 // freeaddrinfo(res);
233
234 hostAddr.sin_port = htons(port);
235 hostAddr.sin_family = AF_INET;
236
237 int sent_length = sendto(this->sock, bytes, (int)byteslength, 0, (sockaddr*)&hostAddr, sizeof(hostAddr));
238 if (sent_length == -1)
239 {
240 onError(errno, "Cannot send message to the address.");
241 return -1;
242 }
243
244 return sent_length;
245 }
246 // Send raw bytes to a spesific `host` & `port` with no connection
247 int SendTo(const char* bytes, size_t byteslength, const std::string& host, uint16_t port, FDR_ON_ERROR)
248 {
249 return this->SendTo(bytes, byteslength, host.c_str(), port, onError);
250 }
251 // Send std::string to a spesific `host` & `port` with no connection
252 int SendTo(const std::string& message, const char* host, uint16_t port, FDR_ON_ERROR)
253 {
254 return this->SendTo(message.c_str(), message.length(), host, port, onError);
255 }
256 // Send std::string to a spesific `host` & `port` with no connection
257 int SendTo(const std::string& message, const std::string& host, uint16_t port, FDR_ON_ERROR)
258 {
259 return this->SendTo(message.c_str(), message.length(), host.c_str(), port, onError);
260 }
261
262 // Send raw bytes to the `Connect()`ed server.
263 int Send(const char* bytes, size_t byteslength) { return send(this->sock, bytes, (int)byteslength, 0); }
264 // Send std::string to the `Connect()`ed server.
265 int Send(const std::string& message) { return this->Send(message.c_str(), message.length()); }
266
267 // Connect to a server with raw `uint32_t ipv4` and `uint16_t port` values.
268 void Connect(uint32_t ipv4, uint16_t port, FDR_ON_ERROR)
269 {
270 this->address.sin_family = AF_INET;
271 this->address.sin_port = htons(port);
272 this->address.sin_addr.s_addr = ipv4;
273
274 // Try to connect.
275 int status = connect(this->sock, (const sockaddr* )&this->address, sizeof(sockaddr_in));
276 if (status == -1)
277 {
278 onError(errno, "Connection failed to the host.");
279 return;
280 }
281 }
282 // Connect to a server with `host` address and `port` values.
283 void Connect(const char* host, uint16_t port, FDR_ON_ERROR)
284 {
285 // struct addrinfo hints, *res, *it;
286 // memset(&hints, 0, sizeof(hints));
287 // hints.ai_family = AF_INET;
288 // hints.ai_socktype = SOCK_DGRAM;
289
290 // int status = getaddrinfo(host, NULL, &hints, &res);
291 // if (status != 0)
292 // {
293 // onError(errno, "Invalid address." + std::string(gai_strerror(status)));
294 // return;
295 // }
296
297 // for (it = res; it != NULL; it = it->ai_next)
298 // {
299 // if (it->ai_family == AF_INET)
300 // { // IPv4
301 // memcpy((void* )(&this->address), (void*)it->ai_addr, sizeof(sockaddr_in));
302 // break; // for now, just get first ip (ipv4).
303 // }
304 // }
305
306 // freeaddrinfo(res);
307
308 if((this->address.sin_addr.s_addr =inet_addr(host))==INADDR_NONE){
309 onError(errno, "SendTo: Invalid address. Address type not supported.");
310 }
311 this->Connect((uint32_t)this->address.sin_addr.s_addr, port, onError);
312 }
313 // Connect to a server with `host` address and `port` values.
314 void Connect(const std::string& host, uint16_t port, FDR_ON_ERROR) { this->Connect(host.c_str(), port, onError); }
315
316private:
317 static void Receive(UDPSocket* udpSocket)
318 {
319 char tempBuffer[BUFFER_SIZE_RFLY+1];
320 size_t messageLength;
321 //std::cout<<"Receive thread.."<<std::endl;
322 while ((messageLength = recv(udpSocket->sock, tempBuffer, BUFFER_SIZE_RFLY, 0)) != -1)
323 {
324 //std::cout<<"Receive Msg.."<<std::endl;
325 tempBuffer[messageLength] = '\0';
326 if (udpSocket->onMessageReceived)
327 udpSocket->onMessageReceived(std::string(tempBuffer, messageLength), ipToString(udpSocket->address), ntohs(udpSocket->address.sin_port));
328
329 if (udpSocket->onRawMessageReceived)
330 udpSocket->onRawMessageReceived(tempBuffer, messageLength, ipToString(udpSocket->address), ntohs(udpSocket->address.sin_port));
331 }
332 }
333
334 static void ReceiveFrom(UDPSocket* udpSocket)
335 {
336
337 sockaddr_in hostAddr;
338 socklen_t hostAddrSize = sizeof(hostAddr);
339
340 char tempBuffer[BUFFER_SIZE_RFLY+1];
341 size_t messageLength;
342 //std::cout<<"ReceiveFrom thread.."<<std::endl;
343 while ((messageLength = recvfrom(udpSocket->sock, tempBuffer, BUFFER_SIZE_RFLY, 0, (sockaddr* )&hostAddr, &hostAddrSize)) != -1)
344 {
345 //std::cout<<"Receive Msg.."<<std::endl;
346 tempBuffer[messageLength] = '\0';
347 if (udpSocket->onMessageReceived)
348 udpSocket->onMessageReceived(std::string(tempBuffer, messageLength), ipToString(hostAddr), ntohs(hostAddr.sin_port));
349
350 if (udpSocket->onRawMessageReceived)
351 udpSocket->onRawMessageReceived(tempBuffer, messageLength, ipToString(hostAddr), ntohs(hostAddr.sin_port));
352 //std::cout<<"ReceiveFrom thread.."<<tempBuffer<<messageLength<<std::endl;
353 }
354 }
355};
356
357
358class UDPServer : public UDPSocket
359{
360public:
361 // filter udp data according to ip
362 bool needFilter=false;
363 // Bind the custom address & port of the server.
364 void Bind(const char* addressin, uint16_t port, FDR_ON_ERROR)
365 {
366 // int status = inet_pton(AF_INET, addressin, &this->address.sin_addr);
367 // switch (status) {
368 // case -1:
369 // onError(errno, "Invalid address. Address type not supported.");
370 // return;
371 // case 0:
372 // onError(errno, "AF_INET is not supported. Please send message to developer.");
373 // return;
374 // default:
375 // break;
376 // }
377
378
379 if((this->address.sin_addr.s_addr =inet_addr(addressin))==INADDR_NONE){
380 onError(errno, "Invalid address. Address type not supported.");
381 }
382 //this->address.sin_addr =inet_addr(addressin);
383 this->address.sin_family = AF_INET;
384 this->address.sin_port = htons(port);
385
386
387 int status;
388 //set recv buffer and reuseIP
389#ifndef __linux__
390 bool bOpt = true;
391 status = setsockopt(this->sock, SOL_SOCKET, SO_REUSEADDR, (char*)&bOpt, sizeof(bOpt));
392 if (status == -1)
393 {
394 onError(errno, "Cannot set SO_REUSEADDR the socket.");
395 return;
396 }
397 // int rcvBufSize=602400;
398 // status = setsockopt(this->sock, SOL_SOCKET, SO_RCVBUF, (char*)&rcvBufSize, sizeof(rcvBufSize));
399 // {
400 // onError(errno, "Cannot set SO_RCVBUF the socket.");
401 // return;
402 // }
403
404#else
405 int flag0 = 1;
406 setsockopt(this->sock, SOL_SOCKET, SO_REUSEADDR, &flag0, sizeof(flag0) );
407 // int rcvBufSize=602400;
408 // setsockopt(this->sock, SOL_SOCKET, SO_RCVBUF, &rcvBufSize, sizeof(rcvBufSize));
409#endif
410
411 status = bind(this->sock, (const sockaddr*)&this->address, sizeof(this->address));
412 if (status == -1)
413 {
414 onError(errno, "Cannot bind the socket.");
415 return;
416 }
417
418 //this->StartRecvThread();
419 }
420
421 // Bind the address(0.0.0.0) & port of the server.
422 void Bind(uint16_t port, FDR_ON_ERROR)
423 {
424 //std::cout<<"Bind.."<<std::endl;
425 this->Bind("0.0.0.0", port, onError);
426 }
427
428 // For Sim, Bind 127.0.0.1 for Sim.
429 // For Real, if static ip "192.168.151.168" exist, bind it;
430 // else, bind a non "0.0.0.0" static ip;
431 // else, bind "0.0.0.0".
432 void BindAuto(bool isReal, uint16_t port, FDR_ON_ERROR)
433 {
434 std::cout<<"Bind Auto, with ip:\t";
435 if (isReal){
436 needFilter = true;
437 std::vector<std::string> staticIPs = getStaticIPAddresses();
438 std::string targetIP = "192.168.151.168";
439 auto it = std::find(staticIPs.begin(), staticIPs.end(), targetIP);
440 if (it != staticIPs.end()) {
441 this->Bind("192.168.151.168", port, onError);
442 std::cout<<targetIP<<std::endl;
443 } else {
444 std::string bindIP = "0.0.0.0";
445 for (const auto& ip : staticIPs) {
446 if (ip != "0.0.0.0") {
447 bindIP = ip;
448 break;
449 }
450 }
451 this->Bind(bindIP.c_str(), port, onError);
452 std::cout<<bindIP<<std::endl;
453 }
454 } else{
455 this->Bind("127.0.0.1", port, onError);
456 std::cout<<"127.0.0.1"<<std::endl;
457 }
458 }
459
460 // SET Multicast IP and add to group
461 void setMulticast(const char* GROUP_IP, FDR_ON_ERROR)
462 {
463
464 struct ip_mreq vmreq;
465
466 if((vmreq.imr_multiaddr.s_addr =inet_addr(GROUP_IP))==INADDR_NONE){
467 onError(errno, "setMulticast: Invalid address. Address type not supported.");
468 }
469 if((vmreq.imr_interface.s_addr =inet_addr("0.0.0.0"))==INADDR_NONE){
470 onError(errno, "setMulticast: Invalid address. Address type not supported.");
471 }
472
473 // inet_pton(AF_INET, GROUP_IP, &vmreq.imr_multiaddr);
474 // inet_pton(AF_INET, "0.0.0.0", &vmreq.imr_interface);
475
476#ifndef __linux__
477 int status = setsockopt(this->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&vmreq, sizeof(vmreq));
478#else
479 int status = setsockopt(this->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &vmreq, sizeof(vmreq));
480#endif
481
482 if(status == -1)
483 {
484 onError(errno, "setsockopt(IP_ADD_MEMBERSHIP) failed.");
485 return;
486 }
487 }
488
489 // Enable or disable the SO_BROADCAST flag
490 void setBroadcast(bool value, FDR_ON_ERROR)
491 {
492 int broadcast = static_cast<int>(value);
493#ifndef __linux__
494 int status = setsockopt(this->sock, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, sizeof broadcast);
495#else
496 int status = setsockopt(this->sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast);
497#endif
498 if (status == -1)
499 {
500 onError(errno, "setsockopt(SO_BROADCAST) failed.");
501 return;
502 }
503 }
504
505 int RecvNoblock(char * buf, std::string &ip, int &port,int maxrecvlen=BUFFER_SIZE_RFLY)
506 {
507 if(!this->hasSetNoblock){
508 nonblockingsocket(this->sock);
509 this->hasSetNoblock=true;
510 }
511 int req_len=0;
512 int recvlen=0;
513 sockaddr_in hostAddr;
514 socklen_t hostAddrSize = sizeof(hostAddr);
515
516#ifndef __linux__
517 recvlen=recvfrom(this->sock, buf, maxrecvlen, 0, (struct sockaddr *)&hostAddr, &hostAddrSize);
518#else
519 recvlen=recvfrom(this->sock, buf, maxrecvlen, MSG_DONTWAIT, (struct sockaddr *)&hostAddr, (socklen_t *)(&hostAddrSize));
520#endif
521 if(recvlen>0){
522 ip=ipToString(hostAddr);
523 port = ntohs(hostAddr.sin_port);
524 buf[recvlen] = '\0';
525 }
526 return recvlen;
527 }
528
529
530};
定义 rfly_udp.h:40
定义 rfly_udp.h:359
定义 rfly_udp.h:160