Looking for Constructive Criticism for TcpListener Windows Service Code

Allstar

New Member
I don't have a lot of experience with Windows Services, TcpListeners, and XML. But, this code does seem to be working. Does anyone see anything that may cause problems when moved to a production environment? Also, I don't like the string manipulation (see comments "remove header, namespace elements, labels")I'm doing in Sub ProcessStream, but If I rip it out the code doesn't work.Here's the Data:\[code\]<?xml version="1.0" encoding="UTF-8"?><ale:ECReports elevation="135" date="2013-03-25T17:42:42.805Z" xmlns:ale="urn:epcglobal:ale:xsd:1" specName="Mojix_Loc_Spec" latitude="34.03" terminationCondition="DATA_AVAILABLE" declination="0.0" longitude="-118.47" schemaVersion="1.1" creationDate="2013-03-25T17:42:42.806Z" totalMilliseconds="449684" ALEID="D4AE52BCBFD6" initiationCondition="REQUESTED" units="feet"> <reports> <report reportName="zone report"> <group> <groupList> <member posZ="3" ts="2013-03-27T13:04:52.436Z" logicalReader="Rack_2a_2" posX="67.0000076293945" posY="-3" eNode="3EE0EE5"> <rawHex>urn:epc:raw:96.xD1D101000000000000000025</rawHex> </member> <member posZ="3" ts="2013-03-27T13:04:52.397Z" logicalReader="Rack_2a_1" posX="67" posY="-6.00000047683716" eNode="3EE0EE1"> <rawHex>urn:epc:raw:96.xD1D10100000000000000000A</rawHex> </member>n:epc:raw:96.x2F24D3932353031000000019</rawHex> </groupList> <groupCount> <count>2</count> </groupCount> </group> </report> </reports></ale:ECReports>\[/code\]Here is the code:\[code\] Imports System.Threading Imports System.Net Imports System.Net.Sockets Imports System.Text Imports System.Xml Imports System.Data.SqlClientPublic Class MojixLoc Private stopping As Boolean Private stoppedEvent As ManualResetEvent Protected myListener As MojixListener Protected listenerThread As Thread Public Sub New() InitializeComponent() Me.stopping = False Me.stoppedEvent = New ManualResetEvent(False) End Sub Protected Overrides Sub OnStart(ByVal args() As String) ' Log a service start message to the Application log. My.Application.Log.WriteEntry("MojixLocWindowsService in OnStart.") myListener = New MojixListener listenerThread = New Thread(AddressOf myListener.Main) listenerThread.IsBackground = True listenerThread.Start() End Sub Protected Overrides Sub OnStop() ' Log a service stop message to the Application log. My.Application.Log.WriteEntry("MojixLocWindowsService in OnStop.") myListener.Shutdown() listenerThread.Join(1000) ' give it a second ' If listenerThread.IsAlive Then listenerThread.Abort() End If End Sub Public Class MojixListener Private tcpClientConnected As New ManualResetEvent(False) Private server As TcpListener Protected shutingdown As Boolean = False Public Sub Main() Dim port As Int32 = 8000 Dim localAddr As IPAddress = IPAddress.Parse("192.168.80.205") server = New TcpListener(localAddr, port) shutingdown = False ' Start listening for client requests. server.Start() While Not shutingdown ' Perform a async call to accept requests. DoBeginAcceptTcpClient(server) End While End Sub ' Accept one client connection asynchronously. Public Sub DoBeginAcceptTcpClient(listener As TcpListener) ' Set the event to nonsignaled state. tcpClientConnected.Reset() ' Start to listen for connections from a client. ' Accept the connection. ' BeginAcceptSocket() creates the accepted socket. 'ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ServiceWorkerThread)) listener.BeginAcceptTcpClient(New AsyncCallback(AddressOf DoAcceptTcpClientCallback), listener) ' Wait until a connection is made and processed before ' continuing. tcpClientConnected.WaitOne() End Sub 'DoBeginAcceptTcpClient Public Sub DoAcceptTcpClientCallback(ar As IAsyncResult) ' Get the listener that handles the client request. Dim listener As TcpListener = CType(ar.AsyncState, TcpListener) ' End the operation and display the received data on ' the console. Dim client As TcpClient = listener.EndAcceptTcpClient(ar) ' Process the connection here. (Add the client to a ' server table, read data, etc.) ' Get a stream object for reading and writing Dim stream As NetworkStream = client.GetStream() ProcessStream(stream) ' Signal the calling thread to continue. tcpClientConnected.Set() End Sub 'DoAcceptTcpClientCallback Private Sub ProcessStream(stream As NetworkStream) Dim Data As String = Nothing Dim buffer(32768) As Byte Dim ms As New IO.MemoryStream Do While True Dim read As Integer = stream.Read(buffer, 0, buffer.Length) If read = 0 Then Data = http://stackoverflow.com/questions/15841502/System.Text.ASCIIEncoding.ASCII.GetString(ms.ToArray()) Exit Do End If ms.Write(buffer, 0, read) Loop'remove header Dim ndx As Integer = Data.IndexOf("<") Data = http://stackoverflow.com/questions/15841502/Data.Substring(ndx)'remove namespace elements ndx = Data.IndexOf("<ale:") Dim ndx2 As Integer = Data.IndexOf("<reports>") Data = http://stackoverflow.com/questions/15841502/Data.Substring(0, ndx) & Data.Substring(ndx2) If Data.EndsWith("</ale:ECReports>") Then Data = http://stackoverflow.com/questions/15841502/Data.Substring(0, Data.LastIndexOf("</ale:ECReports>")) End If 'remove labels Data = http://stackoverflow.com/questions/15841502/Replace(Data,"urn:epc:raw:96.x", "") Try Dim xdoc As New XmlDocument xdoc.LoadXml(Data) SqlImportLoc(xdoc) SqlImportLocHistory(xdoc) Catch ex As Exception My.Application.Log.WriteException(ex, TraceEventType.Error, "Malformed XML.") End Try End Sub Private Sub SqlImportLoc(xDoc As XmlDocument) Dim cn As New SqlConnection(My.Settings.MojixConnectionString) Dim mysql, mysql2 As String mysql = "Declare @xml XML Set @xml = '" & xDoc.InnerXml & "'" mysql2 = <sql> ;merge Loc as l using ( select r.c.value('rawHex[1]','varchar(40)') TagId, r.c.value('@logicalReader[1]','varchar(50)') LogicalReader, r.c.value('@ts[1]','datetime') TS, r.c.value('@posX[1]','real') PosX, r.c.value('@posY[1]','real') PosY from @xml.nodes('/reports/report/group/groupList/member') r(c) ) as s on l.TagIdStr = s.TagId When matched then update set l.LogicalReader = s.LogicalReader, l.TimeStamp = s.TS, l.PosX = s.PosX, l.PosY = s.Posy when not matched by target then insert(TagIdStr, LogicalReader, TimeStamp, PosX, PosY) values(s.TagId, s.LogicalReader, s.TS, s.PosX, s.PosY) when not matched by source and TimeStamp < dateadd(dd, -30, getdate()) then delete ;</sql> mysql += mysql2 Dim cmd As New SqlCommand(mysql, cn) Try cn.Open() cmd.ExecuteNonQuery() Catch ex As Exception My.Application.Log.WriteException(ex, TraceEventType.Error, "SqlImportLoc Error.") Finally cn.Close() End Try End Sub Private Sub SqlImportLocHistory(xdoc As XmlDocument) Dim cn As New SqlConnection(My.Settings.MojixConnectionString) Dim mysql, mysql2 As String mysql = "Declare @xml XML Set @xml = '" & xdoc.InnerXml & "'" mysql2 = <sql> delete from LocHistory where Timestamp < dateadd(hh, -1, getdate()) insert into LocHistory select r.c.value('rawHex[1]','varchar(40)') TagId, r.c.value('@logicalReader[1]','varchar(50)') LogicalReader, r.c.value('@ts[1]','datetime') TS, r.c.value('@posX[1]','real') PosX, r.c.value('@posY[1]','real') PosY from @xml.nodes('/reports/report/group/groupList/member') r(c) </sql> mysql += mysql2 Dim cmd As New SqlCommand(mysql, cn) Try cn.Open() cmd.ExecuteNonQuery() Catch ex As Exception My.Application.Log.WriteException(ex, TraceEventType.Error, "SqlImportLocHistory Error.") Finally cn.Close() End Try End Sub Public Sub Shutdown() shutingdown = True End Sub End ClassEnd Class\[/code\]Thank you for your help.
 
Back
Top