Hi Dw.
I am developing a client server multi-thread application. This application uses signals(certain messages as signals), in order to perform a task for a client. For instance if a client wants to login, the client send a message as: Login:<username>:<password>
and on a server I first check if the message contains :
and if it does then I split the message using :
as a split.
I am using the client server code from http://www.vb.net-informations.com/communications/vb.net_multithreaded_server_socket_programming.htm
But I didn't use it as Console its both WinForms. I'm facing avery hug problem here. All of my activity codes are under the handleClient
class inside the doChat
but I've changed that to doData
.
My biggest problem comes when I run more then 1 client instances and when they all send a signal to retrieve data base on each client filter settings.
The Filter is just a string word which will tell the server for this client open database and retrieve all records let's say my filter was USA, then the server will retrieve all the records containing USA under the Country field. But first I first check if that record is available.
I have 2 tables on one database.
The first table is for transactions, then the second table is for registration.
The transaction table is where the transactions take place and its where most of the data sent to client(s) comes from, so this is a very busy table. It has 9 columns as follows.
username,bookedUser,Amount,dueDate,Status,RefNumber,Who,Remainder,pp
1) username -> this is the username for the registered user, this also helps when we need to locate the user under the registration table.
2) bookedUser -> this is 0 at first then if this user is open for bookings then once a another user books this user I put that user here, but I changed that when I added the Remainder, and the pp columns. So if let's say this user wants to be booked for 2500, if the other user offering to book this user says s/he will pay 2500 then that username is entered here. But if the amount is less then 2500 then I first check if the pp is open, if this is close then that means there can be no more bookings, else if this is open I then check if the field Remaining is greater then 0, if this is true then I check if the amount offered equal the remainder and do proper update. I will post a code for this bellow.
I have this under the doData() on the server side. Will only write what I saw giving me a problem.
Dim ClieUsername As String
Dim requestCount As Integer
Dim bytesFrom(10024) As Byte
Dim dataFromClient As String
Dim sendBytes As [Byte]()
Dim serverResponse As String
Dim rCount As String
requestCount = 0
While (True)
Try
requestCount = requestCount + 1
Dim networkStream As NetworkStream = client.GetStream
networkStream.Read(bytesFrom,0,CInt(client.ReceiveBufferSize))
dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom)
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"))
If dataFromClient.Contains(":") Then
Dim list() As String
list = dataFromClient.Split(":")
'Now I check which signal was sent.
If list(0).Contains("Login") Then
'Do login here.
Else
If list(0).Contains("bringlist") Then
' Checking to see if a user has specified a country.
If list(1).Trim("<",">") = Nothing Then
' The user has not specified a filter so just bring everything available.
Try
Dim Country As String
' Open a database connection.
ConnDB()
sql = "select * from transactions;"
cmd = New OleDbCommand(sql, conn)
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
Do While dr.Read = True
'Status variable is declared às global variable.
status = dr(4)
Dim qqrefnumber As String
If status = "Open" Then
Dim dDate As String
dDate = dr(3)
If dDate >= DateTime.Today Then
Dim xusername As String
xusername = dr(0)
price = dr(2) 'Amount
Dim Calcu As Double
qqrefnumber = dr(5)
Try
ConnDB()
Dim da As New OleDbDataAdapter(("select * from register where username ='" & xusername & "'"),conn)
Dim dt As New DataTable
da.Fill(dt)
If dt.Rows.Count > 0 Then
Country = dt.Rows(0).Item("Country") & ""
End If
Catch ex As Exception
End Try
' Sending data to the client.
response = "List:<" & xusername & ">:<" & price & ">:<" & Country & ">:<" & dDate & ">:<" & "Open>:<" & qqrefnumber
serverResponse = response
sendBytes = Encoding.ASCII.GetBytes(serverResponse)
networkStream.Write(sendBytes,0,sendBytes.Length)
networkStream.Flush()
Else
'Because there is no data meet this date
'Send a notification so that a client won't
'Freeze waiting for the response.
response = "nodata:<>"
serverResponse = response
sendBytes = Encoding.ASCII.GetBytes(serverResponse)
networkStream.Write(sendBytes,0,sendBytes.Length)
networkStream.Flush()
End If
Else
End If
Loop
Catch ex As Exception
'The error that is most generated here use to say
'Unspecified error message so just take it
'As if it didn't get any data so that the client won't freeze.
response ="nodata:<>"
serverResponse = response
sendBytes = Encoding.ASCII.GetBytes(serverResponse)
networkStream.Write(sendBytes,0,sendBytes.Length)
networkStream.Flush()
End Try
Else
' The user did specify the filter(country).
Dim myFilter As String = list(1).Trim("<",">")
Dim country As String
Try
ConnDB()
sql = "select * from transactions;"
cmd = New OleDbCommand(sql,conn)
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
Do While (True)
status = dr(4)
Dim qqrefnumber As String
If status = "Open" Then
Dim dDate As String
If dDate >= DateTime.Today Then
Dim xusername As String
xusername = dr(0)
price = dr(2)
qqrefnumber = dr(5)
Try
ConnDB()
Dim da As New OleDbDataAdapter(("select * from register where username ='" & xusername & "'"),conn)
Dim dt As New DataTable
da.Fill(dt)
If dt.Rows.Count > 0 Then
Country = dt.Rows(0).Item("Country") & ""
'Check to see if the Country match the filter.
If Country = myFilter Then
'Its does match so send it.
response = "List:<" & xusername & ">:<" & price & ">:<" & Country & ">:<" & dDate & ">:<" & "Open>:<" & qqrefnumber
serverResponse = response
sendBytes = Enconding.ASCII.GetBytes(serverResponse)
networkStream.Write(sendBytes,0,sendBytes.Length)
networkStream.Flush()
Else
End If
End If
Catch ex As Exception
End Try
Else
response = "nodata:<>"
serverResponse = response
sendBytes = Encoding.ASCII.GetBytes(serverResponse)
networkStream.Write(sendBytes,0,sendBytes.Length)
networkStream.Flush()
End If
Else
End If
Loop
Catch ex As Exception
'Send the response with nodata signal
End Try
End If
End If
The problem is that if I run one client everything is fine, but if I run more then one at the same time they all freezes but the server is not freezing. Bellow is the relevant client signaling code relevant to the above server code.
Own about that ConnDB you keep seeing here is the module.
Import System.Data.OleDb
Module ModConnection
Public cur As Form
Public dt As DataTable
Public conn As OleDbConnection
Public cmd As OleDbCommand
Public dr As OleDbDataReader
Public da As OleDbDataAdapter
Public ds As DataSet
Public sql As String
Public Sub ConnDB()
Try
conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source="mydatabasefullPath;Jet OLEDB:Database Password = "myPassword")
conn.Open()
Catch ex As Exception
Finally
End Try
End Sub
Public Function getDataTable(ByVal SQL As String) As DataTable
ConnDB()
Dim cmd As New OleDBCommand(SQL, conn)
Dim dt As New DataTable
Dim da As New OleDbDataAdapter(cmd)
da.Fill(dt)
Return dt
End Function
End Module
Now the client side code relevant to the above first code potion.
Basically what it does is that after certain time its send a signal message to the server to retrieve the list and the list can be retrieved based on the users filter or the list can be retrieved without being filtered.
I have 2 forms for this form4 is the form that is displayed to the user and the Feeder form is a form that is hidden, its keep sending the signal to the server and if the server send list it then add the data to form4's ListView.
On Feeder I have this.
1 BackgroundWorker
1 Timer.
The BackgroundWorker tries to establish a connection with server, and if the connection is established then its call/start timer1 which is what sends the signal to the server and receive the response and based on the response its perform the appropriate action.
The timer interval is 600.
Here is the code to send the signal and receive the response.
'First check if the user has filtered or not.
If Form1.lblFilter.Text = Nothing Then
'The user didn't filter.
Try
Dim serverStream As NetworkStream = clientSocket.GetStream
Dim bufferSize As Integer
Dim outStream As Byte() = System.Text.Encoding.ASCII.GetBytes("bringlist:<>" + "$")
serverStream.Write(outStream,0,outStream.Length)
serverStream.Flush()
Dim inStream(10024) As Byte
bufferSize = clientSocket.ReceiveBufferSize
serverStream.Read(inStream,0,bufferSize)
Dim returndata As String = System.Text.Encoding.ASCII.GetString(inStream)
msg(returndata)
Dim xlist() As String
If returndata.Contains("List") Then
xlist = returndata.Split(":")
'I check if the listView is empty or not
'Then if not I then loop through each item
'To see if the new item hasn't been already added
'This is to prevent having a long list
'Of one thing.
' This is how I add data to listview on form4
Dim data_Array(5) As String
Dim itmData As ListViewItem
data_Array(0) = xlist(1).Trim("<",">")
data_Array(1) = xlist(2).Trim("<",">")
data_Array(2) = xlist(3).Trim("<",">")
data_Array(3) = xlist(4).Trim("<",">")
data_Array(4) = xlist(5).Trim("<",">")
itmData = New ListViewItem(data_Array)
Form4.ListView1.Items.Add(itmData)
So that's how I go about this but the client freezes the first two sometimes do receive one record each and then freezes.
What am I missing/doing wrong here.
Sorry I know this post is too long now so will just stop there.