PageRenderTime 26ms CodeModel.GetById 47ms RepoModel.GetById 0ms app.codeStats 1ms

/src/network/vpServer.cpp

https://github.com/thomas-moulard/visp-deb
C++ | 284 lines | 176 code | 35 blank | 73 comment | 35 complexity | 59ee0965ffa259e6677709a662dc36f8 MD5 | raw file
  1. /****************************************************************************
  2. *
  3. * $Id: vpServer.cpp 4056 2013-01-05 13:04:42Z fspindle $
  4. *
  5. * This file is part of the ViSP software.
  6. * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
  7. *
  8. * This software is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * ("GPL") version 2 as published by the Free Software Foundation.
  11. * See the file LICENSE.txt at the root directory of this source
  12. * distribution for additional information about the GNU GPL.
  13. *
  14. * For using ViSP with software that can not be combined with the GNU
  15. * GPL, please contact INRIA about acquiring a ViSP Professional
  16. * Edition License.
  17. *
  18. * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
  19. *
  20. * This software was developed at:
  21. * INRIA Rennes - Bretagne Atlantique
  22. * Campus Universitaire de Beaulieu
  23. * 35042 Rennes Cedex
  24. * France
  25. * http://www.irisa.fr/lagadic
  26. *
  27. * If you have questions regarding the use of this file, please contact
  28. * INRIA at visp@inria.fr
  29. *
  30. * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  31. * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  32. *
  33. *
  34. * Description:
  35. * TCP Server
  36. *
  37. * Authors:
  38. * Aurelien Yol
  39. *
  40. *****************************************************************************/
  41. #include <visp/vpServer.h>
  42. /*!
  43. Construct a server on the machine launching it.
  44. */
  45. vpServer::vpServer( ) : vpNetwork(), started(false)
  46. {
  47. int protocol = 0;
  48. emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
  49. #ifdef UNIX
  50. if (emitter.socketFileDescriptorEmitter < 0)
  51. #else
  52. if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
  53. #endif
  54. {
  55. vpERROR_TRACE( "vpServer::vpServer(), cannot open socket." );
  56. }
  57. emitter.emitterAdress.sin_family = AF_INET;
  58. emitter.emitterAdress.sin_addr.s_addr = INADDR_ANY;
  59. emitter.emitterAdress.sin_port = 0;
  60. adress = inet_ntoa(emitter.emitterAdress.sin_addr);
  61. port = emitter.emitterAdress.sin_port;
  62. }
  63. /*!
  64. Construct a server on the machine launching it, with a specified port.
  65. \param port_serv : server's port.
  66. */
  67. vpServer::vpServer( const int &port_serv ) : vpNetwork(), started(false)
  68. {
  69. int protocol = 0;
  70. emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
  71. #ifdef UNIX
  72. if (emitter.socketFileDescriptorEmitter < 0)
  73. #else
  74. if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
  75. #endif
  76. {
  77. vpERROR_TRACE( "vpServer::vpServer(const int &port_serv), cannot open socket." );
  78. }
  79. emitter.emitterAdress.sin_family = AF_INET;
  80. emitter.emitterAdress.sin_addr.s_addr = INADDR_ANY; //inet_addr("127.0.0.1");;
  81. emitter.emitterAdress.sin_port = htons( (unsigned short)port_serv );
  82. adress = inet_ntoa(emitter.emitterAdress.sin_addr);
  83. port = port_serv;
  84. }
  85. /*!
  86. Construct a server on the machine at a given adress, with a specified port.
  87. \param adress_serv : server's adress.
  88. \param port_serv : server's port.
  89. */
  90. vpServer::vpServer( const std::string &adress_serv,const int &port_serv ) : vpNetwork(), started(false)
  91. {
  92. int protocol = 0;
  93. emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
  94. #ifdef UNIX
  95. if (emitter.socketFileDescriptorEmitter < 0)
  96. #else
  97. if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
  98. #endif
  99. {
  100. vpERROR_TRACE( "vpServer::vpServer(const std::string &adress_serv,const int &port_serv), cannot open socket." );
  101. }
  102. emitter.emitterAdress.sin_family = AF_INET;
  103. emitter.emitterAdress.sin_addr.s_addr = inet_addr(adress_serv.c_str());
  104. emitter.emitterAdress.sin_port = htons( (unsigned short)port_serv );
  105. adress = adress_serv;
  106. port = port_serv;
  107. }
  108. /*!
  109. Shutdown the server.
  110. */
  111. vpServer::~vpServer()
  112. {
  113. #ifdef UNIX
  114. close( emitter.socketFileDescriptorEmitter );
  115. #else //Win32
  116. closesocket( (unsigned)emitter.socketFileDescriptorEmitter );
  117. #endif
  118. for(unsigned int i = 0 ; i < receptor_list.size() ; i++)
  119. #ifdef UNIX
  120. close( receptor_list[i].socketFileDescriptorReceptor );
  121. #else //Win32
  122. closesocket( (unsigned)receptor_list[i].socketFileDescriptorReceptor );
  123. #endif
  124. }
  125. /*!
  126. Enable the server to wait for clients (on the limit of the maximum limit).
  127. \return True if the server has started, false otherwise.
  128. */
  129. bool vpServer::start()
  130. {
  131. int serverStructLength = sizeof(emitter.emitterAdress);
  132. #ifdef UNIX
  133. int bindResult = bind( emitter.socketFileDescriptorEmitter, (struct sockaddr *) &emitter.emitterAdress, (unsigned)serverStructLength );
  134. #else //Win32
  135. int bindResult = bind( (unsigned)emitter.socketFileDescriptorEmitter, (struct sockaddr *) &emitter.emitterAdress, serverStructLength );
  136. #endif
  137. if( bindResult < 0 )
  138. {
  139. std::cout << "Error id : " << bindResult << std::endl;
  140. std::string errorMessage( "vpServer::vpServer(), cannot bind to port" );
  141. char posrtNumberString[32];
  142. sprintf( posrtNumberString, "%d", port );
  143. errorMessage += " ";
  144. errorMessage += posrtNumberString;
  145. errorMessage += " The port may be already used.";
  146. vpERROR_TRACE( errorMessage.c_str() );
  147. return false;
  148. }
  149. #ifdef SO_NOSIGPIPE
  150. // Mac OS X does not have the MSG_NOSIGNAL flag. It does have this
  151. // connections based version, however.
  152. if (emitter.socketFileDescriptorEmitter > 0) {
  153. int set_option = 1;
  154. if (0 == setsockopt(emitter.socketFileDescriptorEmitter, SOL_SOCKET, SO_NOSIGPIPE, &set_option, sizeof(set_option))) {
  155. } else {
  156. std::cout << "Failed to set socket signal option" << std::endl;
  157. }
  158. }
  159. #endif // SO_NOSIGPIPE
  160. #ifdef UNIX
  161. listen( emitter.socketFileDescriptorEmitter, (int)max_clients );
  162. #else //Win32
  163. listen( (unsigned)emitter.socketFileDescriptorEmitter, (int)max_clients );
  164. #endif
  165. std::cout << "Server ready" << std::endl;
  166. started = true;
  167. return true;
  168. }
  169. /*!
  170. Check if a client has connected or deconnected the server
  171. \return True if a client connected or deconnected, false otherwise OR server not started yet.
  172. */
  173. bool vpServer::checkForConnections()
  174. {
  175. if(!started)
  176. if(!start()){
  177. return false;
  178. }
  179. tv.tv_sec = tv_sec;
  180. tv.tv_usec = tv_usec;
  181. FD_ZERO(&readFileDescriptor);
  182. socketMax = emitter.socketFileDescriptorEmitter;
  183. FD_SET((unsigned)emitter.socketFileDescriptorEmitter,&readFileDescriptor);
  184. for(unsigned int i=0; i<receptor_list.size(); i++){
  185. FD_SET((unsigned)receptor_list[i].socketFileDescriptorReceptor,&readFileDescriptor);
  186. if(i == 0)
  187. socketMax = receptor_list[i].socketFileDescriptorReceptor;
  188. if(socketMax < receptor_list[i].socketFileDescriptorReceptor) socketMax = receptor_list[i].socketFileDescriptorReceptor;
  189. }
  190. int value = select((int)socketMax+1,&readFileDescriptor,NULL,NULL,&tv);
  191. if(value == -1){
  192. //vpERROR_TRACE( "vpServer::run(), select()" );
  193. return false;
  194. }
  195. else if(value == 0){
  196. return false;
  197. }
  198. else{
  199. if(FD_ISSET((unsigned int)emitter.socketFileDescriptorEmitter,&readFileDescriptor)){
  200. vpNetwork::vpReceptor client;
  201. client.receptorAddressSize = sizeof(client.receptorAddress);
  202. #ifdef UNIX
  203. client.socketFileDescriptorReceptor = accept(emitter.socketFileDescriptorEmitter,(struct sockaddr*) &client.receptorAddress, &client.receptorAddressSize);
  204. #else //Win32
  205. client.socketFileDescriptorReceptor = accept((unsigned int)emitter.socketFileDescriptorEmitter,(struct sockaddr*) &client.receptorAddress, &client.receptorAddressSize);
  206. #endif
  207. #ifdef UNIX
  208. if((client.socketFileDescriptorReceptor) == -1)
  209. #else
  210. if((client.socketFileDescriptorReceptor) == INVALID_SOCKET)
  211. #endif
  212. vpERROR_TRACE( "vpServer::run(), accept()" );
  213. client.receptorIP = inet_ntoa(client.receptorAddress.sin_addr);
  214. printf("New client connected : %s\n", inet_ntoa(client.receptorAddress.sin_addr));
  215. receptor_list.push_back(client);
  216. return true;
  217. }
  218. else{
  219. for(unsigned int i=0; i<receptor_list.size(); i++){
  220. if(FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor,&readFileDescriptor)){
  221. char deco;
  222. #ifdef UNIX
  223. int numbytes = recv(receptor_list[i].socketFileDescriptorReceptor, &deco, 1, MSG_PEEK);
  224. #else //Win32
  225. int numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &deco, 1, MSG_PEEK);
  226. #endif
  227. if(numbytes == 0)
  228. {
  229. std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
  230. receptor_list.erase(receptor_list.begin()+(int)i);
  231. return 0;
  232. }
  233. }
  234. }
  235. }
  236. }
  237. return false;
  238. }
  239. /*!
  240. Print the connected clients.
  241. */
  242. void vpServer::print()
  243. {
  244. vpNetwork::print("Client");
  245. }