RflySimSDK v3.05
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#define nonblockingsocket(s) {unsigned long ctl = 1;}
13#elif _WIN32
14#include <winsock2.h>
15#include <ws2tcpip.h>
16#pragma comment(lib,"ws2_32.lib")
17#define nonblockingsocket(s) {unsigned long ctl = 1;ioctlsocket( s, FIONBIO, &ctl );}
18#endif
19
20#include <string>
21#include <functional>
22#include <cerrno>
23#include <thread>
24#include <iostream>
25
26#define FDR_UNUSED(expr){ (void)(expr); }
27#define FDR_ON_ERROR std::function<void(int, std::string)> onError = [](int errorCode, std::string errorMessage){FDR_UNUSED(errorCode); FDR_UNUSED(errorMessage)}
28
29#ifndef BUFFER_SIZE_RFLY
30#define BUFFER_SIZE_RFLY 1024
31#endif
32
33
35{
36public:
37 enum SocketType
38 {
39 TCP = SOCK_STREAM,
40 UDP = SOCK_DGRAM
41 };
42 sockaddr_in address;
43 //char udpBuf[BUFFER_SIZE_RFLY+1];
44 //std::string RecvIP;
45 //uint16_t RecvPort;
46 std::string remoteAddress() const { return ipToString(this->address); }
47 int remotePort() const { return ntohs(this->address.sin_port); }
48 int fileDescriptor() const { return this->sock; }
49
50protected:
51 int sock = 0;
52
53 bool hasSetNoblock=false;
54
55
56
57 //bool isStopRec=false;
58
59 // Get std::string value of the IP from a `sockaddr_in` address struct
60 static std::string ipToString(const sockaddr_in& addr)
61 {
62 char ip[INET_ADDRSTRLEN];
63
64 struct sockaddr_in in;
65 memset(&in, 0, sizeof(in));
66 in.sin_family = AF_INET;
67 memcpy(&in.sin_addr, &(addr.sin_addr), sizeof(struct in_addr));
68 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), ip, INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
69
70 return std::string(ip);
71 }
72
73 BaseSocket(FDR_ON_ERROR, SocketType sockType = TCP, int socketId = -1)
74 {
75 if (socketId == -1)
76 {
77 this->sock = (int)socket(AF_INET, sockType, 0);
78
79 if ( this->sock == -1 )
80 {
81 onError(errno, "Socket creating error.");
82 }
83 }
84 else
85 {
86 this->sock = socketId;
87 }
88 int rcvBufSize=102400*10;
89#ifndef __linux__
90 setsockopt(this->sock, SOL_SOCKET, SO_RCVBUF, (char*)&rcvBufSize, sizeof(rcvBufSize));
91 rcvBufSize=102400*10;
92 setsockopt(this->sock, SOL_SOCKET, SO_SNDBUF, (char*)&rcvBufSize, sizeof(rcvBufSize));
93#else
94 setsockopt(this->sock, SOL_SOCKET, SO_RCVBUF, &rcvBufSize, sizeof(rcvBufSize));
95 rcvBufSize=102400*10;
96 setsockopt(this->sock, SOL_SOCKET, SO_SNDBUF, &rcvBufSize, sizeof(rcvBufSize));
97#endif
98
99
100
101 }
102 virtual ~BaseSocket(){}
103};
104
105
106class UDPSocket : public BaseSocket
107{
108public:
109 std::function<void(std::string, std::string, uint16_t)> onMessageReceived;
110 std::function<void(const char*, size_t, std::string, uint16_t)> onRawMessageReceived;
111 bool isUseConnect = false;
112 //std::thread* mT;
113
114 void Close() {
115
116#ifndef __linux__
117 closesocket(this->sock);
118#else
119 shutdown(this->sock, SHUT_RDWR);
120 close(this->sock);
121#endif
122 }
123
124
125 explicit UDPSocket(bool useConnect = false, FDR_ON_ERROR, int socketId = -1): BaseSocket(onError, SocketType::UDP, socketId)
126 {
127 this->isUseConnect=useConnect;
128
129 }
130
131 void StartRecvThread()
132 {
133
134 if (this->isUseConnect)
135 {
136 std::thread t(Receive, this); // usage with Connect()
137 t.detach();
138 }
139 else
140 {
141 std::thread t(ReceiveFrom, this);
142 t.detach();
143 }
144
145 //this->isStopRec=false;
146 }
147
148 // Send raw bytes to a spesific `host` & `port` with no connection
149 int SendTo(const char* bytes, size_t byteslength, const char* host, uint16_t port, FDR_ON_ERROR)
150 {
151 sockaddr_in hostAddr;
152
153 //int status;
154 if((hostAddr.sin_addr.s_addr =inet_addr(host))==INADDR_NONE){
155 onError(errno, "SendTo: Invalid address. Address type not supported.");
156 }
157
158 // struct addrinfo hints, *res, *it;
159 // memset(&hints, 0, sizeof(hints));
160 // hints.ai_family = AF_INET;
161 // hints.ai_socktype = SOCK_DGRAM;
162
163 // int status;
164 // if ((status = getaddrinfo(host, NULL, &hints, &res)) != 0)
165 // {
166 // onError(errno, "Invalid address." + std::string(gai_strerror(status)));
167 // return -1;
168 // }
169
170 // for (it = res; it != NULL; it = it->ai_next)
171 // {
172 // if (it->ai_family == AF_INET)
173 // { // IPv4
174 // memcpy((void* )(&hostAddr), (void* )it->ai_addr, sizeof(sockaddr_in));
175 // break; // for now, just get first ip (ipv4).
176 // }
177 // }
178
179 // freeaddrinfo(res);
180
181 hostAddr.sin_port = htons(port);
182 hostAddr.sin_family = AF_INET;
183
184 int sent_length = sendto(this->sock, bytes, (int)byteslength, 0, (sockaddr*)&hostAddr, sizeof(hostAddr));
185 if (sent_length == -1)
186 {
187 onError(errno, "Cannot send message to the address.");
188 return -1;
189 }
190
191 return sent_length;
192 }
193 // Send raw bytes to a spesific `host` & `port` with no connection
194 int SendTo(const char* bytes, size_t byteslength, const std::string& host, uint16_t port, FDR_ON_ERROR)
195 {
196 return this->SendTo(bytes, byteslength, host.c_str(), port, onError);
197 }
198 // Send std::string to a spesific `host` & `port` with no connection
199 int SendTo(const std::string& message, const char* host, uint16_t port, FDR_ON_ERROR)
200 {
201 return this->SendTo(message.c_str(), message.length(), host, port, onError);
202 }
203 // Send std::string to a spesific `host` & `port` with no connection
204 int SendTo(const std::string& message, const std::string& host, uint16_t port, FDR_ON_ERROR)
205 {
206 return this->SendTo(message.c_str(), message.length(), host.c_str(), port, onError);
207 }
208
209 // Send raw bytes to the `Connect()`ed server.
210 int Send(const char* bytes, size_t byteslength) { return send(this->sock, bytes, (int)byteslength, 0); }
211 // Send std::string to the `Connect()`ed server.
212 int Send(const std::string& message) { return this->Send(message.c_str(), message.length()); }
213
214 // Connect to a server with raw `uint32_t ipv4` and `uint16_t port` values.
215 void Connect(uint32_t ipv4, uint16_t port, FDR_ON_ERROR)
216 {
217 this->address.sin_family = AF_INET;
218 this->address.sin_port = htons(port);
219 this->address.sin_addr.s_addr = ipv4;
220
221 // Try to connect.
222 int status = connect(this->sock, (const sockaddr* )&this->address, sizeof(sockaddr_in));
223 if (status == -1)
224 {
225 onError(errno, "Connection failed to the host.");
226 return;
227 }
228 }
229 // Connect to a server with `host` address and `port` values.
230 void Connect(const char* host, uint16_t port, FDR_ON_ERROR)
231 {
232 // struct addrinfo hints, *res, *it;
233 // memset(&hints, 0, sizeof(hints));
234 // hints.ai_family = AF_INET;
235 // hints.ai_socktype = SOCK_DGRAM;
236
237 // int status = getaddrinfo(host, NULL, &hints, &res);
238 // if (status != 0)
239 // {
240 // onError(errno, "Invalid address." + std::string(gai_strerror(status)));
241 // return;
242 // }
243
244 // for (it = res; it != NULL; it = it->ai_next)
245 // {
246 // if (it->ai_family == AF_INET)
247 // { // IPv4
248 // memcpy((void* )(&this->address), (void*)it->ai_addr, sizeof(sockaddr_in));
249 // break; // for now, just get first ip (ipv4).
250 // }
251 // }
252
253 // freeaddrinfo(res);
254
255 if((this->address.sin_addr.s_addr =inet_addr(host))==INADDR_NONE){
256 onError(errno, "SendTo: Invalid address. Address type not supported.");
257 }
258 this->Connect((uint32_t)this->address.sin_addr.s_addr, port, onError);
259 }
260 // Connect to a server with `host` address and `port` values.
261 void Connect(const std::string& host, uint16_t port, FDR_ON_ERROR) { this->Connect(host.c_str(), port, onError); }
262
263private:
264 static void Receive(UDPSocket* udpSocket)
265 {
266 char tempBuffer[BUFFER_SIZE_RFLY+1];
267 size_t messageLength;
268 //std::cout<<"Receive thread.."<<std::endl;
269 while ((messageLength = recv(udpSocket->sock, tempBuffer, BUFFER_SIZE_RFLY, 0)) != -1)
270 {
271 //std::cout<<"Receive Msg.."<<std::endl;
272 tempBuffer[messageLength] = '\0';
273 if (udpSocket->onMessageReceived)
274 udpSocket->onMessageReceived(std::string(tempBuffer, messageLength), ipToString(udpSocket->address), ntohs(udpSocket->address.sin_port));
275
276 if (udpSocket->onRawMessageReceived)
277 udpSocket->onRawMessageReceived(tempBuffer, messageLength, ipToString(udpSocket->address), ntohs(udpSocket->address.sin_port));
278 }
279 }
280
281 static void ReceiveFrom(UDPSocket* udpSocket)
282 {
283
284 sockaddr_in hostAddr;
285 socklen_t hostAddrSize = sizeof(hostAddr);
286
287 char tempBuffer[BUFFER_SIZE_RFLY+1];
288 size_t messageLength;
289 //std::cout<<"ReceiveFrom thread.."<<std::endl;
290 while ((messageLength = recvfrom(udpSocket->sock, tempBuffer, BUFFER_SIZE_RFLY, 0, (sockaddr* )&hostAddr, &hostAddrSize)) != -1)
291 {
292 //std::cout<<"Receive Msg.."<<std::endl;
293 tempBuffer[messageLength] = '\0';
294 if (udpSocket->onMessageReceived)
295 udpSocket->onMessageReceived(std::string(tempBuffer, messageLength), ipToString(hostAddr), ntohs(hostAddr.sin_port));
296
297 if (udpSocket->onRawMessageReceived)
298 udpSocket->onRawMessageReceived(tempBuffer, messageLength, ipToString(hostAddr), ntohs(hostAddr.sin_port));
299 //std::cout<<"ReceiveFrom thread.."<<tempBuffer<<messageLength<<std::endl;
300 }
301 }
302};
303
304
305class UDPServer : public UDPSocket
306{
307public:
308 // Bind the custom address & port of the server.
309 void Bind(const char* addressin, uint16_t port, FDR_ON_ERROR)
310 {
311 // int status = inet_pton(AF_INET, addressin, &this->address.sin_addr);
312 // switch (status) {
313 // case -1:
314 // onError(errno, "Invalid address. Address type not supported.");
315 // return;
316 // case 0:
317 // onError(errno, "AF_INET is not supported. Please send message to developer.");
318 // return;
319 // default:
320 // break;
321 // }
322
323
324 if((this->address.sin_addr.s_addr =inet_addr(addressin))==INADDR_NONE){
325 onError(errno, "Invalid address. Address type not supported.");
326 }
327 //this->address.sin_addr =inet_addr(addressin);
328 this->address.sin_family = AF_INET;
329 this->address.sin_port = htons(port);
330
331
332 int status;
333 //set recv buffer and reuseIP
334#ifndef __linux__
335 bool bOpt = true;
336 status = setsockopt(this->sock, SOL_SOCKET, SO_REUSEADDR, (char*)&bOpt, sizeof(bOpt));
337 if (status == -1)
338 {
339 onError(errno, "Cannot set SO_REUSEADDR the socket.");
340 return;
341 }
342 // int rcvBufSize=602400;
343 // status = setsockopt(this->sock, SOL_SOCKET, SO_RCVBUF, (char*)&rcvBufSize, sizeof(rcvBufSize));
344 // {
345 // onError(errno, "Cannot set SO_RCVBUF the socket.");
346 // return;
347 // }
348
349#else
350 int flag0 = 1;
351 setsockopt(this->sock, SOL_SOCKET, SO_REUSEADDR, &flag0, sizeof(flag0) );
352 // int rcvBufSize=602400;
353 // setsockopt(this->sock, SOL_SOCKET, SO_RCVBUF, &rcvBufSize, sizeof(rcvBufSize));
354#endif
355
356 status = bind(this->sock, (const sockaddr*)&this->address, sizeof(this->address));
357 if (status == -1)
358 {
359 onError(errno, "Cannot bind the socket.");
360 return;
361 }
362
363 //this->StartRecvThread();
364 }
365
366 // Bind the address(0.0.0.0) & port of the server.
367 void Bind(uint16_t port, FDR_ON_ERROR)
368 {
369 //std::cout<<"Bind.."<<std::endl;
370 this->Bind("0.0.0.0", port, onError);
371 }
372
373 // SET Multicast IP and add to group
374 void setMulticast(const char* GROUP_IP, FDR_ON_ERROR)
375 {
376
377 struct ip_mreq vmreq;
378
379 if((vmreq.imr_multiaddr.s_addr =inet_addr(GROUP_IP))==INADDR_NONE){
380 onError(errno, "setMulticast: Invalid address. Address type not supported.");
381 }
382 if((vmreq.imr_interface.s_addr =inet_addr("0.0.0.0"))==INADDR_NONE){
383 onError(errno, "setMulticast: Invalid address. Address type not supported.");
384 }
385
386 // inet_pton(AF_INET, GROUP_IP, &vmreq.imr_multiaddr);
387 // inet_pton(AF_INET, "0.0.0.0", &vmreq.imr_interface);
388
389#ifndef __linux__
390 int status = setsockopt(this->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&vmreq, sizeof(vmreq));
391#else
392 int status = setsockopt(this->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &vmreq, sizeof(vmreq));
393#endif
394
395 if(status == -1)
396 {
397 onError(errno, "setsockopt(IP_ADD_MEMBERSHIP) failed.");
398 return;
399 }
400 }
401
402 // Enable or disable the SO_BROADCAST flag
403 void setBroadcast(bool value, FDR_ON_ERROR)
404 {
405 int broadcast = static_cast<int>(value);
406#ifndef __linux__
407 int status = setsockopt(this->sock, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, sizeof broadcast);
408#else
409 int status = setsockopt(this->sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast);
410#endif
411 if (status == -1)
412 {
413 onError(errno, "setsockopt(SO_BROADCAST) failed.");
414 return;
415 }
416 }
417
418 int RecvNoblock(char * buf, std::string &ip, int &port,int maxrecvlen=BUFFER_SIZE_RFLY)
419 {
420 if(!this->hasSetNoblock){
421 nonblockingsocket(this->sock);
422 this->hasSetNoblock=true;
423 }
424 int req_len=0;
425 int recvlen=0;
426 sockaddr_in hostAddr;
427 socklen_t hostAddrSize = sizeof(hostAddr);
428
429#ifndef __linux__
430 recvlen=recvfrom(this->sock, buf, maxrecvlen, 0, (struct sockaddr *)&hostAddr, &hostAddrSize);
431#else
432 recvlen=recvfrom(this->sock, buf, maxrecvlen, MSG_DONTWAIT, (struct sockaddr *)&hostAddr, (socklen_t *)(&hostAddrSize));
433#endif
434 if(recvlen>0){
435 ip=ipToString(hostAddr);
436 port = ntohs(hostAddr.sin_port);
437 buf[recvlen] = '\0';
438 }
439 return recvlen;
440 }
441
442
443};
定义 rfly_udp.h:35
定义 rfly_udp.h:306
定义 rfly_udp.h:107