TNI Next steps -- TCP/IP

granthes

New member
For the project I wish to complete, TCP/IP connectivity is really the only missing feature.

I can pass data both directions from the TNI DLL (not tested, but I did see both a library call and a message posting operation).

To make the next part work, I need to be able to open a TCP/IP socket connection (two actually) to JMRI and pass messages back and forth between Trainz and JMRI.

The protocol I need to implement is a line by line text protocol, so the ultimate would be for me to be able to write a string to a socket whenever I need to pass data to JMRI and to get some kind of a notification or event every time a line is received from JMRI.

On the other hand, a less "automatic" functionality is fine assuming that there is a polling functionality. I can write the code to send strings out and parse inbound strings for newlines. In this case, I might either try to implement the receiving functionality as a thread or use a post message with delay loop to check for new messages depending on what features are implemented.

--Grant
 
(Just to be clear; I haven't replied here because the requirements seem obvious and don't appear to need discussion at the current time.)

chris
 
(Just to be clear; I haven't replied here because the requirements seem obvious and don't appear to need discussion at the current time.)

Perfectly understandable. I've been working on making sure the basics are there and then I figure I'd use the BOOST async library to prototype out the network stuff just to get things working.

Once a suitable network API becomes available via TNI, I should be able to get that swapped in fairly easily.

--Grant
 
I will also need a network API. The goal will be to send and receive some data to and from a Raspberry Pi. Like Grant, I think I'll just need to write strings.
 
Last edited:
Which brings us to the question how we would do IPC anyway. The standard C and C++ libraries are rather basic, from an application level point of view and cannot be compared to the feature-rich .Net or Java frameworks, but we certainly do not want to reinvent the wheel here. (Well, the C++ standard library has improved significantly in C++11 with platform independent concurrency, but still...)

TNI plugins should be kept lean and clean as far as I understand the concept (all source files in one folder), which suggests that they probably act in a client role to some external service.
 
Which brings us to the question how we would do IPC anyway. The standard C and C++ libraries are rather basic, from an application level point of view and cannot be compared to the feature-rich .Net or Java frameworks, but we certainly do not want to reinvent the wheel here. (Well, the C++ standard library has improved significantly in C++11 with platform independent concurrency, but still...)

TNI plugins should be kept lean and clean as far as I understand the concept (all source files in one folder), which suggests that they probably act in a client role to some external service.


Yeah, C++ is a mixed bag. It's exceedingly powerful as a language, but the standard library is somewhat incomplete, and even where it does now offer the goods, many shops have long since internally standardised on something else due to the historical lack of features.

What does that mean for us?

As you say, reinventing the wheel is not a great idea. At the same time, N3V can't afford to maintain and vet copies of every library that external users might want to take advantage of, hence the restriction on library inclusions. This doesn't matter at all for raw programming, but as soon as you want to interface with the outside world in any fashion it can become more problematic.

For now, we'll have to handle it on a case-by-case basis depending on what people are trying to do. Certain things are best supported through Trainz anyway, so there would be no point in using an external library. There are cases where no external interfaces are required. Physics, Rendering or Sound playback might be examples of this. In these cases, you just program against the Trainz APIs and use STL for containers etc. and you're basically done.

Other things, as you say, are probably best pushed out to an external process. There are limitations with that approach as well- obviously there are major security questions for end users regarding running random executables on their machines, and I think in the majority of cases the kind of developers TNI is likely to attract won't have the time and/or experience to provide a clean multi-platform solution, meaning that some significant portion of our customers would be left out. I think this is a suitable approach where there is an existing technology that is independent of Trainz (such as your own tool) and which doesn't have a run-time impact on the Trainz gameplay, but we'd be unlikely to accept such a solution where a straight TNI plugin could do the same job, or where the executable would be strongly required to use the resultant route/session. It's fair to say that TNI should be about extending the gameplay, not replacing it.


Back to IPC: loopback TCP sockets are definitely the way to go there. They're flexible and portable and have no serious downsides. Plus they get you automatic network transparency, which can be a good thing in a number of cases even if it's not your original use-case.

chris
 
Back
Top