"Hello, World!" Sample WalkthroughFIX Antenna .NET Programmer's Guide

Below you can see the list of step-by-step instructions to create a Hello, World! sample from scratch. Currently, we have only C# version of this walkthrough, but VB.NET version will be available soon too.

Steps Required to Create a HelloWorld.Initiator Sample

  1. Create a new Console application project in Visual Studio, chose the project name and namespace to be HelloWorld.Initiator

  2. Remove all references from the project, except for the reference to System. We don't need System.Data, System.Xml and other references that Visual Studio adds by default

  3. Add a reference to FIXAntenna_net2.0.dll, by default it could be found in SYSTEM_DRIVE:\Program Files\B2BITS\FIX Antenna.NET\[version_number]\lib The reference should contain the Copy Local = true property.

  4. Copy the engine.properties file from any of existing samples (or create it by copying a configuration sample from the page Sample Configuration File) and paste the engine.properties file into the HelloWorld.Acceptor project, set Copy to Output directory = Copy if newer This will ensure that the engine.properties file will be in the working directory and FixEngine.Create("engine.properties") code will work;

  5. Correct the following parameters in the engine.properties file:

    1. ListenPort. It is not important for this sample what port you set, because it will only initiate a session, so the rule is simple - ListenPort should be different from listen ports you set up for other samples. Let's set it ListenPort = 9116
    2. LicenseFile. There should be an absolute or relative path to engine.license. The engine.license is a file with licence information you should get when purchasing FixAntenna.NET library or downloading a trial version.
    3. LogDirectory.. You should create a logs directory manually in the application root directory. You should also create a backup directory inside the logs directory. This can be done by means of the following commands, see SetupLogs.bat included into Hello World sample. mkdir bin\Debug\logs\backupmkdir bin\Release\logs\backup
  6. Write code in Main() function to initialize engine, create a session, connect, wait until connect happens, then send a Hello, World! message and wait for logout event.

    This code can be found below.

    Note Note

    We will pass port = 9115 parameter to ConnectAsInitiator() function in the code, so when we write the HelloWorld.Acceptor sample, we will use port 9115. Note, that we have used different ListenPort parameters in Acceptor and Initiator samples because we want them to start on the same PC (i.e. on localhost). Sure, in our Initiator sample, port 9116 will not be used actually (HelloWorld.Initiator does not listen for incoming UnregisteredAcceptor events and all connunications with HelloWorld.Initiator happen through 9115 port), however FixEngine still requires that ListenPort parameters of each FixEngine instance should be different.

    Note Note

    To establish a FIX session, both parties should agree to communicate with each other (see FIX Sessions). It means that Initiator session should be created and should perform Logon, and Acceptor session should be able to reponse for logon message at the same time. In HelloWorld.Initiator we will use a conditional loop do { ... } while (!loggedIn); to wait for Acceptor to start. Connect in FixAntenna always happens asyncronously, so even when ConnectAsInitiator function exists succesfully, there is no guarantee that connection has already been established. Only when initiator_LogonEvent event is fired (and it will be fired in another thread!), we can be sure that Initiator and Acceptor are now connected and we can start sending messages.

    However, it is not an elegant way in .NET to sync thread execution using loops. Later, in Acceptor sample, we will show a better way of doing this by using synchronization objects from System.Threading namespace, like ManualResetEvent.

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

using com.b2bits.FIXAntenna;

namespace HelloWorld.Initiator
{
    class Program
    {
        static bool loggedIn = false;

        static void Main(string[] args)
        {
            Console.WriteLine("HelloWorld sample, Initiator. (c) B2BITS 2009");
            try
            {
                FixEngine.Create("engine.properties");  // engine initialization

                string sender = "HelloWorldInitiator";  //sender and receiver can be any unique strings that will identify the session
                string target = "HelloWorldAcceptor";
                string host = "localhost";     // remote FIX engine's host name
                int heartBtInt = 30;           // Heartbeat interval (in seconds)
                int port = 9115;   //this should match port defined in ListenPort setting in engine.properties file in the Acceptor application

                //sessions are disposable objects, so we will create one in a using {} block 
                using (Session initiator = FixEngine.Instance.CreateSession(target, sender, FixVersion.FIX44))
                {
                    //subscribe for logon and logout events
                    initiator.LogonEvent += new Session.LogonEventHandler(initiator_LogonEvent);
                    initiator.LogoutEvent += new Session.LogoutEventHandler(initiator_LogoutEvent);

                    Console.WriteLine("Waiting for another side to create an acceptor session.");

                    do
                    {
                        try
                        {
                            initiator.ConnectAsInitiator(host, port, heartBtInt);
                        }
                        catch (ApplicationException)
                        {
                            //In the case when acceptor has not been started yet to the moment, 
                            //when initiator.ConnectAsInitiator executed
                            //FixEngine will raise and exception
                            // 
                            //We will ignore this exception and will try to connect again each second.
                        }
                        Thread.Sleep(1000);
                    }
                    while (!loggedIn);

                    //let's create a new order message
                    FixMessage msg = FixMessage.Create(FixVersion.FIX44, "D");
                    //it will be very simple message with "Hello, World!" string, that we will put in the Text tag
                    msg.SetField(Tag.Text, "Hello, World!");
                    msg.SetField(Tag.TransactTime, DateTime.Now.ToUniversalTime().ToString());

                    Console.WriteLine("Sending the message: {0}", msg.ToString('|'));

                    //Put method works asyncroneously
                    //It means that it will return immediately, when message is put to the queue but not send actually
                    initiator.Put(msg);
                    Console.WriteLine("Message was sent");

                    //Here we should wait while message will be actually sent and received through sockets
                    //and while acceptor will logout
                    //If we logout from initiator immediately after Put(), chances are that acceptor will not get the message

                    Console.WriteLine("Waiting while acceptor will disconnect");

                    do
                    {
                        //We wrote this loop only for a simplicity of the sample
                        //in real projects we do recomment to use synchronization classes from the System.Threading namespace
                        //like WaitHandle and classes inherited from it. Please, see HelloWorld.Acceptor for an example.
                        Thread.Sleep(100);
                    }
                    while (loggedIn);

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                FixEngine.Instance.Stop();
            }
            Console.WriteLine("Press a key to exit");
            Console.ReadKey();
        }

        static void initiator_LogonEvent(object sender, Session.LogonEventArgs args)
        {
            loggedIn = true;
            Console.WriteLine("Logged in.");
        }

        static void  initiator_LogoutEvent(object sender, Session.LogoutEventArgs args)
        {
            loggedIn = false;
            Console.WriteLine("Logged out.");
        }
    }
}

Steps Required to Create a HelloWorld.Acceptor Sample

  1. Create a new Console application project in Visual Studio, chose the project name and namespace to be HelloWorld.Acceptor

  2. Remove all references from the project, except for the reference to System. We don't need System.Data, System.Xml and other references that Visual Studio adds by default

  3. Add a reference to FIXAntenna_net2.0.dll, by default it could be found in SYSTEM_DRIVE:\Program Files\B2BITS\FIX Antenna.NET\[version_number]\lib The reference should contain the Copy Local = true property.

  4. Copy the engine.properties file from any of existing samples (or create it by copying a configuration sample from the page Sample Configuration File) and paste the engine.properties file into the HelloWorld.Acceptor project, set Copy to Output directory = Copy if newer This will ensure that the engine.properties file will be in the working directory, and FixEngine.Create("engine.properties") code will work;

  5. Correct the following parameters in the engine.properties file:

    1. ListenPort. It should match the port defined in the code of Initiator.Program class.
    2. LicenseFile. There should be an absolute or relative path to the engine.license.
    3. LogDirectory.. You should create a logs directory manually in the application root directory. You should also create a backup directory inside the logs directory. This can be done by means of the following commands, see SetupLogs.bat included into the Hello World sample. mkdir bin\Debug\logs\backupmkdir bin\Release\logs\backup
  6. Write code in the Main() function to initialize engine, create a session, connect, wait until connect happens, receive a message and logout.

    See the code below:

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

using com.b2bits.FIXAntenna;

namespace HelloWorld.Acceptor
{
        class Program
    {
        static ManualResetEvent loggedInEvent = new ManualResetEvent(false);
        static ManualResetEvent messageReceivedEvent = new ManualResetEvent(false);

        static void Main(string[] args)
        {
            Console.WriteLine("HelloWorld sample, Acceptor. (c) B2BITS 2009");

            try
            {
                FixEngine.Create("engine.properties");  // engine initialization

                string sender = "HelloWorldAcceptor";  //sender and receiver can be any unique strings that will identify the session
                string target = "HelloWorldInitiator";

                //sessions are disposable objects, so we will create one in a using {} block 
                using (Session acceptor = FixEngine.Instance.CreateSession(target, sender, FixVersion.FIX44))
                {
                    //Subscribe for logon and IncomingMessageEvent events
                    //These events together with ManualResetEvent handlers 
                    //will be used to signal to the main thread that certain event occured
                    acceptor.LogonEvent += new Session.LogonEventHandler(acceptor_LogonEvent);
                    acceptor.IncomingMessageEvent += new Session.IncomingMessageEventHandler(acceptor_IncomingMessageEvent);

                    acceptor.ConnectAsAcceptor();

                    Console.WriteLine("Waiting for another side to create an initiator session.");
                    //stop the main thread and wait for Login event
                    loggedInEvent.WaitOne();

                    Console.WriteLine("Waiting for a message.");
                    //stop the main thread and wait for any message
                    messageReceivedEvent.WaitOne();

                    //When you call Disconnect, FixAntenna doesn't wait until all messages that are still in the queue will be processed 
                    //It will disconnect immediately.
                    //So it is important to Disconnect() only when you are sure that all expected messages have been already received
                    acceptor.Disconnect();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                FixEngine.Instance.Stop();
            }

            Console.WriteLine("Press a key to exit");
            Console.ReadKey();
        }

        static void  acceptor_IncomingMessageEvent(object sender, Session.IncomingMessageEventArgs args)
        {
             Console.WriteLine("Received incoming message: {0}",args.IncomingMessageMsg.ToString('|'));
            Console.WriteLine();

            //let's print the information from the Text tag
            Console.WriteLine(args.IncomingMessageMsg.GetAsString(Tag.Text));
            Console.WriteLine();

            //signal that the main program can proceed
            messageReceivedEvent.Set();
        }

        static void acceptor_LogonEvent(object sender, Session.LogonEventArgs args)
        {
            Console.WriteLine("Logged in.");
            //signal that the main program can proceed
            loggedInEvent.Set();
        }
    }
}