Board index FlightGear Support Interfacing

failure to connect udp or tcp socket via c client

Connecting two computers, using generic protocol, connecting with Matlab?

failure to connect udp or tcp socket via c client

Postby jambox » Tue Jul 03, 2018 12:34 am

Hi! I have been checking out these very helpful forums over the past week and appreciate the wealth of info here.
What I am attempting to do has been done before, use FG as a scene generator for my own hardware in a cockpit simulator.
The hardware pipes to a 'client' computer that is attempting to create a socket connection the the FG 'server' (just passing data into FG right now)

i execute >fgfs --generic=socket,in,45,localhost,5040,tcp,input_xml as my starting command (i have also played around with a udp socket, however that gives less feedback on whether or not a connection has been established and as that is my problem I was hoping to start by establishing a tcp connection, especially after successfully connecting via telnet interface on my redhat virtual machine)

my client side c code looks like this:
Code: Select all
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#define PORT "3490"


int main(int argc, char* argv[])
{
    int sock_in, sock_out;
    int addr_len, bytes_read;
    char recv_data[1024];
    struct sockaddr_in server_addr_in , client_addr_in;
    struct sockaddr_in server_addr_out;
    struct addrinfo hints, *servinfo, *p;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    int rv, sockfd;

    /*error check argument inputs*/
    if (argc != 2) {
       printf("meant to connect to server IP!\n");
        return 1;
    }

    /*
       error check get addr info, else put into servinfo
       currently: 10.1.12.128 and PORT is 5001
    */
    char msg[10];
    sprintf(msg, "%d", htons(3490));
    if ((rv = getaddrinfo(argv[1], ((char *) msg) , &hints, &servinfo)) != 0) {
          printf("getaddrinfo failed! rv = %d \n",rv);
          printf("error def: %s\n", gai_strerror(rv));
          return -1;
    } else {
        printf("addr info obtained!\n");
    }
   
   /*error check and initialize obtaining sockfd*/
   if ((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, 0)) == -1) {
       printf("socket file descriptor init failed\n");
       printf("error def: %s\n", gai_strerror(sockfd));
        return 1;
    } else {
        printf("socket file descriptor obtained!\n");
    }
   
    /*error check and intialize connection to fg server*/
    if ((rv = connect(sockfd, servinfo->ai_addr, servinfo->ai_addrlen)) < 0) {
       close(sockfd);
        printf("connection failed to open\n");
        printf("error number is: %d def: %s\n", errno, gai_strerror(errno));
        return 1;
    } else {
        printf("socket connect!\n");
    }
   return 0;
}


when I execute the code it just hangs at the call to connect.

my udp implementation attempted to set position/altitude-ft as error check and that looked like this
Code: Select all
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#define PORT "5010"


int main(int argc, char* argv[])
{
    int addr_len, bytes_read;
    char recv_data[1024];
    char send_data[1024];
    struct addrinfo hints, *servinfo, *p;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;
    int rv, sockfd;
    int msg_len = 0;
    float altitude = 10000;

    /*error check argument inputs*/
    if (argc != 2) {
       printf("meant to connect to server IP!\n");
        return 1;
    }

    /*
       error check get addr info, else put into servinfo
       currently: 10.1.12.128 and PORT is 5001
    */
    if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
          printf("getaddrinfo failed! rv = %d \n",rv);
          printf("error def: %s\n", gai_strerror(rv));
          return -1;
    } else {
        printf("addr info obtained!\n");
    }
   
   /*error check and initialize obtaining sockfd*/
   if ((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
       printf("socket file descriptor init failed\n");
       printf("error def: %s\n", gai_strerror(sockfd));
        return 1;
    } else {
        printf("socket file descriptor obtained!\n");
    }
   
    /*error check and intialize connection to fg server*/
    if ((rv = connect(sockfd, servinfo->ai_addr, servinfo->ai_addrlen)) < 0) {
       close(sockfd);
        printf("connection failed to open\n");
        printf("error number is: %d def: %s\n", errno, gai_strerror(errno));
        return 1;
    } else {
        printf("no error in datagram socket connect!\n");
    }

    msg_len = sprintf(send_data, "%.2f\n", altitude);
    // Print Control inputs to stdout
    printf("\nSetting alititude to:\n%s\n", send_data);         
    // Send UDP packet
    printf("attempting to send %d bytes of data \n", msg_len);
    send(sockfd, send_data, msg_len, 0);

   return 0;
}


with an xml struct titled input_protocol of (sorry for comments, trying to keep everything striaght)
Code: Select all
<?xml version="1.0"?>
   <PropertyList>
      <generic>
         <input>
            <!--
               !!!!IMPORTANT!!!!!
               make sure to save edits to this copy into
               C:\Program Files\FlightGear 2018.2.2\data\Protocol
               !!!!IMPORTANT!!!!!
            -->
            <line_separator>newline</line_separator> <!-- used at the end of sprintf statements-->
            <!-- <var_separator>tab</var_separator> only needed for mulitple cars--><!-- used between vars packed within an sprintf -->
            <!-- <binary_mode>true</binary_mode> comment this line back to swith to binary -->
            <chunk>
               <name>/position/altitude-ft</name>
               <type>float</type>
               <node>/position/altitude-ft</node>
               <!-- <format>%f</format> only for outputs i believe-->
            </chunk>

            <!--not using this chunk rn
            <chunk>
               <name>/controls/flight/elevator</name>
               <node>/controls/flight/elevator</node>
               <type>float</type>
               <format>%f</format>
            </chunk>
            -->
         </input>
      </generic>
   </PropertyList>


that i called in command line with >fgfs --generic=socket,in,45,localhost,udp,input_protocol (which was placed in protocol directory)
i received no feedback from this one (expect to see change in height)

I am posting as a continuation of viewtopic.php?f=17&t=33381 where it seemed the poster could only solve his issue via integrating hardware and pushing socket data via serial connection to the computer. @Hooray seemed to suggest that this is a neccesary workaround (unless I misunderstood).

Let me know if you need any more information! This is an awesome platform with a cool community that I would love to develop for.
jambox
 
Posts: 2
Joined: Tue Jul 03, 2018 12:18 am

Re: failure to connect udp or tcp socket via c client

Postby RJ5576 » Tue Jul 03, 2018 5:23 am

I find that it doesn't work unless you omit the host name from the FG command-line option.
RJ5576
 
Posts: 86
Joined: Wed Feb 20, 2013 4:24 am
Location: Between KSEA and KPDX
Callsign: RJ5576
Version: 2018.1.1
OS: Linux Mint Sylvia

Re: failure to connect udp or tcp socket via c client

Postby AndersG » Tue Jul 03, 2018 7:34 am

Yes, the localhost in "--generic=socket,in,45,localhost,5040,tcp,input_xml" specifies the IP-address of the interface FG should receive on.
So with localhost there it should only be possible to connect and send data over the loopback device (and if not that'd be a bug).
Callsign: SE-AG
Aircraft (uhm...): Submarine Scout, Zeppelin NT, ZF Navy free balloon, Nordstern, Hindenburg, Short Empire flying-boat, ZNP-K, North Sea class, MTB T21 class, U.S.S. Monitor, MFI-9B, Type UB I submarine, Gokstad ship, Renault FT.
AndersG
 
Posts: 2524
Joined: Wed Nov 29, 2006 10:20 am
Location: Göteborg, Sweden
Callsign: SE-AG
OS: Debian GNU Linux

Re: failure to connect udp or tcp socket via c client

Postby wkitty42 » Tue Jul 03, 2018 5:16 pm

i'm concerned, too, with the defined "port" in the posted code... it doesn't seem to point to the same port as what is used on the command line but i may not be reading very thoroughly and these ports may be what the code is using to connect from to the FG 5040 port...

the only other thing to point out is that, IMHO, TCP would be the better since it is guaranteed that a transmitted packet will make it to the other end... UDP has no such guarantee and is more like a "Hail Mary" American football play where you just throw the ball (packet) into the air (ether) and hope someone catches it...
"You get more air close to the ground," said Angalo. "I read that in a book. You get lots of air low down, and not much when you go up."
"Why not?" said Gurder.
"Dunno. It's frightened of heights, I guess."
User avatar
wkitty42
 
Posts: 9148
Joined: Fri Feb 20, 2015 4:46 pm
Location: central NC, USA
Callsign: wk42
Version: git next
OS: Kubuntu 20.04

Re: failure to connect udp or tcp socket via c client

Postby jambox » Tue Jul 03, 2018 6:16 pm

it works!!!! (over udp and setting altitude to 10000ft). I really really appreaciate the speedy response.
the only thing i changed was ommiting localhost for ,, instead

ill post a version of the code with all the port nonsense cleaned up.

the fgfs command i ran was:
Code: Select all
fgfs --generic=socket,in,45,,1917,udp,input_protocol


my c client side code
Code: Select all
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#define PORT "1917"


int main(int argc, char* argv[])
{
    int addr_len, bytes_read;
    char recv_data[1024];
    char send_data[1024];
    struct addrinfo hints, *servinfo, *p;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;
    int rv, sockfd;
    int msg_len = 0;
    float altitude = 10000;

    /*error check argument inputs*/
    if (argc != 2) {
       printf("meant to connect to server IP!\n");
        return 1;
    }

    /*
       error check get addr info, else put into servinfo
       currently: 10.1.12.128 and PORT is 5001
    */
    if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
          printf("getaddrinfo failed! rv = %d \n",rv);
          printf("error def: %s\n", gai_strerror(rv));
          return -1;
    } else {
        printf("addr info obtained!\n");
    }
   
   /*error check and initialize obtaining sockfd*/
   if ((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
       printf("socket file descriptor init failed\n");
       printf("error def: %s\n", gai_strerror(sockfd));
        return 1;
    } else {
        printf("socket file descriptor obtained!\n");
    }
   
    /*error check and intialize connection to fg server*/
    if ((rv = connect(sockfd, servinfo->ai_addr, servinfo->ai_addrlen)) < 0) {
       close(sockfd);
        printf("connection failed to open\n");
        printf("error number is: %d def: %s\n", errno, gai_strerror(errno));
        return 1;
    } else {
        printf("no error in datagram socket connect!\n");
    }

    msg_len = sprintf(send_data, "%.2f\n", altitude);
    // Print Control inputs to stdout
    printf("\nSetting alititude to:\n%s\n", send_data);         
    // Send UDP packet
    printf("attempting to send %d bytes of data \n", msg_len);
    send(sockfd, send_data, msg_len, 0);

   return 0;
}


my xml input protocol
Code: Select all
<?xml version="1.0"?>
   <PropertyList>
      <generic>
         <input>
            <!--
               !!!!IMPORTANT!!!!!
               make sure to save edits to this copy into
               C:\Program Files\FlightGear 2018.2.2\data\Protocol
               !!!!IMPORTANT!!!!!
            -->
            <line_separator>newline</line_separator> <!-- used at the end of sprintf statements-->
            <!-- <var_separator>tab</var_separator> only needed for mulitple cars--><!-- used between vars packed within an sprintf -->
            <!-- <binary_mode>true</binary_mode> comment this line back to swith to binary -->
            <chunk>
               <name>/position/altitude-ft</name>
               <type>float</type>
               <node>/position/altitude-ft</node>
               <!-- <format>%f</format> only for outputs i believe-->
            </chunk>

            <!--not using this chunk rn
            <chunk>
               <name>/controls/flight/elevator</name>
               <node>/controls/flight/elevator</node>
               <type>float</type>
               <format>%f</format>
            </chunk>
            -->
         </input>
      </generic>
   </PropertyList>
jambox
 
Posts: 2
Joined: Tue Jul 03, 2018 12:18 am

Re: failure to connect udp or tcp socket via c client

Postby Richard » Wed Jul 04, 2018 9:18 am

wkitty42 wrote in Tue Jul 03, 2018 5:16 pm:the only other thing to point out is that, IMHO, TCP would be the better since it is guaranteed that a transmitted packet will make it to the other end... UDP has no such guarantee


Not necessarily the right advice; it can seem at a first glance as though TCP is what you want; however this is probably not the case; and importantly one needs to understand exactly what the differences are before choosing a protocol.

Generally UDP is better suited for frequently sent packets, and designing in the ability to handle occasional packet loss is a better solution than relying on packet delivery. TCP works great for low frequency data, my rule of thumb is tens of seconds rather than milliseconds.

I just googled "udp or tcp in multiplayer games"; and found some good background readings; the one that seems most relevant to us is https://gafferongames.com/post/udp_vs_tcp/
Richard
 
Posts: 810
Joined: Sun Nov 02, 2014 11:17 pm
Version: Git
OS: Win10

Re: failure to connect udp or tcp socket via c client

Postby wkitty42 » Wed Jul 04, 2018 5:34 pm

excellent addition to the discussion, Richard... i was hoping that someone would come in with a counter to my "use TCP" statement :mrgreen:
"You get more air close to the ground," said Angalo. "I read that in a book. You get lots of air low down, and not much when you go up."
"Why not?" said Gurder.
"Dunno. It's frightened of heights, I guess."
User avatar
wkitty42
 
Posts: 9148
Joined: Fri Feb 20, 2015 4:46 pm
Location: central NC, USA
Callsign: wk42
Version: git next
OS: Kubuntu 20.04


Return to Interfacing

Who is online

Users browsing this forum: No registered users and 2 guests