A FIX-session (see FIX Sessions) is represented by the com.b2bits.FIXAntennaSession class.
This topic contains the following sections:
- Creating Session
- Releasing Resources
- Establishing Session as Acceptor
- Establishing Session as Acceptor on Demand
- Establishing Session as Initiator
- Custom Logon message
- Closing Session
- Forcedly Setting Sequence Numbers
- Information about Session State
- Sending Messages
- Processing Incoming Messages
- Session Events Monitoring
- See Also
![]() |
---|
To compile the samples below, please declare the usage of com.b2bits.FIXAntenna namespace |
To create a session, call the following method:
See the example below:
Session session = FixEngine.Instance.CreateSession("SenderCompID", "TargetCompID", FixVersion.FIX44);
If your application is going to create several sessions with the same Sender/Target pair, you first need to create com.b2bits.FIXAntennaSessionId object with unique identifier as 3rd argument of constructor and then pass it to FixEngineCreateSession
See the example below:
SessionId sid = new SessionId("SenderCompID", "TargetCompID", "Q1"); Session session = FixEngine.Instance.CreateSession(sid, FixVersion.FIX44);
![]() |
---|
FixEngine should be properly initialized before you will be able to create a session. See FixEngine |
By default resources assigned with all sessions are released after FixEngineStop. To dispose resources of the session implicitly, call the SessionDispose method.
Session session = FixEngine.Instance.CreateSession("SenderCompID", "TargetCompID", FixVersion.FIX44); // ... session.Dispose();
To establish a session as an Acceptor, use the SessionConnectAsAcceptor method.
// FixEngine must be initialized before Session acceptor = FixEngine.Instance.CreateSession("SenderCompID", "TargetCompID", FixVersion.FIX44); acceptor.ConnectAsAcceptor();
![]() |
---|
Sender and Target IDs are strings that will allow to distinguish different senders and targets in your application. You can use any notation you like (for example it can be workstation name or GUID), but you should ensure that if you create more than one session, they should have different Target or Sender IDs |
If the CreateUnregisteredAcceptorSession parameter is switched on and the event listener is registered for the FixEngineUnregisteredAcceptor event, a session-acceptor will be established automatically, when a remote FixEngine is trying to establish a FIX session. If the mode is switched off, the connection with a remote FixEngine will be closed without establishing a session.
See also com.b2bits.FIXAntennaFixEngineUnregisteredAcceptorHandler
// Event Listener class AcceptorsListener { public void OnUnregisteredAcceptor(Object sender, FixEngine.UnregisteredAcceptorArgs e) { Console.WriteLine("\nOnUnregisteredAcceptor: " + e.Session); } } AcceptorsListener listener = new AcceptorsListener(); FixEngine.Instance.UnregisteredAcceptor += new FixEngine.UnregisteredAcceptorHandler(listener.OnUnregisteredAcceptor);
To establish a session as an Initiator, use the SessionConnectAsInitiator method
See the example below:
FixEngine.Create("engine.properties"); // initialization string sender = "Acceptor's CompID"; string target = "Initiator's CompID"; Session acceptor = FixEngine.Instance.CreateSession(sender, target, FixVersion.FIX44); acceptor.ConnectAsAcceptor(); Session initiator = FixEngine.Instance.CreateSession(target, sender, FixVersion.FIX44); string host = "localhost"; // remote FIX engine's host name int port = FixEngine.Instance.ListenPort; // remote FIX engine's port int heartBtInt = 30; // Heartbeat interval (in seconds) initiator. (host, port, heartBtInt); // Establish the session as Initiator Console.WriteLine("Current Role: " + initiator.Role.ToString()); Console.WriteLine(FixEngine.Instance.Statistics); // ... - business logic initiator.Disconnect(); // Close the session
See "Hello, World!" Sample Walkthrough that illustrates the examples of initiator and acceptor sessions connecting to each other.
The method override SessionConnectAsInitiator(String, Int32, Int32, FixMessage) with com.b2bits.FIXAntennaFixMessagecustomLogonMsg parameter allows sending a custom logon message during logon.
See the example below:
string target = "Acceptor's CompID"; string sender = "Initiator's CompID"; Session initiator = FixEngine.Instance.CreateSession(target, sender, FixVersion.FIX44); string host = "localhost"; // remote FIX engine's host name int port = FixEngine.Instance.ListenPort; // remote FIX engine's port int heartBtInt = 30; // Heartbeat interval (in seconds) // create a Logon message framework FixMessage logonMsg = FixMessage.Create(FixVersion.FIX44, "A"); logonMsg.SetField(Tag.MaxMessageSize, 2000); Console.WriteLine("Custom Logon Message: " + logonMsg); // Establish the session as Initiator using Custom Logon Message initiator.ConnectAsInitiator(host, port, heartBtInt, logonMsg);
In Benchmark custom logon messages were used to inform acceptor about the number of messages we are going to send from initiator. This was done by adding a custom field to the logon message and storing the number of messages in this field.
To close the session, use the following methods:
SessionDisconnectNonGracefully
The difference between these methods is the State of the session after disconnect, that will be either CORRECTLY_TERMINATED or NON_GRACEFULLY_TERMINATED, respectively. (see enum com.b2bits.FIXAntennaSessionState).
Disposing resources of a connected session also forces disconnect. If you call FixEngineStop or SessionDispose it will cause the session to disconnect non gracefully.
To forcedly set session's message sequence numbers use the following properties:
To obtain a session current state report, use the SessionState property.
Below you can see the list of most important states (please see com.b2bits.FIXAntennaSessionState for the complete list).
SessionState enum | Description |
---|---|
INITIAL | The session was created, but is not connected yet. |
WAIT_FOR_FIRST_LOGON | The session was connected as an Acceptor and waits for the first Logon message. |
WAIT_FOR_CONFIRM_LOGON | The session was connected as an Initiator, the first Logon message was sent and it waits for the confirming Logon message. |
ESTABLISHED | The session is fully established. |
RECONNECT | The session-initiator detected the telecommunication link error and is trying to re-establish the link. |
CORRECTLY_TERMINATED | The session was correctly terminated. |
NON_GRACEFULLY_TERMINATED | The session was non-gracefully terminated. |
![]() |
---|
When FixAntenna retrieves session state, it locks this property to prevent its changing from another thread. When you develop a multithreaded application, please ensure that you will not put into lock {} sections both code that gets current session state and code that at the same time changes session state in another thread (by calling Connect or Desconnect). This may cause deadlocks in your application and the program will hang up. In case when you want to display actual session state in your application we recommend you to subscribe to SessionNewStateEvent. Session events will also be discussed below, in section. |
To send outgoing application-level messages, use the SessionPut(FixMessage) method.
FixEngine also automatically sends all session-level messages, defined by the FIX Protocol, like Logon, Logout and Heartbeat messages.
FixMessage msg = FixMessage.Create(FixVersion.FIX44, "D"); // New Order - Single (MsgType = D) msg.SetField(Tag.ClOrdID, "90001008"); msg.SetField(Tag.Side, "1"); msg.SetField(Tag.TimeInForce, "0"); msg.SetField(Tag.HandlInst, "1"); msg.SetField(Tag.Symbol, "IBM"); msg.SetField(Tag.OrderQty, 10); msg.SetField(Tag.OrdType, "1"); msg.SetField(Tag.TransactTime, "20060101-10:00:00"); //... Console.WriteLine("Msg: " + msg); initiator.Put(msg); // send the message System.Threading.Thread.Sleep(1000); // wait for message processing
All FIX sessions are bi-directional. So, once 2 applications establish a connection and loggen on, they can send messages and receive messages from each other using the same session.
![]() |
---|
Sending messages is performed by FixAntenna as an asyncroneous operation. That means that when you call the Put method and it returns the control flow to your program, the message is not actually sent at this moment. FixAntenna queues and processes messages in multiple working threads, that allows boosting message sending performance. If you gracefully close the session right after you call Put, the session will not be closed until all messages from buffer are sent. However, if you want to terminate non-gracefully or call FixEngineStop you should wait until all messages are delivered to the acceptor. |
To process incoming messages, subscribe for the SessionIncomingMessageEvent event.
See the example below:
// Event Listener class IncomingMessagesListener { public void OnIncomingMessage(Object sender, Session.IncomingMessageEventArgs e) { Console.WriteLine("\nOnIncomingMessage: " + e.IncomingMessageMsg); } }; IncomingMessagesListener listener = new IncomingMessagesListener(); acceptor.IncomingMessageEvent += new Session.IncomingMessageEventHandler(listener.OnIncomingMessage);
![]() |
---|
IncomingMessageEvent is fired when an application-level event is received (i.e. when a counterpart application sent it using SessionPut(FixMessage) method). Other event handlers are responsible for session-level events, please see section below. |
The Session class has several events that can be subscribed by client applications.
See the complete list of events here: SessionSession
The example below demonstrates how to subscribe for all session events and log their execution to console.
// Session's events listener class SessionEventsListener { public void OnLogon(Object sender, Session.LogonEventArgs e) { Console.WriteLine("OnLogon: " + e.LogonMsg); } public void OnLogout(Object sender, Session.LogoutEventArgs e) { Console.WriteLine("OnLogout: " + e.LogoutMsg); } public void OnSessionLevelReject(Object sender, Session.SessionLevelRejectEventArgs e) { Console.WriteLine("OnSessionLevelReject: " + e.SessionLevelRejectMsg); } public void OnSequenceGap(Object sender, Session.SequenceGapEventArgs e) { Console.WriteLine("OnSequenceGap: " + e.Message + ", expected: " + e.ExpectedSeqNum + ", received: " + e.ReceivedSeqNum); } public void OnHeartbeatWithTestReqID(Object sender, Session.HeartbeatWithTestReqIDEventArgs e) { Console.WriteLine("OnHeartbeatWithTestReqID: " + e.HeartbeatMsg + ", id: " + e.TestReqID); } public void OnResendRequest(Object sender, Session.ResendRequestEventArgs e) { Console.WriteLine("OnResendRequest: " + e.ResendRequestMsg + ", beginSeqNo=" + e.BeginSeqNo + ", endSeqNo=" + e.EndSeqNo); } public void OnNewStateEvent(Object sender, Session.NewStateEventArgs e) { Console.WriteLine("NewStateEvent received." ); } } SessionEventsListener event_listener = new SessionEventsListener(); acceptor.LogonEvent += new Session.LogonEventHandler(event_listener.OnLogon); acceptor.LogoutEvent += new Session.LogoutEventHandler(event_listener.OnLogout); acceptor.SessionLevelRejectEvent += new Session.SessionLevelRejectEventHandler(event_listener.OnSessionLevelReject); acceptor.SequenceGapEvent += new Session.SequenceGapEventHandler(event_listener.OnSequenceGap); acceptor.HeartbeatWithTestReqIDEvent += new Session.HeartbeatWithTestReqIDEventHandler(event_listener.OnHeartbeatWithTestReqID); acceptor.ResendRequestEvent += new Session.ResendRequestEventHandler(event_listener.OnResendRequest); acceptor.NewStateEvent += new Session.NewStateEventHandler(event_listener.OnNewStateEvent);
![]() |
---|
Usually you may wish to subscribe for all session events in order to do logging. However OnLogon, OnLogout or OnNewStateEvent events are also very important to implement any logic in your program that should rely on the fact that session is already in a certain state. For example if you want to send messages directly after logon, you should wait until session signals you that logon is really completed. SessionConnectAsInitiator and SessionConnectAsAcceptor are asynchronous functions, so even when they both return control flow to the application, some time will still be required for both sessions to exchange with Login and Login Confirmation messages through a TCP/IP network. Please see "Hello, World!" Sample Walkthrough for an example of how session events can be used to syncronize main execution thread with the actual session state. |