I've finally dipped my toes into .Net and created the following with the assistance of quite a few examples I found lying around the Internet.
It's a simple 'text exchanger' between it and a Server and is designed to run on a Pocket PC using Compact Framework 2 which appears to work. (I have a simple 'echo' server for testing, that just sends back anything it receives). It will also run as a 'standard' windows application.
As a "VB6'er" I've not been used to managing communications between different threads (and have been 'spoilt' by Winsock) so that's the main area where improvements could, perhaps, be made. Also, there may be 'VB6 style code' where .Net would do it 'better'.
I've included comments identifying areas where I'm not too sure. Any advice / comments / criticisms (constructive) for improvement would be gratefully received. This is really meant to be a proof of concept / model for a larger application so I'd like to do it 'properly'.
Code:Imports System.Net.Sockets Imports System.Text Public Class Form1 Dim Client As New TcpClient Dim state As New StateObject Public Delegate Sub DataReceived() Private Sub UpdateText() ' ' (Invoked by the Deligate Sub DataReceived) ' If this was other than a simple text swapping application ' this is where the data would be buffered until a 'record complete' ' character had been received ' txtReceived.Text = txtReceived.Text & result & vbNewLine End Sub Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click Dim Err As Boolean = False state.workClient = Client Dim Error_Message As String = "Error: " ' ' Do some simple validation of the Host and Port ' If txtHost.Text = "" Then Error_Message = Error_Message & "Host not Specified" & vbNewLine Err = True End If ' ' TODO: check that the Port is numeric and in an appropriate range ' If txtPort.Text = "" Then Error_Message = Error_Message & "Port not Specified" & vbNewLine Err = True End If If Not Err Then Try ' ' Use a blocking connection request ' since nothing can happen until we're connected ' Client.Connect(txtHost.Text, CInt(txtPort.Text)) ' ' Connected OK ' Set the UI appropriately ' and start an asynchronous read ' btnSend.Enabled = True btnConnect.Enabled = False 'MsgBox("Connected") Call Receive(Client) Catch ex As Exception MsgBox("Unable to Connect: " & ex.Message) ' ' Is this the correct way to gracefully terminate ? ' Application.Exit() End Try Else MsgBox(Error_Message) End If End Sub Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click ' ' Check there's something to send and send it asynchronously ' ' TODO: Put in a Try / Catch block and determine what to do ' in the event of an exception ' If txtToSend.Text <> "" Then ' ' Is this the most efficient method to use to convert the ' string data to a binary array ? ' (It feels a bit "VB6'ish") ' Dim bytSend(txtToSend.TextLength - 1) As Byte For i = 0 To txtToSend.TextLength - 1 bytSend(i) = Asc(txtToSend.Text.Substring(i, 1)) Next Client.Client.BeginSend(bytSend, 0, txtToSend.TextLength, 0, AddressOf SendCallback, Client) End If End Sub Private Sub SendCallback(ByVal ar As IAsyncResult) ' ' I guess I could check to ensure that all bytes ' have been sent by examining the return from EndSend(?) ' Client.Client.EndSend(ar) End Sub Private Sub Receive(ByVal rClient As TcpClient) ' ' Fire off a receive and let the CallBack routine do its work ' Dim state As New StateObject Try state.workClient = rClient rClient.Client.BeginReceive(state.buffer, 0, state.BufferSize, 0, AddressOf ReceiveCallBack, state) Catch ex As Exception ' ' TODO: Analyse the exception to determine if it's recoverable ' and take appropriate action ' MsgBox("Receive Error " & ex.Message) End Try End Sub Private Sub ReceiveCallBack(ByVal ar As IAsyncResult) ' ' Something's ready to be received ' get hold of it and use the Deligate (DataReceived) to update the UI Thread ' using the UpdateText routine ' Try Dim state As StateObject = CType(ar.AsyncState, StateObject) ' ' Flush the buffer ' state.sb.Length = 0 ' ' Pick up the Client Object, determine the amount of data received ' and convert it to a string. ' (The variable 'result' is defined as Public in a Module - I guess I could ' just pass it as a ByVal parameter to UpdateText instead or could it be a member ' of the StateObject ?) ' Dim rClient As TcpClient = state.workClient Dim bytesRead As Integer = rClient.Client.EndReceive(ar) If bytesRead > 0 Then state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)) result = state.sb.ToString BeginInvoke(New DataReceived(AddressOf UpdateText)) ' ' Start another asynchronous read ' rClient.Client.BeginReceive(state.buffer, 0, state.BufferSize, 0, AddressOf ReceiveCallBack, state) End If Catch ex As Exception ' ' TODO: Analyse the exception to determine if it's recoverable ' and take appropriate action ' MsgBox("Error in ReceiveCallBack: " & ex.Message) End Try End Sub Public Class StateObject Public workClient As TcpClient = Nothing Public BufferSize As Integer = 256 Public buffer(255) As Byte Public sb As New StringBuilder() End Class


Reply With Quote