socketOutConnection.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 "socketOutConnection.h"
18 
19 #define HEADER_LENGTH 6 // byte1=id1, byte2=id2, byte3+byte4=packetSize, byte5+byte6=packetsLeftToRead
20 
21 CSocketOutConnection::CSocketOutConnection(const char* theConnectionAddress,int theConnectionPort,unsigned short maxPacketSize/*=250*/,char headerID1/*=59*/,char headerID2/*=57*/)
22 {
23  _socketConnectionAddress=theConnectionAddress;
24  _socketConnectionPort=theConnectionPort;
25  _socketConn=-1;
26  _headerByte1=headerID1;
27  _headerByte2=headerID2;
28  _maxPacketSize=maxPacketSize;
29 }
30 
32 {
33  if (_socketConn!=(SOCKET)-1)
34  {
35  #ifdef _WIN32
36  closesocket(_socketConn);
37  WSACleanup();
38  #elif defined (__linux) || defined (__APPLE__)
39  close(_socketConn);
40  #endif
41  }
42 }
43 
45 { // return 1: success
46 #ifdef _WIN32
47  if (WSAStartup(0x101,&_socketWsaData)!=0)
48  return(0);
49 #endif
50  _socketConn=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
51  if(_socketConn==INVALID_SOCKET)
52  {
53 #ifdef _WIN32
54  WSACleanup();
55 #endif
56  return(0);
57  }
58  _socketServer.sin_addr.s_addr=inet_addr(_socketConnectionAddress.c_str());
59 
60  _socketServer.sin_family=AF_INET;
61  _socketServer.sin_port=htons(_socketConnectionPort);
62  if(connect(_socketConn,(struct sockaddr*)&_socketServer,sizeof(_socketServer)))
63  {
64 #ifdef _WIN32
65  closesocket(_socketConn);
66  WSACleanup();
67 #elif defined (__linux) || defined (__APPLE__)
68  close(_socketConn);
69 #endif
70  return(0);
71  }
72  return(1);
73 }
74 
75 bool CSocketOutConnection::sendData(char* data,int dataSize)
76 {
77  if (_socketConn==(SOCKET)-1)
78  return(false);
79 
80  if (dataSize==0)
81  return(false);
82 
83  // In Following we make sure we don't send too big packets (we might send the data in several packets)
84  int packetCount=0;
85  int s=dataSize;
86  while (s!=0)
87  {
88  packetCount++;
91  else
92  s=0;
93  }
94 
95  s=dataSize;
96  int ptr=0;
97  while (s!=0)
98  {
99  packetCount--;
100  int sizeToSend=s;
102  sizeToSend=_maxPacketSize-HEADER_LENGTH;
103  s-=sizeToSend;
104  if (!_sendSimplePacket(data+ptr,sizeToSend,packetCount))
105  return(false);
106  ptr+=sizeToSend;
107  }
108  return(true);
109 }
110 
112 { // Returns the data size if >0, otherwise error
113  if (_socketConn==(SOCKET)-1)
114  {
115  dataSize=-2; // error
116  return(NULL);
117  }
118 
119  std::vector<char> receivedData;
120  while (true)
121  {
122  std::vector<char> inDat;
123  int result=_receiveSimplePacket(inDat);
124  if (result<0)
125  {
126  dataSize=0; // error
127  return(NULL);
128  }
129  receivedData.insert(receivedData.end(),inDat.begin(),inDat.end());
130  if (result==0)
131  { // success
132  dataSize=int(receivedData.size());
133  char* retBuff=new char[dataSize];
134  for (int i=0;i<dataSize;i++)
135  retBuff[i]=receivedData[i];
136  return(retBuff);
137  }
138  }
139 }
140 
141 bool CSocketOutConnection::_sendSimplePacket(char* packet,int packetLength,unsigned short packetsLeft)
142 {
143  if (packetLength==0)
144  return(false);
145  // Insert the header:
146  unsigned short s=(unsigned short)packetLength;
147  char header[HEADER_LENGTH];
148  header[0]=_headerByte1;
149  header[1]=_headerByte2;
150  ((unsigned short*)(header+2))[0]=s;
151  ((unsigned short*)(header+2))[1]=packetsLeft;
152 
153  std::vector<char> toSend;
154  for (int i=0;i<HEADER_LENGTH;i++)
155  toSend.push_back(header[i]);
156  for (int i=0;i<packetLength;i++)
157  toSend.push_back(packet[i]);
158  // Send the packet:
159  int dl=send(_socketConn,&toSend[0],packetLength+HEADER_LENGTH,0);
160  if (dl==packetLength+HEADER_LENGTH)
161  return(true);
162  return(false);
163 }
164 
165 int CSocketOutConnection::_receiveSimplePacket(std::vector<char>& packet)
166 { // Returns the number of packets left to read if >=0, otherwise error
167  //1. Read the header and packet size:
168  char headerAndSize[HEADER_LENGTH];
169  int totalReceived=0;
170  unsigned short startT=_getTimeInMs();
171  while(totalReceived!=HEADER_LENGTH)
172  {
173  int nb=recv(_socketConn,headerAndSize+totalReceived,HEADER_LENGTH-totalReceived,0);
174  if (nb<1)
175  break;
176  totalReceived+=nb;
177  if (_getTimeDiffInMs(startT)>3000)
178  break;
179  }
180  // 2. Check if the header is consistent:
181  if (totalReceived!=HEADER_LENGTH)
182  return(-1); // Error reading
183  if ( (headerAndSize[0]!=_headerByte1)||(headerAndSize[1]!=_headerByte2) )
184  return(-1); // Error, wrong header
185  unsigned short dataLength=((unsigned short*)(headerAndSize+2))[0];
186  // 3. Read the data with correct length:
187  packet.clear();
188  packet.resize(dataLength,0);
189  totalReceived=0;
190  startT=_getTimeInMs();
191  while(totalReceived!=dataLength)
192  {
193  int nb=recv(_socketConn,&packet[0]+totalReceived,dataLength-totalReceived,0);
194  if (nb<1)
195  break;
196  totalReceived+=nb;
197  if (_getTimeDiffInMs(startT)>3000)
198  break;
199  }
200  if (totalReceived!=dataLength)
201  return(-1); // wrong size or nothing received
202  return(int(((unsigned short*)(headerAndSize+2))[1]));
203 }
204 
206 {
207 #ifdef _WIN32
208  return(timeGetTime()&0x03ffffff);
209 #elif defined (__linux) || defined (__APPLE__)
210  struct timeval tv;
211  unsigned int result=0;
212  if (gettimeofday(&tv,NULL)==0)
213  result=(tv.tv_sec*1000+tv.tv_usec/1000)&0x03ffffff;
214  return(result);
215 #endif
216 }
217 
219 {
220  int currentTime=_getTimeInMs();
221  if (currentTime<lastTime)
222  return(currentTime+0x03ffffff-lastTime);
223  return(currentTime-lastTime);
224 }
bool sendData(char *data, int dataSize)
struct sockaddr_in _socketServer
char * receiveReplyData(int &dataSize)
bool _sendSimplePacket(char *packet, int packetLength, unsigned short packetsLeft)
int _getTimeDiffInMs(int lastTime)
unsigned short _maxPacketSize
std::string _socketConnectionAddress
#define HEADER_LENGTH
int _receiveSimplePacket(std::vector< char > &packet)
CSocketOutConnection(const char *theConnectionAddress, int theConnectionPort, unsigned short maxPacketSize=250, char headerID1=59, char headerID2=57)