socketInConnection.cpp
Go to the documentation of this file.
1 // Copyright 2006-2016 Coppelia Robotics GmbH. All rights reserved.
2 // marc@coppeliarobotics.com
3 // www.coppeliarobotics.com
4 //
5 // -------------------------------------------------------------------
6 // THIS FILE IS DISTRIBUTED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
7 // WARRANTY. THE USER WILL USE IT AT HIS/HER OWN RISK. THE ORIGINAL
8 // AUTHORS AND COPPELIA ROBOTICS GMBH WILL NOT BE LIABLE FOR DATA LOSS,
9 // DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING OR
10 // MISUSING THIS SOFTWARE.
11 //
12 // You are free to use/modify/distribute this file for whatever purpose!
13 // -------------------------------------------------------------------
14 //
15 // This file was automatically created for V-REP release V3.3.2 on August 29th 2016
16 
17 #include "socketInConnection.h"
18 #define HEADER_LENGTH 6 // byte1=id1, byte2=id2, byte3+byte4=packetSize, byte5+byte6=packetsLeftToRead
19 
20 CSocketInConnection::CSocketInConnection(int theConnectionPort,unsigned short maxPacketSize/*=250*/,char headerID1/*=59*/,char headerID2/*=57*/)
21 {
22  _socketConnectionPort=theConnectionPort;
23  _socketConnectWasOk=false;
24  _headerByte1=headerID1;
25  _headerByte2=headerID2;
26  _maxPacketSize=maxPacketSize;
27 
28  memset(&_socketLocal,0,sizeof(struct sockaddr_in));
29 #if defined (__linux) || defined (__APPLE__)
30  _socketServer=-1;
31  _socketClient=-1;
32 #endif /* __linux || __APPLE__ */
33 }
34 
36 {
38  {
39 #ifdef _WIN32
40  shutdown(_socketClient,SD_BOTH);
41  closesocket(_socketServer);
42  WSACleanup();
43 #elif defined (__linux) || defined (__APPLE__)
44  if (_socketServer!=-1)
45  {
46  close(_socketServer);
47  }
48  if (_socketClient!=-1)
49  {
50  close(_socketClient);
51  }
52 #endif
53  }
54 }
55 
57 {
58 #ifdef _WIN32
59  // 1. connect to port:
60  if (WSAStartup(0x101,&_socketWsaData)!=0)
61  return(false); // WSAStartup failed.
62 #endif /* _WIN32 */
63 
64  _socketLocal.sin_family=AF_INET;
65  _socketLocal.sin_addr.s_addr=INADDR_ANY;
66  _socketLocal.sin_port=htons((u_short)_socketConnectionPort);
67  _socketServer=socket(AF_INET,SOCK_STREAM,0);
68  if (_socketServer==INVALID_SOCKET)
69  return(false); // socket failed.
70 
71  if (bind(_socketServer,(struct sockaddr*)&_socketLocal,sizeof(_socketLocal))!=0)
72  return(false); // bind failed.
73 
74  if (listen(_socketServer,10)!=0)
75  return(false); // listen failed.
76 
77  // 2. accept client:
78  struct sockaddr_in from;
79  int fromlen=sizeof(from);
80 
81  _socketClient=accept(_socketServer,(struct sockaddr*) &from, (_socklen *) &fromlen);
82  _socketConnectedMachineIP=inet_ntoa(from.sin_addr);
83  FD_ZERO(&_socketTheSet);
86  return(true);
87 }
88 
90 { // Returns the data size if >0, 0=we had a read time out, -1=we have an error
92  {
93  dataSize=-1; // error
94  return(NULL);
95  }
96  std::vector<char> receivedData;
97  while (true)
98  {
99  std::vector<char> inDat;
100  int result=_receiveSimplePacket(inDat);
101  if (result<0)
102  {
103  dataSize=result+1; // error or read time-out
104  return(NULL);
105  }
106  receivedData.insert(receivedData.end(),inDat.begin(),inDat.end());
107  if (result==0)
108  { // success
109  dataSize=int(receivedData.size());
110  char* retBuff=new char[dataSize];
111  for (int i=0;i<dataSize;i++)
112  retBuff[i]=receivedData[i];
113  return(retBuff);
114  }
115  }
116 }
117 
118 bool CSocketInConnection::replyToReceivedData(char* data,int dataSize)
119 {
120  if (!_socketConnectWasOk)
121  return(false);
122  if (dataSize==0)
123  return(false);
124 
125  // In Following we make sure we don't send too big packets (we might send the data in several packets)
126  int packetCount=0;
127  int s=dataSize;
128  while (s!=0)
129  {
130  packetCount++;
133  else
134  s=0;
135  }
136 
137  s=dataSize;
138  int ptr=0;
139  while (s!=0)
140  {
141  packetCount--;
142  int sizeToSend=s;
144  sizeToSend=_maxPacketSize-HEADER_LENGTH;
145  s-=sizeToSend;
146  if (!_sendSimplePacket(data+ptr,sizeToSend,packetCount))
147  return(false);
148  ptr+=sizeToSend;
149  }
150  return(true);
151 }
152 
154 {
155  if (!_socketConnectWasOk)
156  return("NONE (reception line is not open)");
158 }
159 
160 bool CSocketInConnection::_sendSimplePacket(char* packet,int packetLength,unsigned short packetsLeft)
161 {
162  if (packetLength==0)
163  return(false);
164 
165  // Insert the header:
166  unsigned short s=(unsigned short)packetLength;
167  char header[HEADER_LENGTH];
168  header[0]=_headerByte1;
169  header[1]=_headerByte2;
170  ((unsigned short*)(header+2))[0]=s;
171  ((unsigned short*)(header+2))[1]=packetsLeft;
172 
173  std::vector<char> toSend;
174  for (int i=0;i<HEADER_LENGTH;i++)
175  toSend.push_back(header[i]);
176  for (int i=0;i<packetLength;i++)
177  toSend.push_back(packet[i]);
178  // Send the packet:
179  return(send(_socketClient,&toSend[0],packetLength+HEADER_LENGTH,0)==packetLength+HEADER_LENGTH);
180 }
181 
182 int CSocketInConnection::_receiveSimplePacket(std::vector<char>& packet)
183 {
184  // Returns the number of packets left to read if >=0, -2=error, -1=select time out
185  FD_ZERO(&_socketTheSet);
186  FD_SET(_socketClient,&_socketTheSet);
187 #ifdef _WIN32
188  int selectResult=select(0,&_socketTheSet,NULL,NULL,NULL); // No timeout!
189 #endif /* _WIN32 */
190 #if defined (__linux) || defined (__APPLE__)
191  int selectResult=select(_socketClient+1, &_socketTheSet,NULL,NULL,NULL); // No timeout!
192 #endif /* __linux || __APPLE__ */
193  if (selectResult==1)
194  {
195  //1. Read the header and packet size:
196  char headerAndSize[HEADER_LENGTH];
197  int totalReceived=0;
198  unsigned int startT=_getTimeInMs();
199  while(totalReceived!=HEADER_LENGTH)
200  {
201  int nb=recv(_socketClient,headerAndSize+totalReceived,HEADER_LENGTH-totalReceived,0);
202  if (nb<1)
203  break;
204  totalReceived+=nb;
205  if (_getTimeDiffInMs(startT)>3000)
206  break;
207  }
208  // 2. Check if the header is consistent:
209  if (totalReceived!=HEADER_LENGTH)
210  return(-2); // Error reading
211  if ( (headerAndSize[0]!=_headerByte1)||(headerAndSize[1]!=_headerByte2) )
212  return(-2); // Error, wrong header
213  unsigned short dataLength=((unsigned short*)(headerAndSize+2))[0];
214  // 3. Read the data with correct length:
215  packet.clear();
216  packet.resize(dataLength,0);
217  totalReceived=0;
218  startT=_getTimeInMs();
219  while(totalReceived!=dataLength)
220  {
221  int nb=recv(_socketClient,&packet[0]+totalReceived,dataLength-totalReceived,0);
222  if (nb<1)
223  break;
224  totalReceived+=nb;
225  if (_getTimeDiffInMs(startT)>3000)
226  break;
227  }
228  if (totalReceived!=dataLength)
229  return(-2); // wrong size or nothing received
230  return(int(((unsigned short*)(headerAndSize+2))[1]));
231  }
232  if (selectResult==0)
233  return(-1);
234  return(-2);
235 }
236 
237 #ifdef _WIN32
238 unsigned int CSocketInConnection::_getTimeInMs(void)
239 {
240  return(timeGetTime()&0x03ffffff);
241 }
242 #endif /* _WIN32 */
243 
244 #if defined (__linux) || defined (__APPLE__)
245 unsigned int CSocketInConnection::_getTimeInMs(void)
246 {
247  struct timeval tv;
248  unsigned int result=0;
249  if (gettimeofday(&tv,NULL)==0)
250  result=(tv.tv_sec*1000+tv.tv_usec/1000)&0x03ffffff;
251  return(result);
252 }
253 #endif /* __linux || __APPLE__ */
254 
255 unsigned int CSocketInConnection::_getTimeDiffInMs(unsigned int lastTime)
256 {
257  unsigned int currentTime=_getTimeInMs();
258  if (currentTime<lastTime)
259  return(currentTime+0x03ffffff-lastTime);
260  return(currentTime-lastTime);
261 }
std::string _socketConnectedMachineIP
bool _sendSimplePacket(char *packet, int packetLength, unsigned short packetsLeft)
CSocketInConnection(int theConnectionPort, unsigned short maxPacketSize=250, char headerID1=59, char headerID2=57)
char * receiveData(int &dataSize)
#define HEADER_LENGTH
std::string getConnectedMachineIP()
unsigned int _getTimeInMs()
unsigned short _maxPacketSize
unsigned int _getTimeDiffInMs(unsigned int lastTime)
bool replyToReceivedData(char *data, int dataSize)
int _receiveSimplePacket(std::vector< char > &packet)
struct sockaddr_in _socketLocal