|
-
Mar 28th, 2009, 01:39 PM
#1
Thread Starter
New Member
tcp/ip - consecutive serialized objects not deserializing. help!
Hi,
This is my first post on here--I've been teaching myself VB via forums like this and MSDN for about 2 years now.
I'm programming a computerized economics experiment, and I'm using a communications package that a guy I worked
with developed. He and I have been going back and forth trying to figure out what the heck is going on.
The upshot of the communications package is that there's a serializeable MQMessage class that we send back and forth, essentially just a package of an integer (Type), string (Text), and Object (Data). Most of the time, this goes according to plan.
The problem is this: If the client receives two or more messages back-to-back, the client stops raising the MessageArrived event. (and presumably, the same would hold true for the server--I should test this, but jeez-oh-man, I've been running test after test for the last week).
It's still connected, as on disconnect it throws the "Socket forcibly closed" exception. When it receives multiple messages sequentially, it's still receiving the data, it just never knows when the first message ends, and the buffer just keeps filling and filling. The problem seems to be that it can never successfully Deserialize the MQMessage object, and so it returns Nothing on the getCompletedMessage function and just keeps adding to the buffer (ABuffer.Length goes 1024, 2048, etc.). Any ideas on how to solve this would be GREATLY appreciated (I've been frustrated by this for a year or so, and have only recently taken upon myself to learn how the hell the TCP/IP part of this works to see if I can't find a solution.).
Code to follow.
--stopworth
-
Mar 28th, 2009, 01:39 PM
#2
Thread Starter
New Member
Re: tcp/ip - consecutive serialized objects not deserializing. help!
This is the server code:
Code:
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
Public Class MQmonitor
'Delegates
Public Delegate Sub MessageArrivedCallBack(ByVal Subject As Integer, ByVal message As MQMessage)
Public Delegate Sub TextArrivedCallBack(ByVal Subject As Integer, ByVal text As String)
Public Delegate Sub NewSubjectConnectedCallBack(ByVal Subject As Integer, ByVal UserName As String)
Public Delegate Sub SubjectReconnectedCallBack(ByVal Subject As Integer, ByVal UserName As String)
Public Delegate Sub SubjectDisconnectedCallBack(ByVal Subject As Integer, ByVal UserName As String)
Public Delegate Sub Socket_ErrorCallBack(ByVal e As Exception)
'Events
Public Event MessageArrived(ByVal Subject As Integer, ByVal message As MQMessage)
Public Event TextArrived(ByVal Subject As Integer, ByVal text As String)
Public Event NewSubjectConnected(ByVal Subject As Integer, ByVal UserName As String)
Public Event SubjectReconnected(ByVal Subject As Integer, ByVal UserName As String)
Public Event SubjectDisconnected(ByVal Subject As Integer, ByVal UserName As String)
Public Event Socket_Error(ByVal e As Exception)
'Fields & Private Vars
Private m_InitSubjectNumber As String = 101
Private SubjectNameTable As New Hashtable
Private StateTable As New Hashtable
Private isExperimentStart As Boolean
Dim m_ExpInstance As String
Dim m_ExpName As String
Dim m_port As Integer = "2955"
Dim tcpListener As TcpListener
Dim m_start As Boolean = False
Dim allClients As ArrayList = New ArrayList()
Dim currentID As Integer = 101
Dim listener As Socket
'Properties
- Public Property ExpInstance() As String
- Public Property ExpName() As String
- Public Property Port() As Integer
- Public Property InitialSubjectNumber() As Integer
'Public Functions
'SendMessage(m as MQMessage, x as Integer) As Exception : Send MQMessage object m to Client with SubjectID x
'BroadCastMessage(m as MQMessage) as Exception: Send MQMessage object m to all clients
'OpenServer() as Exception: Sets up SubjectIDs and opens a TCPListener on m_port()
'Code
Public Function SendMessage(ByVal msg As MQMessage, ByVal SubjectID As Integer) As Exception
Try
Dim state As ExpStateObject = StateTable.Item(SubjectID)
Me.Send(state, msg)
Catch ex As Exception
Return ex
End Try
Return Nothing
End Function
Public Function BroadCastMessage(ByVal msg As MQMessage) As Exception
Try
Dim myEnumerator As IDictionaryEnumerator = StateTable.GetEnumerator()
Dim state As ExpStateObject
While myEnumerator.MoveNext()
state = myEnumerator.Value
Me.Send(state, msg)
End While
Catch ex As Exception
Return ex
End Try
Return Nothing
End Function
Public Function OpenServer() As Exception
'Initializes the SubjectNumber (unique ID) and TCPListener and starts the TCPListener.
If (m_start) Then
Return New Exception("Queue has already been started")
End If
currentID = m_InitSubjectNumber
m_start = True
Dim bytes() As Byte = New [Byte](1024) {}
' Establish the local endpoint for the socket.
' The DNS name of the computer
' running the listener is "host.contoso.com".
' Bind the socket to the local endpoint and listen for incoming
' connections.
Try
Dim ipHostInfo As IPHostEntry = Dns.GetHostEntry(Dns.GetHostName)
Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
For Each ip As IPAddress In ipHostInfo.AddressList
If (ip.AddressFamily = AddressFamily.InterNetwork) Then
ipAddress = ip
Exit For
End If
Next
Dim localEndPoint As New IPEndPoint(ipAddress, m_port)
' Intializes a TCP/IP socket.
Dim listener As New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)
listener.Bind(localEndPoint)
listener.Listen(10)
' Start an asynchronous socket to listen for connections.
listener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), _
listener)
Catch e As Exception
Return e
End Try
Return Nothing
End Function
Private Sub AcceptCallback(ByVal ar As IAsyncResult)
' Get the socket that handles the client request.
Dim listener As Socket = CType(ar.AsyncState, Socket)
Dim handler As Socket = listener.EndAccept(ar)
handler.NoDelay = True
' Create the state object.
Dim state As New ExpStateObject()
state.workSocket = handler
handler.BeginReceive(state.buffer, 0, ExpStateObject.BufferSize, 0, _
New AsyncCallback(AddressOf ReceiveCallback), state)
listener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), listener)
End Sub 'AcceptCallback
Private Sub ReceiveCallback(ByVal ar As IAsyncResult)
Dim content As [String] = [String].Empty
' Retrieve the state object and the handler socket
' from the asynchronous state object.
Dim state As ExpStateObject = CType(ar.AsyncState, ExpStateObject)
Dim handler As Socket = state.workSocket
' Read data from client socket.
Try
Dim bytesRead As Integer = handler.EndReceive(ar)
If bytesRead > 0 Then
Dim message As MQMessage = state.getCompletedMessage(bytesRead)
If Not (message Is Nothing) Then
messageRecieved(state, message)
End If
handler.BeginReceive(state.buffer, 0, ExpStateObject.BufferSize, _
0, New AsyncCallback(AddressOf ReceiveCallback), state)
End If
Catch ex As Exception
RaiseEvent Socket_Error(ex)
End Try
End Sub 'ReadCallback
Private Sub messageRecieved(ByRef state As ExpStateObject, ByVal msg As MQMessage)
If msg.Type = MQMessage.TYPE_SUBJECT_CONNECTION_MESSAGE Then
connectionRequest(state, msg)
ElseIf msg.Type = MQMessage.TYPE_PLAIN_TEXT_MESSAGE Then
RaiseEvent TextArrived(state.SubjectID, msg.Text)
Else
RaiseEvent MessageArrived(state.SubjectID, msg)
End If
End Sub
Private Function connectionRequest(ByRef state As ExpStateObject, ByVal msg As MQMessage) As Integer
Dim userName As String = CType(msg.Data, MQMessage.SubjectConnectionMessage).UserName
Dim ID As Integer
If isExperimentStart Then
If SubjectNameTable.ContainsKey(userName) Then
ID = SubjectNameTable.Item(userName)
state.SubjectID = ID
updateStateTable(state, ID)
ReSendMessage(ID)
End If
Else
If SubjectNameTable.ContainsKey(userName) Then
Send(state, New MQMessage(MQMessage.TYPE_DUPLICATE_USERNAME_MESSAGE))
Else
ID = currentID
currentID += 1
state.SubjectID = ID
SubjectNameTable.Add(userName, ID)
updateStateTable(state, ID)
RaiseEvent NewSubjectConnected(ID, CType(msg.Data, MQMessage.SubjectConnectionMessage).UserName)
Dim message As New MQMessage(MQMessage.TYPE_LOGIN_CONFIRMED_MESSAGE)
message.Data = ID
Send(state, message)
End If
End If
End Function 'connectionRequest
Private Sub updateStateTable(ByVal state As ExpStateObject, ByVal subjectID As Integer)
If StateTable.ContainsKey(subjectID) Then
Dim oldState As ExpStateObject = StateTable.Item(subjectID)
Dim socket As Socket = oldState.workSocket
If Not (socket Is Nothing) Then
socket.Shutdown(SocketShutdown.Both)
socket.Close()
End If
StateTable.Remove(subjectID)
End If
StateTable.Add(subjectID, state)
End Sub 'updateStateTable
Private Sub ReSendMessage(ByVal subjectID As Integer)
Dim state As ExpStateObject = StateTable.Item(subjectID)
Dim msg As MQMessage
Dim i As Integer
SyncLock (state)
For i = 0 To state.MessageQueue.Count
msg = state.MessageQueue.Item(i)
state.workSocket.Send(msg.toBytes)
Next
End SyncLock
End Sub
Private Sub Send(ByVal handler As ExpStateObject, ByVal data As MQMessage)
'Dim byteData As Byte() = SerializeUtils.Serialize(data)
SyncLock (handler)
handler.MessageQueue.Add(data)
Dim message() As Byte = data.toBytes
handler.workSocket.Send(message)
End SyncLock
End Sub 'Send
Public Sub startExperiment()
isExperimentStart = True
End Sub
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|