forked from quatrix/flying-karir
/
UDP_Sock.cpp
150 lines (126 loc) · 3.71 KB
/
UDP_Sock.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <iostream>
#include <string>
#include <sstream>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> /* close() */
#include <string.h> /* memset() */
#include "UDP_Sock.hpp"
#include "NetEvent.hpp"
#include "Ship.hpp"
#define PORT 1500
#define SOCKET_ERROR -1
#define FLAGS 0
#define TIMEOUT 0 // ms
int Sock::isReadable(int sd,int * error) { // milliseconds
fd_set socketReadSet;
FD_ZERO(&socketReadSet);
FD_SET(sd,&socketReadSet);
struct timeval tv;
if (TIMEOUT) {
tv.tv_sec = TIMEOUT / 1000;
tv.tv_usec = (TIMEOUT % 1000) * 1000;
} else {
tv.tv_sec = 0;
tv.tv_usec = 0;
} // if
if (select(sd+1,&socketReadSet,0,0,&tv) == SOCKET_ERROR) {
*error = 1;
return 0;
} // if
*error = 0;
return FD_ISSET(sd,&socketReadSet) != 0;
} /* isReadable */
void Sock::snd(const NetEvent& serial)
{
std::ostringstream os;
boost::archive::text_oarchive oa(os);
oa << serial;
std::string message = os.str();
if (remoteDefined) {
rc = sendto(sd, message.c_str(), message.size(), FLAGS,
(struct sockaddr *) &remoteAddr, sizeof(remoteAddr));
if(rc<0) {
std::cout << "cannot send data " << std::endl;
close(sd);
return;
}
}
}
bool Sock::rcv(NetEvent& serial)
{
memset(msg,0x0,MAX_MSG);
remoteLen = sizeof(remoteAddr);
if (!isReadable(sd,&error)) return false;
/* receive echoed message */
n = recvfrom(sd, msg, MAX_MSG, FLAGS,
(struct sockaddr *) &remoteAddr, &remoteLen);
if(n<0) {
std::cerr << "cannot receive data\n";
return false;
}
remoteDefined = true;
/* print received message */
std::cout << "echo from " << inet_ntoa(remoteAddr.sin_addr)
<< " UDP:" << ntohs(remoteAddr.sin_port)
<< ": " << msg << std::endl;
std::istringstream is(std::string(msg, strlen(msg)));
boost::archive::text_iarchive ia(is);
ia >> serial;
return true;
}
bool Sock::create_server() {
/* socket creation */
sd=socket(AF_INET, SOCK_DGRAM, 0);
if(sd<0) {
std::cerr << "cannot open socket \n";
return false;
}
remoteDefined = false;
/* bind local server port */
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
localAddr.sin_port = htons(PORT);
rc = bind (sd, (struct sockaddr *) &localAddr,sizeof(localAddr));
if(rc<0) {
std::cerr << "cannot bind port number " << PORT << std::endl;
return false;
}
std::cout << "waiting for data on port udp " << PORT << std::endl;
return true;
}
bool Sock::create_client(std::string host) {
h = gethostbyname(host.c_str());
if(h==NULL) {
std::cerr << "unknown host: " << host << std::endl;
return false;
}
std::cout << "starting to send data to " << h->h_name << " IP: " <<
inet_ntoa(*(struct in_addr *)h->h_addr_list[0]) << std::endl;
remoteAddr.sin_family = h->h_addrtype;
memcpy((char *) &remoteAddr.sin_addr.s_addr,
h->h_addr_list[0], h->h_length);
remoteAddr.sin_port = htons(PORT);
remoteDefined = true;
/* socket creation */
sd = socket(AF_INET,SOCK_DGRAM,0);
if(sd<0) {
std::cerr << "cannot open socket\n";
return false;
}
/* bind any port */
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
localAddr.sin_port = htons(0);
rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr));
if(rc<0) {
std::cerr << "cannot bind port\n";
return false;
}
return true;
}