JSBSim Flight Dynamics Model 1.3.0 (09 Apr 2026)
An Open Source Flight Dynamics and Control Software Library in C++
Loading...
Searching...
No Matches
FGfdmSocket Class Reference

Detailed Description

The FGfdmSocket class enables JSBSim to communicate via sockets.

This class provides functionality for sending and receiving data over a socket connection. It can behave as both a client and/or a server, depending on the constructor used. The socket can use either UDP or TCP protocol for communication.

Definition at line 75 of file FGfdmSocket.h.

#include <FGfdmSocket.h>

+ Inheritance diagram for FGfdmSocket:
+ Collaboration diagram for FGfdmSocket:

Public Types

enum  ProtocolType { ptUDP , ptTCP }
 
- Public Types inherited from FGJSBBase
enum  { eL = 1 , eM , eN }
 Moments L, M, N. More...
 
enum  { eP = 1 , eQ , eR }
 Rates P, Q, R. More...
 
enum  { eU = 1 , eV , eW }
 Velocities U, V, W. More...
 
enum  { eX = 1 , eY , eZ }
 Positions X, Y, Z. More...
 
enum  { ePhi = 1 , eTht , ePsi }
 Euler angles Phi, Theta, Psi. More...
 
enum  { eDrag = 1 , eSide , eLift }
 Stability axis forces, Drag, Side force, Lift. More...
 
enum  { eRoll = 1 , ePitch , eYaw }
 Local frame orientation Roll, Pitch, Yaw. More...
 
enum  { eNorth = 1 , eEast , eDown }
 Local frame position North, East, Down. More...
 
enum  { eLat = 1 , eLong , eRad }
 Locations Radius, Latitude, Longitude. More...
 
enum  {
  inNone = 0 , inDegrees , inRadians , inMeters ,
  inFeet
}
 Conversion specifiers. More...
 

Public Member Functions

 FGfdmSocket (const std::string &address, int port, int protocol, int precision=7)
 Construct a client socket.
 
 FGfdmSocket (int port, int protocol, int precision=7)
 Construct a server socket.
 
void Append (const char *)
 Append the specified C-style string to the internal buffer.
 
void Append (const std::string &s)
 Append the specified string to the internal buffer.
 
void Append (double value)
 Append the specified double value to the internal buffer.
 
void Append (long value)
 Append the specified long value to the internal buffer.
 
void Clear (const std::string &s)
 Clear the internal buffer and appends the specified string.
 
void Clear (void)
 Clear the internal buffer.
 
void Close (void)
 Close the socket connection if the protocol is TCP.
 
bool GetConnectStatus (void)
 Return the connection status of the socket.
 
std::string Receive (void)
 Receive data from the socket connection.
 
int Reply (const std::string &text)
 Send a reply to the client ending by a prompt "JSBSim>".
 
void Send (const char *data, int length)
 Send the specified data over the socket connection.
 
void Send (const std::string &data)
 
void Send (void)
 Send the internal buffer over the socket connection.
 
void WaitUntilReadable (void)
 Wait until the TCP socket is readable.
 
- Public Member Functions inherited from FGJSBBase
 FGJSBBase ()
 Constructor for FGJSBBase.
 
virtual ~FGJSBBase ()
 Destructor for FGJSBBase.
 
void disableHighLighting (void)
 Disables highlighting in the console output.
 

Additional Inherited Members

- Static Public Member Functions inherited from FGJSBBase
static const std::string & GetVersion (void)
 Returns the version number of JSBSim.
 
static constexpr double KelvinToFahrenheit (double kelvin)
 Converts from degrees Kelvin to degrees Fahrenheit.
 
static constexpr double CelsiusToRankine (double celsius)
 Converts from degrees Celsius to degrees Rankine.
 
static constexpr double RankineToCelsius (double rankine)
 Converts from degrees Rankine to degrees Celsius.
 
static constexpr double KelvinToRankine (double kelvin)
 Converts from degrees Kelvin to degrees Rankine.
 
static constexpr double RankineToKelvin (double rankine)
 Converts from degrees Rankine to degrees Kelvin.
 
static constexpr double FahrenheitToCelsius (double fahrenheit)
 Converts from degrees Fahrenheit to degrees Celsius.
 
static constexpr double CelsiusToFahrenheit (double celsius)
 Converts from degrees Celsius to degrees Fahrenheit.
 
static constexpr double CelsiusToKelvin (double celsius)
 Converts from degrees Celsius to degrees Kelvin.
 
static constexpr double KelvinToCelsius (double kelvin)
 Converts from degrees Kelvin to degrees Celsius.
 
static constexpr double FeetToMeters (double measure)
 Converts from feet to meters.
 
static bool EqualToRoundoff (double a, double b)
 Finite precision comparison.
 
static bool EqualToRoundoff (float a, float b)
 Finite precision comparison.
 
static bool EqualToRoundoff (float a, double b)
 Finite precision comparison.
 
static bool EqualToRoundoff (double a, float b)
 Finite precision comparison.
 
static constexpr double Constrain (double min, double value, double max)
 Constrain a value between a minimum and a maximum value.
 
static constexpr double sign (double num)
 
- Static Public Attributes inherited from FGJSBBase
static char highint [5] = {27, '[', '1', 'm', '\0' }
 highlights text
 
static char halfint [5] = {27, '[', '2', 'm', '\0' }
 low intensity text
 
static char normint [6] = {27, '[', '2', '2', 'm', '\0' }
 normal intensity text
 
static char reset [5] = {27, '[', '0', 'm', '\0' }
 resets text properties
 
static char underon [5] = {27, '[', '4', 'm', '\0' }
 underlines text
 
static char underoff [6] = {27, '[', '2', '4', 'm', '\0' }
 underline off
 
static char fgblue [6] = {27, '[', '3', '4', 'm', '\0' }
 blue text
 
static char fgcyan [6] = {27, '[', '3', '6', 'm', '\0' }
 cyan text
 
static char fgred [6] = {27, '[', '3', '1', 'm', '\0' }
 red text
 
static char fggreen [6] = {27, '[', '3', '2', 'm', '\0' }
 green text
 
static char fgdef [6] = {27, '[', '3', '9', 'm', '\0' }
 default text
 
static short debug_lvl = 1
 
- Static Protected Member Functions inherited from FGJSBBase
static std::string CreateIndexedPropertyName (const std::string &Property, int index)
 
- Static Protected Attributes inherited from FGJSBBase
static constexpr double radtodeg = 180. / M_PI
 
static constexpr double degtorad = M_PI / 180.
 
static constexpr double hptoftlbssec = 550.0
 
static constexpr double psftoinhg = 0.014138
 
static constexpr double psftopa = 47.88
 
static constexpr double fttom = 0.3048
 
static constexpr double ktstofps = 1852./(3600*fttom)
 
static constexpr double fpstokts = 1.0 / ktstofps
 
static constexpr double inchtoft = 1.0/12.0
 
static constexpr double m3toft3 = 1.0/(fttom*fttom*fttom)
 
static constexpr double in3tom3 = inchtoft*inchtoft*inchtoft/m3toft3
 
static constexpr double inhgtopa = 3386.38
 
static constexpr double slugtolb = 32.174049
 Note that definition of lbtoslug by the inverse of slugtolb and not to a different constant you can also get from some tables will make lbtoslug*slugtolb == 1 up to the magnitude of roundoff.
 
static constexpr double lbtoslug = 1.0/slugtolb
 
static constexpr double kgtolb = 2.20462
 
static constexpr double kgtoslug = 0.06852168
 
static const std::string needed_cfg_version = "2.0"
 
static const std::string JSBSim_version = JSBSIM_VERSION " " __DATE__ " " __TIME__
 

Member Enumeration Documentation

◆ ProtocolType

enum ProtocolType

Definition at line 177 of file FGfdmSocket.h.

177{ptUDP, ptTCP};

Constructor & Destructor Documentation

◆ FGfdmSocket() [1/2]

FGfdmSocket ( const std::string &  address,
int  port,
int  protocol,
int  precision = 7 
)

Construct a client socket.

Parameters
addressThe IP address or hostname of the server to connect to.
portThe port number to connect to.
protocolThe protocol to use for communication (ptUDP or ptTCP).
precisionThe precision to use for floating-point numbers (default is 7).

Definition at line 98 of file FGfdmSocket.cpp.

99{
100 sckt = sckt_in = INVALID_SOCKET;
101 Protocol = (ProtocolType)protocol;
102 connected = false;
103 struct addrinfo *addr = nullptr;
104 this->precision = precision;
105
106#ifdef _WIN32
107 if (!LoadWinSockDLL(debug_lvl)) return;
108#endif
109
110 struct addrinfo hints;
111 memset(&hints, 0, sizeof(struct addrinfo));
112 hints.ai_family = AF_INET;
113 if (protocol == ptUDP)
114 hints.ai_socktype = SOCK_DGRAM;
115 else
116 hints.ai_socktype = SOCK_STREAM;
117 hints.ai_protocol = 0;
118 if (!is_number(address))
119 hints.ai_flags = AI_ADDRCONFIG;
120 else
121 hints.ai_flags = AI_NUMERICHOST;
122
123 int failure = getaddrinfo(address.c_str(), NULL, &hints, &addr);
124 if (failure || !addr) {
125 FGLogging log(LogLevel::ERROR);
126 log << "Could not get host net address " << address;
127
128 if (hints.ai_flags == AI_NUMERICHOST)
129 log << " by number...\n";
130 else
131 log << " by name...\n";
132
133 log << gai_strerror(failure) << "\n";
134
135 freeaddrinfo(addr);
136 return;
137 }
138
139 sckt = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
140
141 if (debug_lvl > 0) {
142 FGLogging log(LogLevel::DEBUG);
143 if (protocol == ptUDP) //use udp protocol
144 log << "Creating UDP socket on port " << port << "\n";
145 else //use tcp protocol
146 log << "Creating TCP socket on port " << port << "\n";
147 }
148
149 if (sckt != INVALID_SOCKET) { // successful
150 int len = sizeof(struct sockaddr_in);
151 memcpy(&scktName, addr->ai_addr, len);
152 scktName.sin_port = htons(port);
153
154 if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful
155 if (debug_lvl > 0) {
156 FGLogging log(LogLevel::DEBUG);
157 log << "Successfully connected to socket for output ...\n";
158 }
159 connected = true;
160 } else { // unsuccessful
161 FGLogging log(LogLevel::ERROR);
162 log << "Could not connect to socket for output ...\n";
163 }
164 } else { // unsuccessful
165 FGLogging log(LogLevel::ERROR);
166 log << "Could not create socket for FDM output, error = " << errno << "\n";
167 }
168
169 freeaddrinfo(addr);
170
171 Debug(0);
172}

◆ FGfdmSocket() [2/2]

FGfdmSocket ( int  port,
int  protocol,
int  precision = 7 
)

Construct a server socket.

Parameters
portThe port number to listen on.
protocolThe protocol to use for communication (ptUDP or ptTCP).
precisionThe precision to use for floating-point numbers (default is 7).

Definition at line 176 of file FGfdmSocket.cpp.

177{
178 sckt = INVALID_SOCKET;
179 connected = false;
180 Protocol = (ProtocolType)protocol;
181 string ProtocolName;
182 this->precision = precision;
183
184#ifdef _WIN32
185 if (!LoadWinSockDLL(debug_lvl)) return;
186#endif
187
188 if (Protocol == ptUDP) { //use udp protocol
189 ProtocolName = "UDP";
190 sckt = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
191#ifdef _WIN32
192 u_long NonBlock = 1; // True
193 ioctlsocket(sckt, FIONBIO, &NonBlock);
194#else
195 int flags = fcntl(sckt, F_GETFL, 0);
196 fcntl(sckt, F_SETFL, flags | O_NONBLOCK);
197#endif
198 }
199 else {
200 ProtocolName = "TCP";
201 sckt = socket(AF_INET, SOCK_STREAM, 0);
202 }
203
204 if (debug_lvl > 0) {
205 FGLogging log(LogLevel::DEBUG);
206 log << "Creating input " << ProtocolName << " socket on port " << port
207 << "\n";
208 }
209
210 if (sckt != INVALID_SOCKET) {
211 memset(&scktName, 0, sizeof(struct sockaddr_in));
212 scktName.sin_family = AF_INET;
213 scktName.sin_port = htons(port);
214
215 if (Protocol == ptUDP)
216 scktName.sin_addr.s_addr = htonl(INADDR_ANY);
217
218 socklen_t len = sizeof(struct sockaddr_in);
219 if (bind(sckt, (struct sockaddr*)&scktName, len) != SOCKET_ERROR) {
220 if (debug_lvl > 0) {
221 FGLogging log(LogLevel::DEBUG);
222 log << "Successfully bound to " << ProtocolName
223 << " input socket on port " << port << "\n\n";
224 }
225
226 if (Protocol == ptTCP) {
227 if (listen(sckt, 5) != SOCKET_ERROR) { // successful listen()
228 connected = true;
229#ifdef _WIN32
230 u_long NoBlock = 1;
231 ioctlsocket(sckt, FIONBIO, &NoBlock);
232#else
233 int flags = fcntl(sckt, F_GETFL, 0);
234 fcntl(sckt, F_SETFL, flags | O_NONBLOCK);
235#endif
236 sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
237 } else {
238 closesocket(sckt);
239 sckt = INVALID_SOCKET;
240 FGLogging log(LogLevel::ERROR);
241 log << "Could not listen ...\n";
242 }
243 } else
244 connected = true;
245 } else { // unsuccessful
246 closesocket(sckt);
247 sckt = INVALID_SOCKET;
248 FGLogging log(LogLevel::ERROR);
249 log << "Could not bind to " << ProtocolName << " input socket, error = "
250 << errno << "\n";
251 }
252 } else { // unsuccessful
253 FGLogging log(LogLevel::ERROR);
254 log << "Could not create " << ProtocolName << " socket for input, error = "
255 << errno << "\n";
256 }
257
258 Debug(0);
259}

◆ ~FGfdmSocket()

Definition at line 263 of file FGfdmSocket.cpp.

264{
265 // Release the file descriptors to the OS.
266 if (sckt_in != INVALID_SOCKET) shutdown(sckt_in, SD_BOTH);
267 if (sckt != INVALID_SOCKET) closesocket(sckt);
268 Debug(1);
269}

Member Function Documentation

◆ Append() [1/4]

void Append ( const char *  item)

Append the specified C-style string to the internal buffer.

Parameters
sThe C-style string to append.

Definition at line 385 of file FGfdmSocket.cpp.

386{
387 if (buffer.tellp() > 0) buffer << ',';
388 buffer << item;
389}

◆ Append() [2/4]

void Append ( const std::string &  s)
inline

Append the specified string to the internal buffer.

Parameters
sThe string to append.

Definition at line 131 of file FGfdmSocket.h.

131{Append(s.c_str());}
void Append(const std::string &s)
Append the specified string to the internal buffer.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Append() [3/4]

void Append ( double  value)

Append the specified double value to the internal buffer.

Parameters
valueThe double value to append.

Definition at line 393 of file FGfdmSocket.cpp.

394{
395 if (buffer.tellp() > 0) buffer << ',';
396 buffer << std::setw(12) << std::setprecision(precision) << item;
397}

◆ Append() [4/4]

void Append ( long  value)

Append the specified long value to the internal buffer.

Parameters
valueThe long value to append.

Definition at line 401 of file FGfdmSocket.cpp.

402{
403 if (buffer.tellp() > 0) buffer << ',';
404 buffer << std::setw(12) << item;
405}

◆ Clear() [1/2]

void Clear ( const std::string &  s)

Clear the internal buffer and appends the specified string.

Parameters
sThe string to append after clearing the buffer.

Definition at line 377 of file FGfdmSocket.cpp.

378{
379 Clear();
380 buffer << s << ' ';
381}
void Clear(void)
Clear the internal buffer.
+ Here is the call graph for this function:

◆ Clear() [2/2]

void Clear ( void  )

Clear the internal buffer.

Definition at line 370 of file FGfdmSocket.cpp.

371{
372 buffer.str("");
373}
+ Here is the caller graph for this function:

◆ Close()

void Close ( void  )

Close the socket connection if the protocol is TCP.

Definition at line 361 of file FGfdmSocket.cpp.

362{
363 assert(Protocol == ptTCP);
364 closesocket(sckt_in);
365 sckt_in = INVALID_SOCKET;
366}
+ Here is the caller graph for this function:

◆ GetConnectStatus()

bool GetConnectStatus ( void  )
inline

Return the connection status of the socket.

Returns
True if the socket is connected, false otherwise.

Definition at line 172 of file FGfdmSocket.h.

172{return connected;}
+ Here is the caller graph for this function:

◆ Receive()

string Receive ( void  )

Receive data from the socket connection.

Returns
The received data as a string.

Definition at line 273 of file FGfdmSocket.cpp.

274{
275 char buf[1024];
276 string data; // TODO should allocate this with a standard size as a
277 // class attribute and pass as a reference?
278
279 if (Protocol == ptTCP){
280 if (sckt_in == INVALID_SOCKET) {
281 socklen_t len = sizeof(struct sockaddr_in);
282 sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
283 if (sckt_in != INVALID_SOCKET) {
284#ifdef _WIN32
285 u_long NoBlock = 1;
286 ioctlsocket(sckt_in, FIONBIO, &NoBlock);
287#else
288 int flags = fcntl(sckt_in, F_GETFL, 0);
289 fcntl(sckt_in, F_SETFL, flags | O_NONBLOCK);
290#endif
291 if (send(sckt_in, "Connected to JSBSim server\r\nJSBSim> ", 36, 0) == SOCKET_ERROR)
292 LogSocketError("Receive - TCP connection acknowledgement");
293 }
294 }
295
296 if (sckt_in != INVALID_SOCKET) {
297 int num_chars;
298
299 while ((num_chars = recv(sckt_in, buf, sizeof buf, 0)) > 0)
300 data.append(buf, num_chars);
301
302 if (num_chars == SOCKET_ERROR || num_chars == 0) {
303#ifdef _WIN32
304 if (WSAGetLastError() != WSAEWOULDBLOCK)
305#else
306 if (errno != EWOULDBLOCK)
307#endif
308 {
309 LogSocketError("Receive - TCP data reception");
310 // when nothing received and the error isn't "would block"
311 // then assume that the client has closed the socket.
312 FGLogging log(LogLevel::INFO);
313 log << "Socket Closed. Back to listening\n";
314 closesocket(sckt_in);
315 sckt_in = INVALID_SOCKET;
316 }
317 }
318 }
319 }
320
321 // this is for FGUDPInputSocket
322 if (sckt != INVALID_SOCKET && Protocol == ptUDP) {
323 struct sockaddr addr;
324 socklen_t fromlen = sizeof addr;
325 int num_chars = recvfrom(sckt, buf, sizeof buf, 0, (struct sockaddr*)&addr, &fromlen);
326 if (num_chars > 0) data.append(buf, num_chars);
327 if (num_chars == SOCKET_ERROR) {
328#ifdef _WIN32
329 if (WSAGetLastError() != WSAEWOULDBLOCK)
330#else
331 if (errno != EWOULDBLOCK)
332#endif
333 LogSocketError("Receive - UDP data reception");
334 }
335 }
336
337 return data;
338}
+ Here is the caller graph for this function:

◆ Reply()

int Reply ( const std::string &  text)

Send a reply to the client ending by a prompt "JSBSim>".

Parameters
textThe reply text to send.
Returns
The number of bytes sent.

Definition at line 342 of file FGfdmSocket.cpp.

343{
344 int num_chars_sent=0;
345 assert(Protocol == ptTCP);
346
347 if (sckt_in != INVALID_SOCKET) {
348 num_chars_sent = send(sckt_in, text.c_str(), text.size(), 0);
349 if (num_chars_sent == SOCKET_ERROR) LogSocketError("Reply - Send data");
350 if (send(sckt_in, "JSBSim> ", 8, 0) == SOCKET_ERROR) LogSocketError("Reply - Prompt");
351 } else {
352 FGLogging log(LogLevel::ERROR);
353 log << "Socket reply must be to a valid socket\n";
354 return -1;
355 }
356 return num_chars_sent;
357}
+ Here is the caller graph for this function:

◆ Send() [1/3]

void Send ( const char *  data,
int  length 
)

Send the specified data over the socket connection.

Parameters
dataThe data to send.
lengthThe length of the data.

Definition at line 418 of file FGfdmSocket.cpp.

419{
420 if (Protocol == ptTCP && sckt_in != INVALID_SOCKET) {
421 if ((send(sckt_in, data, length, 0)) == SOCKET_ERROR) LogSocketError("Send - TCP data sending");
422 return;
423 }
424
425 if (Protocol == ptUDP && sckt != INVALID_SOCKET) {
426 if ((send(sckt, data, length, 0)) == SOCKET_ERROR) LogSocketError("Send - UDP data sending");
427 return;
428 }
429
430 FGLogging log(LogLevel::ERROR);
431 log << "Data sending must be to a valid socket\n";
432}

◆ Send() [2/3]

void Send ( const std::string &  data)
inline

Definition at line 109 of file FGfdmSocket.h.

109{ Send(data.c_str(), data.length()); }
void Send(void)
Send the internal buffer over the socket connection.

◆ Send() [3/3]

void Send ( void  )

Send the internal buffer over the socket connection.

Definition at line 409 of file FGfdmSocket.cpp.

410{
411 buffer << '\n';
412 string str = buffer.str();
413 Send(str.c_str(), str.size());
414}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ WaitUntilReadable()

void WaitUntilReadable ( void  )

Wait until the TCP socket is readable.

Definition at line 436 of file FGfdmSocket.cpp.

437{
438 assert(Protocol == ptTCP);
439 if (sckt_in == INVALID_SOCKET) return;
440
441 fd_set fds;
442 FD_ZERO(&fds);
443 FD_SET(sckt_in, &fds);
444
445 int result = select(FD_SETSIZE, &fds, nullptr, nullptr, nullptr);
446
447 if (result == 0) {
448 FGLogging log(LogLevel::ERROR);
449 log << "Socket timeout.\n";
450 return;
451 } else if (result != SOCKET_ERROR)
452 return;
453
454 LogSocketError("WaitUntilReadable");
455}
+ Here is the caller graph for this function:

The documentation for this class was generated from the following files: