Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
UDPServer.cc
1 #include "UDPServer.hh"
2 #include<Base/Common/W32Compat.hh>
3 
4 #ifdef WIN32
5 # include <winsock.h>
6 # include <io.h>
7 #else
8 # include <sys/socket.h>
9 # include <sys/types.h>
10 # include <arpa/inet.h>
11 # include <netdb.h>
12 #endif
13 
14 #include <cstdlib>
15 #include <string>
16 #include <cstring>
17 #include <iostream>
18 #include <cstdio>
19 #include <Base/Debug/Error.hh>
20 #include <Base/Debug/TimeMeasure.hh>
21 
22 #include "errno.h"
23 
24 #include <Base/Common/BIASpragma.hh>
25 
26 using namespace std;
27 using namespace BIAS;
28 
29 UDPServer::UDPServer() {
30  socket_descriptor_ = 0;
31  // Prepare the send buffer
32  send_buffer_ = new char[UDP_PACKAGE_SIZE];
33  // Number of the first message to be sent
34  message_counter_ = 0;
35  TCPinsteadOfUDP_ = false;
36  Throttle_=1;
37 } // constructor
38 
39 
40 
41 UDPServer::~UDPServer() {
42  delete[] send_buffer_;
43  Disconnect();
44 } // destructor
45 
46 
47 int UDPServer::Send(const char *message, const size_t message_size)
48 {
49  BIASCDOUT(D_UDP_SEND,"Send: "<<message_size<<endl);
51  if (socket_descriptor_ <= 0) {
52  BIASERR("UDPServer:send(): not connected. Use Connect()");
53  return -1;
54  }
55 
56  // Convert the beginning of the send buffer to an message frame header
57  message_frame_header* mfh = (message_frame_header*) send_buffer_;
58 
59  // Save the message_number
60  BIASCDOUT(D_UDP_SEND,"Message counter: "<<message_counter_<<endl);
61  mfh->message_number = message_counter_++;
62  if (message_counter_ > maxMessageNumber)
63  message_counter_ = 0;
64 
65  // Calculate the necessary number of frames to send the message
66  // with the message header at the beginning of each udp package
67  register int message_frames_total;
68  message_frames_total = (int)message_size / (UDP_PACKAGE_SIZE - sizeof(message_frame_header)) + 1;
69  BIASCDOUT(D_UDP_SEND,"Message frames to send image: "<<message_frames_total<<endl);
70 
71  if ( ( message_size % (UDP_PACKAGE_SIZE - sizeof(message_frame_header)) )==0)
72  message_frames_total--;
73 
74  MessageSize_ = (unsigned int)message_size +
75  message_frames_total*sizeof(message_frame_header);
76 
77  // Write the number of message frames into the message frame header
78  mfh->message_frames_total = message_frames_total;
79 
80  // Calculate the start position for the message data in the send buffer
81  char* data_start = send_buffer_ + sizeof(message_frame_header);
82 
83 
84  // Calculate the available space for data
85  int data_length = UDP_PACKAGE_SIZE - sizeof(message_frame_header);
86 
87  // Real size of message data put into the send buffer (changes only at the last message frame)
88  int actual_data_length = data_length;
89 // t1.Start();
90  //
91  // Now we can start sending udp packages
92  //
93  for (int i = 0; i < message_frames_total; i++) {
94 
95  // Is it the last frame?
96  if ( i == (message_frames_total - 1) ) {
97  actual_data_length = (int)message_size - (i * data_length);
98  }
99 
100  // Copy the message data into the send buffer
101  memcpy(data_start, &((char*) message)[i * data_length], actual_data_length);
102 
103  // Save the current frame number in the frame header
104  mfh->message_frame_number = i;
105  int bytes_sent;
106  if (TCPinsteadOfUDP_) {
107  bytes_sent = send( socket_descriptor_,
108  send_buffer_,
109  sizeof(message_frame_header) + actual_data_length,
110  0);
111 
112  }
113  else {
114  // Send the send buffer using the udp socket
115  bytes_sent = sendto( socket_descriptor_,
116  send_buffer_,
117  sizeof(message_frame_header) + actual_data_length,
118  0,
119  (struct sockaddr*) &UDPSockAddr_,
120  sizeof(UDPSockAddr_));
121  BIASCDOUT(D_UDP_SEND,"Sendto in "<<i<<" th iteration."<<endl);
122  }
123  if (bytes_sent < 0) {
124  syscallerror("Failed to send via UDP Socket. Stop sending packages!");
125 #ifdef WIN32
126  int error = WSAGetLastError();
127 #endif
128  return -1;
129  }
130  if (Throttle_ >0)
131  biasusleep(Throttle_ * 1000); // wait a bit, to avoid UDP packet collisions
132  // cout <<"Send frame "<<i<<" with size: "<<sizeof(message_frame_header)
133  // + actual_data_length<<endl;
134  } // for
135  // t1.Stop();
136  // cout <<"throttle: "<<Throttle_<<" frames per message: "<<message_frames_total<<" time [ms]: "<<t1.GetRealTime()/1000<<endl;
137  // t1.Reset();
138  return mfh->message_frames_total;
139 
140 } // send()
141 
142 
143 int UDPServer::SendToUDP (const char* message, const size_t message_size, const char* ipAddress, int port) {
144 
145  if (TCPinsteadOfUDP_) {
146  BIASERR("UDPServer: SendToUDP is only usable with UDP sockets");
147  return -1;
148  }
149 
150  BIASCDOUT(D_UDP_SEND,"SendToUDP: "<< message_size << endl);
151  if (socket_descriptor_ <= 0) {
152  BIASERR("UDPServer: SendToUDP(): invalid socket descriptor, call Connect before sending");
153  return -1;
154  }
155 
156  // Convert the beginning of the send buffer to an message frame header
157  message_frame_header* mfh = (message_frame_header*) send_buffer_;
158 
159  // Save the message_number
160  BIASCDOUT(D_UDP_SEND,"Message counter: "<<message_counter_<<endl);
161  mfh->message_number = message_counter_++;
162  if (message_counter_ > maxMessageNumber)
163  message_counter_ = 0;
164 
165  // Calculate the necessary number of frames to send the message
166  // with the message header at the beginning of each udp package
167  register int message_frames_total;
168  message_frames_total = (int)message_size / (UDP_PACKAGE_SIZE - sizeof(message_frame_header)) + 1;
169  BIASCDOUT(D_UDP_SEND,"Message frames to send image: "<<message_frames_total<<endl);
170 
171  if ( ( message_size % (UDP_PACKAGE_SIZE - sizeof(message_frame_header)) ) == 0)
172  message_frames_total--;
173 
174  MessageSize_ = (unsigned int)message_size +
175  message_frames_total*sizeof(message_frame_header);
176 
177  // Write the number of message frames into the message frame header
178  mfh->message_frames_total = message_frames_total;
179 
180  // Calculate the start position for the message data in the send buffer
181  char* data_start = send_buffer_ + sizeof(message_frame_header);
182 
183 
184  // Calculate the available space for data
185  int data_length = UDP_PACKAGE_SIZE - sizeof(message_frame_header);
186 
187  // Real size of message data put into the send buffer (changes only at the last message frame)
188  int actual_data_length = data_length;
189 
190  // Now we can start sending udp packages
191  for (int i = 0; i < message_frames_total; i++) {
192 
193  // Is it the last frame?
194  if ( i == (message_frames_total - 1) ) {
195  actual_data_length = (int)message_size - (i * data_length);
196  }
197 
198  // Copy the message data into the send buffer
199  memcpy(data_start, &((char*) message)[i * data_length], actual_data_length);
200 
201  // Save the current frame number in the frame header
202  mfh->message_frame_number = i;
203  int bytes_sent;
204 
205  // Prepare structure for remote host sending
206  struct sockaddr_in UDPHostAddr;
207  hostent* remoteHost;
208  unsigned int addr;
209 
210  if (strlen(ipAddress) < 16) {
211 
212  addr = inet_addr(ipAddress);
213  if((remoteHost = gethostbyaddr((char *) &addr, 4, AF_INET)) == NULL) {
214  syscallerror("Could not retrieve host information for ip address: " << ipAddress);
215  exit(-1);
216  }
217  } else {
218  syscallerror("Error: supplied host IPv4 address string is too large.");
219  exit(255);
220  }
221 
222  char* ip = inet_ntoa(*((struct in_addr *)remoteHost->h_addr));
223 
224  memset(&UDPHostAddr, 0, sizeof(UDPHostAddr));
225  UDPHostAddr.sin_family = AF_INET;
226  UDPHostAddr.sin_addr.s_addr = inet_addr(ip);
227  UDPHostAddr.sin_port = htons(port);
228 
229  // Send the send buffer using the udp socket
230  bytes_sent = sendto(socket_descriptor_, send_buffer_,
231  sizeof(message_frame_header) + actual_data_length, 0,
232  (struct sockaddr*) &UDPHostAddr, sizeof(UDPHostAddr));
233  BIASCDOUT(D_UDP_SEND,"Sendto in "<<i<<" th iteration."<<endl);
234 
235 if (bytes_sent < 0) {
236  syscallerror("Failed to send via UDP Socket. Stop sending packages!");
237 #ifdef WIN32
238  int error = WSAGetLastError();
239 #endif
240  return -1;
241  }
242  if (Throttle_ >0)
243  biasusleep(Throttle_ * 1000); // wait a bit, to avoid UDP packet collisions
244  } // for
245  return mfh->message_frames_total;
246 }
247 
248 
249 int UDPServer::Connect(const char* ipaddress_or_name, int port, bool UseTCP )
250 {
251  TCPinsteadOfUDP_ = UseTCP;
252  hostent* remoteHost;
253 
254 #ifdef WIN32
255  WORD wVersionRequested;
256  WSADATA wsaData;
257  int err=0;
258  /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
259  wVersionRequested = MAKEWORD(2, 2);
260  err = WSAStartup(wVersionRequested, &wsaData);
261  if (err != 0) {
262  /* Tell the user that we could not find a usable */
263  /* Winsock DLL. */
264  syscallerror("WSAStartup failed with error: "<< err);
265  return 1;
266  }
267 #endif
268 
269  unsigned int addr;
270  if (!isalpha(ipaddress_or_name[0])) /* host address is an IPv4 address */
271  {
272  if (strlen(ipaddress_or_name) < 16)
273  {
274  addr = inet_addr(ipaddress_or_name);
275  if((remoteHost = gethostbyaddr((char *) &addr, 4, AF_INET))==NULL){
276  syscallerror("Could not retrieve IP address of client name: "<<ipaddress_or_name);
277  exit(-1);
278  }
279  }
280  else
281  {
282  syscallerror("error: Supplied host IPv4 address string is too large.");
283  exit(255);
284  }
285  }
286  else{
287  if ( (remoteHost = gethostbyname(ipaddress_or_name) ) == NULL) {
288  syscallerror("Could not retrieve IP address of client name: "<<ipaddress_or_name);
289  exit(-1);
290  }
291  }
292 
293  char* ipaddress = inet_ntoa(*((struct in_addr *)remoteHost->h_addr));
294 
295  // Set up the destination address
296  memset( &UDPSockAddr_, 0, sizeof(UDPSockAddr_));
297  UDPSockAddr_.sin_family = AF_INET;
298  UDPSockAddr_.sin_addr.s_addr = inet_addr(ipaddress);
299  UDPSockAddr_.sin_port = htons(port);
300 
301  if (TCPinsteadOfUDP_) {
302  int res;
303  socket_descriptor_ = socket(AF_INET, SOCK_STREAM,0);
304  do {
305  res=connect( socket_descriptor_, (sockaddr*)&UDPSockAddr_,
306  sizeof(UDPSockAddr_));
307  if (res <0) perror("Failed to connect");
308  biassleep(1);
309  }
310  while (res <0);
311  }
312  else
313  socket_descriptor_ = socket(AF_INET, SOCK_DGRAM,0);
314  if (socket_descriptor_ < 0) {
315  cerr << "UDPServer: An error has occured while creating a UDP" <<
316  " socket. Could not send any data.\n";
317  return -1;
318  }
319 
320  return 0;
321 }
322 
323 
324 int UDPServer::Connect(int port, bool UseTCP )
325 {
326  TCPinsteadOfUDP_ = UseTCP;
327 #ifdef WIN32
328  WORD wVersionRequested;
329  WSADATA wsaData;
330  int err=0;
331  /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
332  wVersionRequested = MAKEWORD(2, 2);
333  err = WSAStartup(wVersionRequested, &wsaData);
334  if (err != 0) {
335  /* Tell the user that we could not find a usable */
336  /* Winsock DLL. */
337  syscallerror("WSAStartup failed with error: "<< err);
338  return 1;
339  }
340 #endif
341 
342  // Set up the destination address
343  memset( &UDPSockAddr_, 0, sizeof(UDPSockAddr_));
344  UDPSockAddr_.sin_family = AF_INET;
345  UDPSockAddr_.sin_addr.s_addr = INADDR_ANY; //INADDR_BROADCAST; //ANY or BROADCAST??
346  UDPSockAddr_.sin_port = htons(port);
347 
348  if (TCPinsteadOfUDP_) {
349  int res;
350  socket_descriptor_ = socket(AF_INET, SOCK_STREAM,0);
351  do {
352  res=connect( socket_descriptor_, (sockaddr*)&UDPSockAddr_,
353  sizeof(UDPSockAddr_));
354  if (res <0) perror("Failed to connect");
355  biassleep(1);
356  }
357  while (res <0);
358  }
359  else
360  socket_descriptor_ = socket(AF_INET, SOCK_DGRAM,0);
361  if (socket_descriptor_ < 0) {
362  cerr << "UDPServer: An error has occured while creating a UDP" <<
363  " socket. Could not send any data.\n";
364  return -1;
365  }
366  return 0;
367 }
368 
369 int UDPServer::Disconnect()
370 {
371  // Shutdown the socket
372  if(socket_descriptor_ >=0){
373 
374 #ifndef WIN32
375  close(socket_descriptor_);
376 #else
377  closesocket(socket_descriptor_);
378  WSACleanup();
379 #endif
380 
381  }
382  return 0;
383 }
const int maxMessageNumber
Header for sending images over UDP connections.
class TimeMeasure contains functions for timing real time and cpu time.
Definition: TimeMeasure.hh:111
const int UDP_PACKAGE_SIZE