I am trying to create a simple Game which needs a TcpConnection.
So I created a Server class which wraps the TcpListener, same goes with Client and TcpClient. But when I attach my Listener Sub and send Messages it only gets called on the first one:
Server
Imports System.Net.Sockets
Public Class Server
Inherits ConnectionPartner
Private Server As TcpListener
Private Client As TcpClient
Private Stream As NetworkStream
Private Port As Integer
Public Sub Init(ByVal port As Integer)
Server = New TcpListener(port)
End Sub
Public Sub Open()
Server.Start()
Client = Server.AcceptTcpClient()
Stream = Client.GetStream()
End Sub
Public Overrides Sub Write(ByVal Message As String)
Dim Bytes() As Byte = Encoder.GetBytes(Message)
Me.Write(Bytes)
End Sub
Public Overrides Sub Write(ByVal Message() As Byte)
If Stream Is Nothing Then Return
Stream.Write(Message, 0, Message.Length)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
Listen(Sub(ByVal Message() As Byte)
Handler(Encoder.GetString(Message))
End Sub)
End Sub
Public Overrides Sub Listen(ByRef Handler As Action(Of Byte()))
Dim Buffer(Client.ReceiveBufferSize()) As Byte
While (True)
Utils.Log("Listening")
Client.GetStream().Read(Buffer, 0, Buffer.Length)
Handler(Buffer)
End While
End Sub
Public Sub Close()
Try
Client.Close()
Catch ex As Exception
End Try
Try
Server.Stop()
Catch ex As Exception
End Try
End Sub
End Class
Client
Imports System.Net
Imports System.Net.Sockets
Public Class Client
Inherits ConnectionPartner
Private Socket As TcpClient
Private Stream As NetworkStream
Private Port As Integer
Public Sub Init()
Socket = New TcpClient()
End Sub
Public Sub Open(ByVal Ip As IPAddress, ByVal Port As Integer)
Socket.Connect(Ip, Port)
Stream = Socket.GetStream()
End Sub
Public Overrides Sub Write(ByVal Message As String)
Dim Bytes() As Byte = Encoder.GetBytes(Message)
Me.Write(Bytes)
End Sub
Public Overrides Sub Write(ByVal Message() As Byte)
If Stream Is Nothing Then Return
Stream.Write(Message, 0, Message.Length)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
Listen(Sub(ByVal Message() As Byte)
Handler(Encoder.GetString(Message))
End Sub)
End Sub
Public Overrides Sub Listen(ByRef Handler As Action(Of Byte()))
Dim Buffer(Socket.ReceiveBufferSize()) As Byte
While (True)
Utils.Log("Listening")
Stream.Read(Buffer, 0, Buffer.Length)
Handler(Buffer)
End While
End Sub
Public Sub Close()
Try
Socket.Close()
Catch ex As Exception
End Try
End Sub
End Class
My Test Class
Imports System.Net
Imports System.Threading
Class MainWindow
Private Server As Server = New Server()
Private Client As Client = New Client()
Private C As Connection
Private Port As Integer = My.Resources.Port
Private Sub button_client_init_Click(sender As Object, e As RoutedEventArgs) Handles button_client_init.Click
Client.Init()
End Sub
Private Sub button_client_start_Click(sender As Object, e As RoutedEventArgs) Handles button_client_start.Click
Client.Open(Dns.GetHostEntry("localhost").AddressList(1), Port)
End Sub
Private Sub button_client_write_Click(sender As Object, e As RoutedEventArgs) Handles button_client_write.Click
Client.Write("bar")
End Sub
Private Sub button_client_listen_Click(sender As Object, e As RoutedEventArgs) Handles button_client_listen.Click
Dim T As Thread = New Thread(Sub()
Client.Listen(Sub(ByVal M As String)
Log("Client:" & M)
End Sub)
End Sub)
T.Start()
End Sub
Private Sub button_server_init_Click(sender As Object, e As RoutedEventArgs) Handles button_server_init.Click
Server.Init(Port)
End Sub
Private Sub button_server_start_Click(sender As Object, e As RoutedEventArgs) Handles button_server_start.Click
Dim T As Thread = New Thread(Sub()
Server.Open()
End Sub)
T.Start()
End Sub
Private Sub button_server_write_Click(sender As Object, e As RoutedEventArgs) Handles button_server_write.Click
Server.Write("foo")
End Sub
Private Sub button_server_listen_Click(sender As Object, e As RoutedEventArgs) Handles button_server_listen.Click
Dim T As Thread = New Thread(Sub()
Server.Listen(Sub(ByVal M As String)
Log("Server: " & M)
End Sub)
End Sub)
T.Start()
End Sub
End Class
Edit:
I tried to do the whole thing with StreamReader/Writers. Now I am not even getting a sÃngle Message:
Server
Imports System.IO
Imports System.Net.Sockets
Public Class Server
Inherits ConnectionPartner
Private Server As TcpListener
Private Client As TcpClient
Private Reader As StreamReader
Private Writer As StreamWriter
Private Port As Integer
Public Sub Init(ByVal port As Integer)
Server = New TcpListener(port)
End Sub
Public Sub Open()
Server.Start()
Client = Server.AcceptTcpClient()
Dim Stream As NetworkStream = Client.GetStream()
Reader = New StreamReader(Stream)
Writer = New StreamWriter(Stream)
End Sub
Public Overrides Sub Write(ByVal Message As String)
Writer.WriteLine(Message)
End Sub
Public Overrides Sub Write(ByVal Message() As Byte)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
While True
Dim Message As String = Reader.ReadLine()
Handler(Message)
End While
End Sub
Public Overrides Sub Listen(ByRef Handler As Action(Of Byte()))
End Sub
Public Sub Close()
Try
Client.Close()
Catch ex As Exception
End Try
Try
Server.Stop()
Catch ex As Exception
End Try
End Sub
End Class
Client
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Public Class Client
Inherits ConnectionPartner
Private Socket As TcpClient
Private Reader As StreamReader
Private Writer As StreamWriter
Private Port As Integer
Public Sub Init()
Socket = New TcpClient()
End Sub
Public Sub Open(ByVal Ip As IPAddress, ByVal Port As Integer)
Socket.Connect(Ip, Port)
Dim Stream As NetworkStream = Socket.GetStream()
Reader = New StreamReader(Stream)
Writer = New StreamWriter(Stream)
End Sub
Public Overrides Sub Write(ByVal Message As String)
Writer.WriteLine(Message)
End Sub
Public Overrides Sub Write(ByVal Message() As Byte)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
While True
Dim Message As String = Reader.ReadLine()
Handler(Message)
End While
End Sub
Public Overrides Sub Listen(ByRef Handler As Action(Of Byte()))
End Sub
Public Sub Close()
Try
Socket.Close()
Catch ex As Exception
End Try
End Sub
End Class
Solution:
Forgot to flush the Messages.
Server
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Public Class Server
Inherits ConnectionPartner
Private Server As TcpListener
Private Client As TcpClient
Private Reader As StreamReader
Private Writer As StreamWriter
Private Port As Integer
Public Sub Init(ByVal Ip As IPAddress, ByVal Port As Integer)
Server = New TcpListener(Ip, Port)
End Sub
Public Sub Open()
Server.Start()
Client = Server.AcceptTcpClient()
Dim Stream As NetworkStream = Client.GetStream()
Reader = New StreamReader(Stream)
Writer = New StreamWriter(Stream)
Writer.AutoFlush = True
End Sub
Public Overrides Sub Start(ByVal Ip As IPAddress, ByVal Port As Integer)
Me.Init(Ip, Port)
Me.Open()
End Sub
Public Overrides Sub Write(ByVal Message As String)
Writer.WriteLine(Message)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
While True
Dim Message As String = Reader.ReadLine()
Handler(Message)
End While
End Sub
Public Overrides Sub Close()
Try
Client.Close()
Catch ex As Exception
End Try
Try
Server.Stop()
Catch ex As Exception
End Try
End Sub
End Class
Client
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Public Class Client
Inherits ConnectionPartner
Private Socket As TcpClient
Private Reader As StreamReader
Private Writer As StreamWriter
Private Port As Integer
Public Sub Init()
Socket = New TcpClient()
End Sub
Public Sub Open(ByVal Ip As IPAddress, ByVal Port As Integer)
Socket.Connect(Ip, Port)
Dim Stream As NetworkStream = Socket.GetStream()
Reader = New StreamReader(Stream)
Writer = New StreamWriter(Stream)
Writer.AutoFlush = True
End Sub
Public Overrides Sub Start(ByVal Ip As IPAddress, ByVal Port As Integer)
Me.Init()
Me.Open(Ip, Port)
End Sub
Public Overrides Sub Write(ByVal Message As String)
Writer.WriteLine(Message)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
While True
Dim Message As String = Reader.ReadLine()
Handler(Message)
End While
End Sub
Public Overrides Sub Close()
Try
Socket.Close()
Catch ex As Exception
End Try
End Sub
End Class
TCP does not provide messages at all. It provides a boundaryless stream of bytes. When you Read you can get back any number of bytes as low as one. You code needs to assume arbitrary chunking. Here, you are assuming that you get a full buffer each time.
You can use BinaryReader.ReadBytes to read an exact number of bytes. StreamReader/Writer makes text-based protocols much easier.
ReceiveBufferSize is not the number of bytes incoming. It's value is meaningless, don't look at it.
Related
I try to make a server client application server client separated
and the client code it seems have no error but on the server i get an error but i don t get it work
its come this error
Error 1 Handles clause requires a WithEvents variable defined in the containing type or one of its base types. c:\users\monchique discovery\documents\visual studio 2012\Projects\serverxpto\serverxpto\frmServer.vb 36 120 serverxpto
this is my server code
Imports System.Net, System.Net.Sockets
Public Class frmServer
Dim serverSocket As Socket
Dim clientSocket As Socket
Private Sub frmServer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
serverSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Dim IpEndPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, 8800)
serverSocket.Bind(IpEndPoint)
serverSocket.Listen(5)
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
End Sub
Private Sub OnAccept(ByVal ar As IAsyncResult)
clientSocket = serverSocket.EndAccept(ar)
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
AddClient(clientSocket)
End Sub
Delegate Sub _AddClient(ByVal client As Socket)
Private Sub AddClient(ByVal client As Socket)
If InvokeRequired Then
Invoke(New _AddClient(AddressOf AddClient), client)
Exit Sub
End If
Dim lvi As New ListViewItem(client.LocalEndPoint.ToString)
lvi.Tag = client
lsvClients.Items.Add(lvi)
End Sub
Private Sub Send(ByVal msg As String, ByVal client As Socket)
Dim sendBytes As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(msg)
client.BeginSend(sendBytes, 0, sendBytes.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), client)
End Sub
Private Sub OnSend(ByVal ar As IAsyncResult)
Dim client As Socket = ar.AsyncState
client.EndSend(ar)
End Sub
Private Sub SendMessageToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SendMessageToolStripMenuItem.Click
Send("Message from server", lsvClients.SelectedItems(0).Tag)
End Sub
End Class
Edit: my orginal question was too confusing.
Public Class PrintResults
Public Sub ResultsToPS(ByVal lis As List(Of FileData), ByVal PSPathName As String)
Me.List = lis
'setup report writer
Dim rep As New Helper.Report
'create report to PS
rep.ToPS(PSPathName)
End Sub
Public Class Report
Public Sub New()
PrintDoc = New Printing.PrintDocument
End Sub
Public WithEvents PrintDoc As Printing.PrintDocument
Public PrintDocPrintPage As PrintDoc_PrintPage
Public Delegate Sub PrintDoc_PrintPage(ByVal sender As Object, _
ByVal e As Printing.PrintPageEventArgs) 'Handles PrintDoc.PrintPage
Public Function ToPS(ByVal PSPathName As String) As String
'fails
AddHandler Me.PrintDoc.PrintPage, AddressOf Me.PrintDocPrintPage
Me.PrintDoc.Print()
End Function
AddHandler has compiler error: AddressOf operand must be the name of a method. Is there any way to assign the handler to a delegate sub?
Maybe creating events and attaching a function to it is what you are looking for.
Sub Main()
Dim c As New TestClass
AddHandler c.OnComplete, AddressOf Test
c.Execute() ' Will print Done
Console.ReadLine()
End Sub
Sub Test()
Console.WriteLine("Done")
End Sub
Class TestClass
Public Event OnComplete()
Public Sub Execute()
RaiseEvent OnComplete()
End Sub
End Class
With some research I found it's not possible to use a delegate sub with AddressOf. So we need a different approach. I see it now that all I have to do is instantiate the PrintDoc in the New sub. Now I have a PrintDoc object for the AddHandler to use.
Public Class Report
Public Sub New()
PrintDoc = New Printing.PrintDocument
End Sub
We use the regular AddHandler with no delegates:
Public Class PrintResults
Public Sub ResultsToPS(ByVal lis As List(Of FileData), ByVal PSPathName As String)
Me.List = lis
'setup report writer
Dim rep As New Helper.Report
'PrintDoc is automatically instatiated so no object error
AddHandler rep.PrintDoc.PrintPage, AddressOf Me.PrintDoc_PrintPage
'create report to PS
rep.ToPS(PSPathName)
End Sub
Delegates and the AddressOf Operator
AddHandler Statement
I'm trying to send a picture over lan using UDP. I have to "cut" the picture into small packets and then reassemble it at the other end. So far I've made the server and almost the client (the server sends the picture). I've made some tests with BeginReceive and worked (on other project). Now I get nothing on the client(no error..nothing). Here's the code for the server:
Imports System
Imports System.IO
Imports System.Net
Imports System.Threading
Imports System.Net.Sockets
Imports System.Text.Encoding
Public Class Form1
Dim publisher As New Sockets.UdpClient(0)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim sendbytes() As Byte = ASCII.GetBytes(txt1.Text)
Dim img As Image, img_stream As MemoryStream, buffer As Byte()
Dim packet_size As Integer = 1500, sent_size As Long
Try
publisher.Connect("localhost", 60000)
img_stream = imgToBytes(txt1.Text)
ReDim buffer(packet_size)
While Not img_stream.Position = img_stream.Length
sent_size += img_stream.Read(buffer, 0, packet_size)
publisher.Send(buffer, buffer.Length)
End While
Catch ex As Exception
Debug.Print(ex.Message)
End Try
End Sub
Function imgToBytes(ByVal file_name As String) As MemoryStream
Dim img As Image = Image.FromFile(file_name)
Dim stream As New MemoryStream
img.Save(stream, Drawing.Imaging.ImageFormat.Jpeg)
stream.Position = 0
Return stream
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Form2.Show()
End Sub
End Class
The client is on the second form:
Imports System
Imports System.IO
Imports System.Net
Imports System.Threading
Imports System.Net.Sockets
Imports System.Text.Encoding
Public Class Form2
Dim ep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0)
Dim client As New UdpClient(1000)
Public Event new_msg(ByVal msg As Byte())
Public Sub client_msg(ByVal msg As Byte())
Debug.Print("a")
End Sub
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try ''don't know why I put this here
client.BeginReceive(New AsyncCallback(AddressOf receive), client)
Catch ex As Exception
Debug.Print(ex.Message)
End Try
End Sub
Sub receive(ByVal ar As IAsyncResult)
Dim buffer As Byte()
Debug.Print("b")
Try
buffer = client.EndReceive(ar, ep)
''RaiseEvent new_msg(buffer)
client.BeginReceive(New AsyncCallback(AddressOf receive), client)
Catch ex As Exception
Debug.Print(ex.Message)
End Try
End Sub
End Class
Where is the problem?
Your problem is that your clients are not communicating over the same port.
In Form2 you do:
Dim client As New UdpClient(1000)
Then in Form1 when you connect you do:
publisher.Connect("localhost", 60000)
Change the port to 1000 and it works:
publisher.Connect("localhost", 1000)
I created a one way client server communication so that the client can send messages to the server which just receives them. How can I modify the code so that both the server and the client can send and receive messages.
Client Code:
TCPControl.vb
Imports System.Net
Imports System.Net.Sockets
Imports System.IO
Public Class TCPControl
Public Client As TcpClient
Public DataStream As StreamWriter
Public Sub New(Host As String, Port As Integer)
' CLIENT
Client = New TcpClient(Host, Port)
DataStream = New StreamWriter(Client.GetStream)
End Sub
Public Sub Send(Data As String)
DataStream.Write(Data & vbCrLf)
DataStream.Flush()
End Sub
End Class
Form1.vb
Public Class Form1
Private Client As TCPControl
Private Sub cmdSend_Click(sender As System.Object, e As System.EventArgs) Handles cmdSend.Click
SendMessage()
txtMessage.Clear()
txtMessage.Focus()
End Sub
Private Sub cmdConnect_Click(sender As System.Object, e As System.EventArgs) Handles cmdConnect.Click
Client = New TCPControl("10.0.0.253", 64555)
If Client.Client.Connected Then cmdConnect.Text = "Connected"
End Sub
Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
If Client.Client.Connected = True Then
Client.DataStream.Close()
Client.Client.Close()
End If
End Sub
Private Sub txtMessage_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles txtMessage.KeyDown
If e.KeyCode = Keys.Enter Then SendMessage()
End Sub
Private Sub SendMessage()
If Client.Client.Connected = True Then Client.Send(txtMessage.Text)
End Sub
End Class
Server Code:
TCPControl.vb
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Public Class TCPControl
Public Event MessageReceived(sender As TCPControl, Data As String)
' SERVER CONFIG
Public ServerIP As IPAddress = IPAddress.Parse("10.0.0.253")
Public ServerPort As Integer = 64555
Public Server As TcpListener
Private CommThread As Thread
Public IsListening As Boolean = True
' CLIENTS
Private Client As TcpClient
Private ClientData As StreamReader
Public Sub New()
Server = New TcpListener(ServerIP, ServerPort)
Server.Start()
CommThread = New Thread(New ThreadStart(AddressOf Listening))
CommThread.Start()
End Sub
Private Sub Listening()
' CREATE LISTENER LOOP
Do Until IsListening = False
' ACCEPT INCOMING CONNECTIONS
If Server.Pending = True Then
Client = Server.AcceptTcpClient
ClientData = New StreamReader(Client.GetStream)
End If
' RAISE EVENT FOR INCOMING MESSAGES
Try
RaiseEvent MessageReceived(Me, ClientData.ReadLine)
Catch ex As Exception
End Try
' REDUCE CPU USAGE
'Thread.Sleep(100)
Loop
End Sub
End Class
Public Class Form1
Private Server As TCPControl
Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Server.IsListening = False
End Sub
TCPControl.vb
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Server = New TCPControl
txtChat.Text = ":: SERVER STARTED ::" & vbCrLf
AddHandler Server.MessageReceived, AddressOf OnLineReceived
End Sub
' ALLOW THREAD TO COMMUNICATE WITH FORM CONTROL
Private Delegate Sub UpdateTextDelegate(TB As TextBox, txt As String)
' UPDATE TEXTBOX
Private Sub UpdateText(TB As TextBox, txt As String)
If TB.InvokeRequired Then
TB.Invoke(New UpdateTextDelegate(AddressOf UpdateText), New Object() {TB, txt})
Else
If txt IsNot Nothing Then TB.AppendText(txt & vbCrLf)
End If
End Sub
' UPDATE TEXT WHEN DATA IS RECEIVED
Private Sub OnLineReceived(sender As TCPControl, Data As String)
UpdateText(txtChat, Data)
End Sub
End Class
I have 2 main classes. The first launches the second which implements a FIX dll. I would like to be able to set variables/textbox.text in the first from the second. I am able to do so from te OnCreate method in the second, but for some reason cannot from the OnLogon method. Any ideas ?
Thanks
Imports QuickFix
Public Class GlobalVariable
Inherits MainFIXClass
Public Shared instance As MainFIXClass
End Class
Public Class MainFIXClass
Private Sub CurrencyArb_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GlobalVariable.instance = Me
Connect({"D:\\Config.txt"})
End Sub
Private Sub Connect(args As String())
Dim settings As New QuickFix.SessionSettings(args(0))
Dim myApp As IApplication = New MyQuickFixApp()
Dim storeFactory As QuickFix.IMessageStoreFactory = New FileStoreFactory(settings)
Dim logFactory As QuickFix.ILogFactory = New FileLogFactory(settings)
Dim initiator As New QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory)
Try
initiator.Start()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
Public Class MyQuickFixApp
Inherits MainFIXClass
Implements IApplication
Private _session As Session = Nothing
Private _settings As QuickFix.Session = Nothing
Private _Store As QuickFix.IMessageStore = Nothing
Private _instance As MainFIXClass
Public Sub OnCreate(sessionID As SessionID) Implements IApplication.OnCreate
_instance = GlobalVariable.instance
_session = Session.LookupSession(sessionID)
_instance.OutputTB.Text = "On Create - " & sessionID.ToString & " " & _session.ToString ' **************************** this line works
End Sub
Public Sub OnLogon(sessionID As SessionID) Implements IApplication.OnLogon
_instance.OutputTB.Text = "Logged On" ' **************************** this line does not work ?????
MsgBox("Logged On")
End Sub
End Class
Imports System.ComponentModel
Imports System.Threading
Imports QuickFix
Imports QuickFix.Fields
Imports QuickFix.MessageCracker
Public Class MainFIXClass
Private WithEvents bw As BackgroundWorker
Delegate Sub ShowOutputDelegate(value As String)
Private Sub CurrencyArb_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GlobalVariable.instance = Me
bw = New BackgroundWorker
bw.RunWorkerAsync()
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bw.DoWork
Dim settings As New QuickFix.SessionSettings("D:\\CurrencyArb.txt")
Dim myApp As IApplication = New MyQuickFixApp()
Dim storeFactory As QuickFix.IMessageStoreFactory = New FileStoreFactory(settings)
Dim logFactory As QuickFix.ILogFactory = New FileLogFactory(settings)
Dim initiator As New QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory)
Try
'If Not TypeOf e.Argument Is String() Then 'only take valid input
' Throw New ArgumentException("Invalid argument")
'End If
'Dim args As String() = DirectCast(e.Argument, String()) 'you can pass your arguments here
initiator.Start()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub bw_WorkCompleted(source As Object, e As RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
If e.Error IsNot Nothing Then
'and exception occured
Else
'everything was fine, you can use the result
Dim result As Object = e.Result
End If
End Sub
Public Sub ShowOutput(msg As String)
If InvokeRequired Then
Invoke(New ShowOutputDelegate(AddressOf ShowOutput), msg)
Else
Me.OutputTB.Text = msg
End If
Me.OutputTB.Text = msg
End Sub
End Class
Public Class MyQuickFixApp
Implements IApplication
Private _session As Session = Nothing
Private _settings As QuickFix.Session = Nothing
Private _Store As QuickFix.IMessageStore = Nothing
Private _instance As MainFIXClass
Public Sub OnCreate(sessionID As SessionID) Implements IApplication.OnCreate
_instance = GlobalVariable.instance
_session = Session.LookupSession(sessionID)
_instance.ShowOutput("On Create - " & sessionID.ToString & " " & _session.ToString)
End Sub
Public Sub OnLogon(sessionID As SessionID) Implements IApplication.OnLogon
_instance.ShowOutput("Logged On")
End Sub
End Class
Public Class GlobalVariable
Public Shared instance As MainFIXClass
End Class
To prevent the Window from blocking, you can use Threads or a BackgroundWorker. I prepared a small code snippet that demonstrates how you can use the BackgroundWorker. Please note how the DoWork and WorkCompleted methods are wired to the worker instance by using Handles.
Imports System.ComponentModel
Imports System.Threading
Imports QuickFix
Imports QuickFix.Fields
Imports QuickFix.MessageCracker
Public Class MainFIXClass
Implements IApplication
Private WithEvents bw As BackgroundWorker
Private _session As Session = Nothing
Private _settings As QuickFix.Session = Nothing
Private _Store As QuickFix.IMessageStore = Nothing
#Region "IApplication Methods"
Public Sub OnCreate(sessionID As SessionID) Implements IApplication.OnCreate
_session = Session.LookupSession(sessionID)
Me.ShowOutput("On Create - " & sessionID.ToString & " " & _session.ToString)
End Sub
Public Sub OnLogon(sessionID As SessionID) Implements IApplication.OnLogon
Me.ShowOutput("Logged On")
End Sub
#End Region
Private Sub CurrencyArb_Load(sender As Object, e As EventArgs) Handles MyBase.Load
bw = New BackgroundWorker
bw.WorkerReportsProgress = True
bw.RunWorkerAsync()
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bw.DoWork
Dim settings As New QuickFix.SessionSettings("D:\\CurrencyArb.txt")
Dim myApp As IApplication = New MyQuickFixApp()
Dim storeFactory As QuickFix.IMessageStoreFactory = New FileStoreFactory(settings)
Dim logFactory As QuickFix.ILogFactory = New FileLogFactory(settings)
Dim initiator As New QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory)
bw.ReportProgress(0, "Starting initiator")
initiator.Start()
bw.ReportProgress(0, "Initiator started successfully")
End Sub
Private Sub bw_ReportProgress(source As Object, e As ProgressChangedEventArgs) Handles bw.ProgressChanged
Me.ShowOutput(e.UserState.ToString())
End Sub
Private Sub bw_WorkCompleted(source As Object, e As RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
If e.Error IsNot Nothing Then
'and exception occured
MsgBox(e.Error.Message)
Else
'everything was fine, you can use the result
Dim result As Object = e.Result
End If
Me.ShowOutput("Worker finished")
End Sub
Public Sub ShowOutput(msg As String)
Me.OutputTB.Text = msg
End Sub
End Class
Here is a snippet when merging both classes
Imports System.ComponentModel
Imports System.Threading
Imports QuickFix
Imports QuickFix.Fields
Imports QuickFix.MessageCracker
Public Class MainFIXClass
Implements IApplication
Private WithEvents bw As BackgroundWorker
Private _session As Session = Nothing
Private _settings As QuickFix.Session = Nothing
Private _Store As QuickFix.IMessageStore = Nothing
#Region "IApplication Methods"
Public Sub OnCreate(sessionID As SessionID) Implements IApplication.OnCreate
_session = Session.LookupSession(sessionID)
Me.ShowOutput("On Create - " & sessionID.ToString & " " & _session.ToString)
End Sub
Public Sub OnLogon(sessionID As SessionID) Implements IApplication.OnLogon
Me.ShowOutput("Logged On")
End Sub
#End Region
Private Sub CurrencyArb_Load(sender As Object, e As EventArgs) Handles MyBase.Load
bw = New BackgroundWorker
bw.WorkerReportsProgress = True
bw.RunWorkerAsync()
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bw.DoWork
Dim settings As New QuickFix.SessionSettings("D:\\CurrencyArb.txt")
Dim myApp As IApplication = New MyQuickFixApp()
Dim storeFactory As QuickFix.IMessageStoreFactory = New FileStoreFactory(settings)
Dim logFactory As QuickFix.ILogFactory = New FileLogFactory(settings)
Dim initiator As New QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory)
bw.ReportProgress(0, "Starting initiator")
initiator.Start()
bw.ReportProgress(0, "Initiator started successfully")
End Sub
Private Sub bw_ReportProgress(source As Object, e As ProgressChangedEventArgs) Handles bw.ProgressChanged
Me.ShowOutput(e.UserState.ToString())
End Sub
Private Sub bw_WorkCompleted(source As Object, e As RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
If e.Error IsNot Nothing Then
'and exception occured
MsgBox(e.Error.Message)
Else
'everything was fine, you can use the result
Dim result As Object = e.Result
End If
Me.ShowOutput("Worker finished")
End Sub
Public Sub ShowOutput(msg As String)
Me.OutputTB.Text = msg
End Sub
End Class