20sec before connection and freezing interface when using asynchr. connection method

mmy

Member
Joined
Oct 5, 2007
Messages
24
Programming Experience
1-3
A server sends data on a particular port. I want to connect to this server and listen for every data on that port. For now, I don't need to send data, just receive.

In the past I worked with VB6 and the winsock control. Now I want to use vb.net and the new method, sockets.

I'v learned that there are 2 methods, synchrone and asynchrone. The synchrone methode (with the connect, read, ... method) blocks everything until the connection is established. Then it blocks again till the data is received, ... So, I prefer to work with the asynchrone method.

With some examples, I'm starting to find my way and I'v wrote this code as a sample.

VB.NET:
Imports System.Net.Sockets
Imports System.Net
Imports System.Text

Public Class Form1

   Private ClientSocket As Socket
   Private ASCII As New System.Text.ASCIIEncoding()

   Private Sub btnConnect(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

   'copy the IP into a variable
   Dim IP As IPAddress
   IP = Dns.GetHostEntry(txtIP.Text).AddressList(0)

   'make an IP endpoint maken (= the server to connect to (IP and port))
   Dim EP As New IPEndPoint(IP, txtPort.Text)

   ClientSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

   'make a connection (asyncrhone)
   'ConnectCallback will be executed when to connection is established
   ClientSocket.BeginConnect(EP, AddressOf ConnectCallback, Nothing)

End Sub

Private Sub ConnectCallback(ByVal ar As IAsyncResult)

   'stop making the connection
   ClientSocket.EndConnect(ar)

   'start receiving data (asynchrone)
   'ReceiveCallback will be executed when data is received
   Dim bytes(4095) As Byte
   ClientSocket.BeginReceive(bytes, 0, bytes.Length, SocketFlags.None, AddressOf ReceiveCallback, bytes)

End Sub

Private Sub ReceiveCallback(ByVal ar As IAsyncResult)

   Dim received() As Byte
   received = CType(ar.AsyncState, Byte())

   'convert the received bytes into a string
   Dim info As String
   info = ASCII.GetString(received, 0, received.Length)

   'show the received string in a textbox
   Dim dlg As New OneStringDelegate(AddressOf ShowReceivedData)
   Dim args() As Object = {info}
   Me.Invoke(dlg, args)

   'I have to write the following line to keep receiving data.
   'if I don't write this line, I only receive data 1 time
   ClientSocket.BeginReceive(received, 0, received.Length, SocketFlags.None, AddressOf ReceiveCallback, received)
End Sub

Private Delegate Sub OneStringDelegate(ByVal data As String)

Private Sub ShowReceivedData(ByVal data As String)
   'show the received data in a text box
   txtTicket.Text = data
End Sub
End Class

But now I have some problems...
1- If I try to connect to the mail server, I receive a response immediately. But when I try to connect to another IP device (a PBX), I have to wait for 20 sec before I receive an answer. Until then, the user interface freezes.

For testing purpose, I wrote a messagebox.show... after ClientSocket.BeginConnect and one as the first line in the sub ReceiveCallback. These lines were executed only after the connection was made.

I have no idea why the PBX takes up to 20seconds to respond, but that's no disaster if the interface doesn't freeze.

2- is it possible to have some error detection? Like when the server is unavailable, the networkconnection was lost, the server is available but the port isn't, ... Or do you have to use try - catch?
 
update...

I have tested a 2nd method and this one connects immediately to a PBX. In this case, a TCPClient is used.

VB.NET:
Imports System.Net.Sockets
Imports System.Text

Public Class Form1

Private ASCII As New System.Text.ASCIIEncoding
Private MyClient As TcpClient
Private mydata(4095) As Byte

Private Sub btnMakeConnection_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMaakConnectie.Click
    Try
       'connect if the IP and port are available
       MyClient = New TcpClient(txtIP.Text, txtPort.Text)
       'read data (asynchr.)
       MyClient.GetStream.BeginRead(mydata, 0, 4095, AddressOf ReadData, Nothing)
    Catch ex As Exception
        ....    
    End Try
End Sub

Private Sub ReadData(ByVal ar As IAsyncResult)
    'asynchr. callback function to read data
    Dim data_length As Integer                        
    Try
       data_lenght = MyClient.GetStream.EndRead(ar)  
       If data_length < 1 Then                       
           txtInfo.AppendText("Disconnected" & vbCrLf)
           Exit Sub
       End If

       'convert data in bytes to a string
       Dim info As String
       info = ASCII.GetString(mydata, 0, data_length)
       '....
       'read data again...
       MyClient.GetStream.BeginRead(mydata, 0, 4095, AddressOf ReadData, Nothing)

    Catch ex As Exception                                    
       MessageBox.Show("Data can't be read / error = " & vbCrLf & ex.Message)
    End Try
End Sub

Private Sub btnDisconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnectieVerbreken.Click
    Try
      MyClient.Close()
      MyClient = Nothing
    Catch ex As Exception
      Exit Sub
    End Try
End Sub
End Class

1) with the try - catch block I check if the connection can be made, if the connection is broken, ...
Are there better ways to do this?
2) If I press btnDisconnect, I won't receive any data anymore (ok), but everytime I get a warning: "A first chance exception of type 'System.NullReferenceException' occurred in...'. Immediately after that, I receive the error from the catch-part from the sub ReadData

Other then that, this code seems te work better. Only, if there is no network connection available, or when the host / IP is unknown the user interface freezes. Even when the connection should be asynchronous. I think this should be some sort of separate thread which leaves enough system resources free for the rest of the application?
 
Last edited:
Back
Top