Simultaneously receive message from clients using sockets (with Async) - vb.net
i have a CyberCafe Software Program with a code that sends a message by the client(socket) and received by the server(also a socket) using Network Stream. (i'm somewhat new about sockets and network stream)
Server Side:
'receive msg from client
Private Sub OnRecieve(ByVal ar As IAsyncResult)
Try
Dim ns As NetworkStream = CType(ar.AsyncState, NetworkStream)
ns.BeginRead(byteData, 0, byteData.Length, New AsyncCallback(AddressOf OnRecieve), ns)
Dim bytesRec As Byte() = byteData
Dim message As String = System.Text.ASCIIEncoding.ASCII.GetString(bytesRec)
Invoke(New _Read(AddressOf Read), message)
ns.Flush()
ns.Close()
Catch ex As Exception
'check for Disconnection or Force Disconnection
Invoke(New _dc(AddressOf dc))
End Try
End Sub
Client Side:
'send msg to server
Private Sub Send(ByVal msg As String, ByVal client As Socket)
Try
Dim sendBytes As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(msg)
NetStream = New NetworkStream(client)
NetStream.BeginWrite(sendBytes, 0, sendBytes.Length, New AsyncCallback(AddressOf OnSend), NetStream)
Catch ex As Exception
If Not clientSocket.Connected Then 'if connection was forcibly disconnected
'reconnecting to the server
Invoke(New _status(AddressOf status), clientSocket)
Connect()
End If
End Try
End Sub
The scenario is, there are 2 clients waiting to connect to the server(the other one is a Virtual Machine), and when i finally run the server, simultaneous connection had no problems, but receiving a message simultaneously didn't worked out. Sometimes it received one message only. Sometimes the message is wrong. Maybe a deadlock.
So, how can i implement this kind of situation? i asked Brother Google :P and he told me about AsyncTask, but i dunno how to do it :(
Any help would be obliged ^_^ Apologies for any bad english.
Update:
Sorry for my incomplete question.
I've added the EndRead/EndWrite method, but i'm not sure if i used the EndRead method right... I just inserted the EndRead before the BeginRead, but it still works though.
Thank you for the help Visual Vincent ^_^.
Also, my sockets are stored in the ListView as tag after they connect. And their IPAddress and HostName are stored in the database (MSAccess). And i don't have any TCP used in this code. Just Sockets and NetworkStreams. IDK if that is ok, but it works.
Server Side(Full):
Imports System.Net, System.Net.Sockets
Imports System.Data.OleDb
Public Class Server
Dim serverSocket As Socket
Dim clientSocket As Socket
Dim netstream As NetworkStream
Dim byteData(1023) As Byte
Dim ipEndPoint As IPEndPoint
Dim myList As New List(Of String)
Dim myList2 As New List(Of String)
Dim txt As String
'listening to clients from port 8800
Private Sub frmServer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Invoke(New _AddExistingClient(AddressOf AddExistingClient))
Listen()
End Sub
Delegate Sub _AddExistingClient()
Private Sub AddExistingClient()
Try
If conn.State = ConnectionState.Open Then conn.Close()
conn.Open()
query = "select * from Clients_tbl"
comm = New OleDbCommand(query, conn)
reader = comm.ExecuteReader
While reader.Read
Dim lvi As New ListViewItem(reader("HostName").ToString)
lvi.Text = reader("HostName")
lvi.SubItems.Add("P00.00") 'price 1
lvi.SubItems.Add("00:00:00") 'time 2
lvi.ImageKey = "Grey.ico"
lsvClients.Items.Add(lvi)
End While
lsvClients.Sort()
conn.Close()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub Listen()
Try
serverSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
ipEndPoint = New IPEndPoint(IPAddress.Any, 8800)
serverSocket.Bind(ipEndPoint)
serverSocket.Listen(1)
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub OnAccept(ByVal ar As IAsyncResult)
Try
clientSocket = serverSocket.EndAccept(ar)
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
CheckIfExist(clientSocket)
netstream = New NetworkStream(clientSocket)
netstream.BeginRead(byteData, 0, byteData.Length, New AsyncCallback(AddressOf OnRecieve), netstream)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Delegate Sub _CheckIfExist(ByVal client As Socket)
Private Sub CheckIfExist(ByVal client As Socket)
Try
If InvokeRequired Then
Invoke(New _CheckIfExist(AddressOf CheckIfExist), client)
Exit Sub
End If
Dim RemoteIP As String = IPAddress.Parse(CType(client.RemoteEndPoint, IPEndPoint).Address.ToString).ToString
Dim host As String = Dns.GetHostEntry(RemoteIP).HostName.ToString
If conn.State = ConnectionState.Open Then conn.Close()
conn.Open()
query = "select * from Clients_tbl where HostName = '" + host + "'"
comm = New OleDbCommand(query, conn)
reader = comm.ExecuteReader
While reader.Read
If reader("IPAddress").ToString <> RemoteIP Then 'if socket do exist in the database but IPAddress was changed
ChangeIP(RemoteIP, host)
End If
count += 1
End While
If count = 0 Then 'if socket do not exist in the database
Add2DB(RemoteIP, host)
AddNewClient(client)
ElseIf count = 1 Then 'if socket do exist in the database and in the listview
For Each item As ListViewItem In lsvClients.Items
If item.Text = host Then
item.Tag = client
item.ImageKey = "Red.ico"
End If
Next
ElseIf count > 1 Then
MsgBox("Duplicate found")
End If
count = 0
conn.Close()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Delegate Sub _ChangeIP(ByVal RemoteIP As String, ByVal host As String)
Private Sub ChangeIP(ByVal RemoteIP As String, ByVal host As String) 'connection is still opened
Try
If InvokeRequired Then
Invoke(New _ChangeIP(AddressOf ChangeIP), RemoteIP, host)
Exit Sub
End If
query = "update Clients_tbl set IPAddress = '" + RemoteIP + "' where HostName = '" + host + "'"
comm = New OleDbCommand(query, conn)
reader = comm.ExecuteReader
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Delegate Sub _Add2DB(ByVal RemoteIP As String, ByVal host As String)
Private Sub Add2DB(ByVal RemoteIP As String, ByVal host As String) 'connection is still opened
Try
If InvokeRequired Then
Invoke(New _Add2DB(AddressOf Add2DB), RemoteIP, host)
Exit Sub
End If
query = "insert into Clients_tbl values('" + RemoteIP + "', '" + host + "')"
comm = New OleDbCommand(query, conn)
reader = comm.ExecuteReader
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
'add client to ListView
Delegate Sub _AddNewClient(ByVal client As Socket)
Private Sub AddNewClient(ByVal client As Socket)
Try
If InvokeRequired Then
Invoke(New _AddNewClient(AddressOf AddNewClient), client)
Exit Sub
End If
Dim lvi As New ListViewItem(client.LocalEndPoint.ToString)
Dim RemoteIP As String = IPAddress.Parse(CType(client.RemoteEndPoint, IPEndPoint).Address.ToString).ToString
Dim host As String = Dns.GetHostEntry(RemoteIP).HostName.ToString
lvi.Text = host
lvi.Tag = client
lvi.SubItems.Add("P00.00") 'price 1
lvi.SubItems.Add("00:00:00") 'time 2
lvi.ImageKey = "Red.ico"
lsvClients.Items.Add(lvi)
lsvClients.Sort()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
'Send msg to specific client
Private Sub Send(ByVal msg As String, ByVal client As Socket)
Try
netstream = New NetworkStream(client)
Dim sendBytes As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(msg)
netstream.BeginWrite(sendBytes, 0, sendBytes.Length, New AsyncCallback(AddressOf OnSend), netstream)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub OnSend(ByVal ar As IAsyncResult)
Try
Dim ns As NetworkStream = CType(ar.AsyncState, NetworkStream)
ns.EndWrite(ar)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Delegate Sub _dc()
Private Sub dc()
For Each lvi As ListViewItem In lsvClients.Items
If Not lvi.Tag Is Nothing Then
Dim S As Socket = lvi.Tag
If Not S.Connected Then lvi.ImageKey = "Grey.ico"
End If
Next
End Sub
'receive msg from client
Private Sub OnRecieve(ByVal ar As IAsyncResult)
Try
Dim ns As NetworkStream = CType(ar.AsyncState, NetworkStream)
ns.EndRead(ar)
ns.BeginRead(byteData, 0, byteData.Length, New AsyncCallback(AddressOf OnRecieve), ns)
Dim bytesRec As Byte() = byteData
Dim message As String = System.Text.ASCIIEncoding.ASCII.GetString(bytesRec)
Invoke(New _Read(AddressOf Read), message)
ns.Flush()
ns.Close()
Catch ex As Exception
'check for Disconnection or Force Disconnection
Invoke(New _dc(AddressOf dc))
End Try
End Sub
Delegate Sub _Read(ByVal msg As String)
Private Sub Read(ByVal msg As String)
Try
myList2 = msg.Split("~").ToList
'mylist.Add("0") 'command number
'mylist.Add(host) 'host name of this client
'mylist.Add(lblState.Text)
'mylist.Add(lblTime.Tag.ToString)
Select Case Integer.Parse(myList2(0))
Case 0
For Each lvi As ListViewItem In lsvClients.Items
If lvi.Text = myList2(1) Then
If myList2(2) = "Timed" Then
lvi.ImageKey = "Green.ico"
ElseIf myList2(2) = "Open"
lvi.ImageKey = "Blue.ico"
End If
lvi.SubItems(2).Tag = Integer.Parse(myList2(3))
End If
Next
End Select
myList2.Clear()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer1.Tick
Invoke(New _Counter(AddressOf Counter))
End Sub
Delegate Sub _Counter()
Private Sub Counter()
Try
If lsvClients.Items.Count > 0 Then
For Each time As ListViewItem In lsvClients.Items
'//////////////
If time.ImageKey = "Green.ico" Then
time.SubItems(2).Tag -= 1
time.SubItems(2).Text = GetTime(time.SubItems(2).Tag)
If time.SubItems(2).Tag = 0 Then time.ImageKey = "Red.ico"
ElseIf time.ImageKey = "Blue.ico" Then
time.SubItems(2).Tag += 1
time.SubItems(2).Text = GetTime(time.SubItems(2).Tag)
End If
'//////////////
Next
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Function GetTime(ByVal time As Integer) As String
Dim Hrs As Integer 'number of hours '
Dim Min As Integer 'number of Minutes '
Dim Sec As Integer 'number of Sec '
'Seconds'
Sec = time Mod 60
'Minutes'
Min = ((time - Sec) / 60) Mod 60
'Hours'
Hrs = ((time - (Sec + (Min * 60))) / 3600) Mod 60
Return Format(Hrs, "00") & ":" & Format(Min, "00") & ":" & Format(Sec, "00")
End Function
Private Sub btnStartTime_Click(sender As Object, e As EventArgs) Handles btnStartTime.Click
Try
If lsvClients.SelectedItems.Count <> 0 Then
myList.Add("0")
myList.Add("10") 'time
myList.Add("15") 'price
txt = String.Join("~", myList)
Send(txt, lsvClients.SelectedItems(0).Tag)
lsvClients.SelectedItems(0).SubItems(2).Tag = myList(1)
lsvClients.SelectedItems(0).ImageKey = "Green.ico"
myList.Clear()
Else
MsgBox("Select first")
End If
Catch ex As Exception
Dim client As Socket = lsvClients.SelectedItems(0).Tag
If Not client.Connected Then
MsgBox("Disconnected")
End If
End Try
End Sub
Private Sub btnOpenTime_Click(sender As Object, e As EventArgs) Handles btnOpenTime.Click
Try
If lsvClients.SelectedItems.Count <> 0 Then
myList.Add("2")
myList.Add("0") 'time
myList.Add("0") 'price
txt = String.Join("~", myList)
Send(txt, lsvClients.SelectedItems(0).Tag)
lsvClients.SelectedItems(0).SubItems(2).Tag = myList(1)
lsvClients.SelectedItems(0).ImageKey = "Blue.ico"
myList.Clear()
Else
MsgBox("Select first")
End If
Catch ex As Exception
Dim client As Socket = lsvClients.SelectedItems(0).Tag
If Not client.Connected Then
MsgBox("Disconnected")
End If
End Try
End Sub
Private Sub btnExtendTime_Click(sender As Object, e As EventArgs) Handles btnExtendTime.Click
Try
If lsvClients.SelectedItems.Count <> 0 Then
myList.Add("1")
myList.Add("10") 'time
myList.Add("15") 'price
txt = String.Join("~", myList)
Send(txt, lsvClients.SelectedItems(0).Tag)
lsvClients.SelectedItems(0).SubItems(2).Tag += myList(1)
lsvClients.SelectedItems(0).ImageKey = "Green.ico"
myList.Clear()
Else
MsgBox("Select first")
End If
Catch ex As Exception
Dim client As Socket = lsvClients.SelectedItems(0).Tag
If Not client.Connected Then
MsgBox("Disconnected")
End If
End Try
End Sub
Private Sub btnPauseTime_Click(sender As Object, e As EventArgs) Handles btnPauseTime.Click
Try
If lsvClients.SelectedItems.Count <> 0 Then
myList.Add("3")
myList.Add("00:00:00") 'time
myList.Add("0") 'price
txt = String.Join("~", myList)
Send(txt, lsvClients.SelectedItems(0).Tag)
If lsvClients.SelectedItems(0).ImageKey = "Green.ico" Then
lsvClients.SelectedItems(0).ImageKey = "Green2Yellow.ico"
ElseIf lsvClients.SelectedItems(0).ImageKey = "Blue.ico"
lsvClients.SelectedItems(0).ImageKey = "Blue2Yellow.ico"
End If
myList.Clear()
Else
MsgBox("Select first")
End If
Catch ex As Exception
Dim client As Socket = lsvClients.SelectedItems(0).Tag
If Not client.Connected Then
MsgBox("Disconnected")
End If
End Try
End Sub
Private Sub btnResumeTime_Click(sender As Object, e As EventArgs) Handles btnResumeTime.Click
Try
If lsvClients.SelectedItems.Count <> 0 Then
myList.Add("4")
myList.Add("00:00:00") 'time
myList.Add("0") 'price
txt = String.Join("~", myList)
Send(txt, lsvClients.SelectedItems(0).Tag)
If lsvClients.SelectedItems(0).ImageKey = "Green2Yellow.ico" Then
lsvClients.SelectedItems(0).ImageKey = "Green.ico"
ElseIf lsvClients.SelectedItems(0).ImageKey = "Blue2Yellow.ico"
lsvClients.SelectedItems(0).ImageKey = "Blue.ico"
End If
myList.Clear()
Else
MsgBox("Select first")
End If
Catch ex As Exception
Dim client As Socket = lsvClients.SelectedItems(0).Tag
If Not client.Connected Then
MsgBox("Disconnected")
End If
End Try
End Sub
End Class
Client Side(full):
Imports System.Net, System.Net.Sockets, System.IO
Public Class Client
Dim clientSocket As Socket
Dim NetStream As NetworkStream
Dim byteData(1023) As Byte
Dim ipEndpoint As IPEndPoint
Dim host As String = Dns.GetHostName
Dim ip As IPAddress = IPAddress.Parse("192.168.56.1") 'Dns.GetHostEntry(host).AddressList(0)
Dim AppPath As String = Application.StartupPath
Dim writer As StreamWriter
Dim reader As StreamReader
Dim mylist As New List(Of String)
Dim txt As String
'/////////////////////connecting to server at port 8800
Private Sub Client_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Try
Invoke(New _readtext(AddressOf readtext))
Connect()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub Connect()
Try
clientSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
ipEndpoint = New IPEndPoint(ip, 8800)
clientSocket.BeginConnect(ipEndpoint, New AsyncCallback(AddressOf OnConnect), Nothing)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub OnConnect(ByVal ar As IAsyncResult)
Try
Invoke(New _status(AddressOf status), clientSocket)
clientSocket.EndConnect(ar)
'Invoke(New _SendTimeState(AddressOf SendTimeState))
NetStream = New NetworkStream(clientSocket)
NetStream.BeginRead(byteData, 0, byteData.Length, New AsyncCallback(AddressOf Recieve), NetStream)
'Invoke(New _SendTimeState(AddressOf SendTimeState))
Catch ex As Exception
If Not clientSocket.Connected Then
Invoke(New _status(AddressOf status), clientSocket)
Connect()
End If
End Try
End Sub
Delegate Sub _SendTimeState()
Private Sub SendTimeState()
Try
mylist.Add("0") 'command number
mylist.Add(host) 'host name of this client
mylist.Add(lblState.Text)
mylist.Add(lblTime.Tag.ToString)
txt = String.Join("~", mylist)
Send(txt, clientSocket)
txt = ""
mylist.Clear()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Delegate Sub _readtext()
Private Sub readtext()
Try
reader = New StreamReader(AppPath & "\time.txt")
Dim x As Integer = reader.ReadLine
reader.Close()
If x <> 0 Then
lblTime.Tag = x
reader = New StreamReader(AppPath & "\state.txt")
Dim state As String = reader.ReadLine
reader.Close()
lblState.Text = state
Timer1.Start()
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Delegate Sub _writetext(ByVal file As String, ByVal txt As String)
Private Sub writetext(ByVal file As String, ByVal txt As String)
Try
If InvokeRequired Then
Invoke(New _writetext(AddressOf writetext), file, txt)
Exit Sub
End If
writer = New StreamWriter(AppPath & file, False)
writer.WriteLine(txt)
writer.Close()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Delegate Sub _status(ByVal client As Socket)
Private Sub status(ByVal client As Socket)
lblConnection.Text = client.Connected.ToString
End Sub
'receive msg from server
Private Sub Recieve(ByVal ar As IAsyncResult)
Try
Dim ns As NetworkStream = CType(ar.AsyncState, NetworkStream)
ns.EndRead(ar)
ns.BeginRead(byteData, 0, byteData.Length, New AsyncCallback(AddressOf Recieve), ns)
Dim bytesRec As Byte() = byteData
Dim message As String = System.Text.ASCIIEncoding.ASCII.GetString(bytesRec)
Invoke(New _Read(AddressOf Read), message)
Catch ex As Exception
If Not clientSocket.Connected Then 'if connection was forcibly disconnected
'reconnecting to the server
Invoke(New _status(AddressOf status), clientSocket)
Connect()
End If
End Try
End Sub
Delegate Sub _Read(ByVal msg As String)
Private Sub Read(ByVal msg As String)
Try
mylist = msg.Split("~").ToList
'mylist(0) is command
'mylist(1) is time
'mylist(2) price
Select Case Integer.Parse(mylist(0))
Case 0 'timed
lblState.Text = "Timed"
lblTime.Tag = Integer.Parse(mylist(1))
lblTime.Text = GetTime(lblTime.Tag)
lblPrice.Text = Integer.Parse(lblPrice.Text) + Integer.Parse(mylist(2))
lblState.Tag = lblState.Text
writetext("\time.txt", lblTime.Tag.ToString)
writetext("\state.txt", "Timed")
Timer1.Start()
Case 1 'extend time
lblTime.Tag += Integer.Parse(mylist(1))
lblTime.Text = GetTime(lblTime.Tag)
lblPrice.Text = Integer.Parse(lblPrice.Text) + Integer.Parse(mylist(2))
If Not Timer1.Enabled Then Timer1.Start()
Case 2 'open time
lblState.Text = "Open"
lblTime.Tag = Integer.Parse(mylist(1))
lblTime.Text = GetTime(lblTime.Tag)
lblPrice.Text = mylist(2)
lblState.Tag = lblState.Text
writetext("\time.txt", lblTime.Tag.ToString)
writetext("\state.txt", "Open")
Timer1.Start()
Case 3 'pause time
lblState.Text = "Paused"
Timer1.Stop()
Case 4 'resume time
lblState.Text = lblState.Tag
Timer1.Start()
Case 5 'stop time
lblState.Text = "Stop"
writetext("\time.txt", "0")
writetext("\state.txt", "Stop")
Timer1.Stop()
Case 6 'shutdown
Case 7 'reset
Case 8 'send msg
End Select
mylist.Clear()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
'send msg to server
Private Sub Send(ByVal msg As String, ByVal client As Socket)
Try
Dim sendBytes As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(msg)
NetStream = New NetworkStream(client)
NetStream.BeginWrite(sendBytes, 0, sendBytes.Length, New AsyncCallback(AddressOf OnSend), NetStream)
Catch ex As Exception
If Not clientSocket.Connected Then 'if connection was forcibly disconnected
'reconnecting to the server
Invoke(New _status(AddressOf status), clientSocket)
Connect()
End If
End Try
End Sub
Private Sub OnSend(ByVal ar As IAsyncResult)
Try
Dim ns As NetworkStream = CType(ar.AsyncState, NetworkStream)
ns.EndWrite(ar)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer1.Tick
Try
Select Case lblState.Text
Case "Timed"
lblTime.Tag -= 1
lblTime.Text = GetTime(lblTime.Tag)
writetext("\time.txt", lblTime.Tag.ToString)
If lblTime.Tag = 0 Then Timer1.Stop()
Case "Open"
lblTime.Tag += 1
lblTime.Text = GetTime(lblTime.Tag)
writetext("\time.txt", lblTime.Tag.ToString)
End Select
Catch ex As Exception
If Not clientSocket.Connected Then 'if connection was forcibly disconnected
'reconnecting to the server
Invoke(New _status(AddressOf status), clientSocket)
Connect()
End If
MsgBox(ex.ToString)
End Try
End Sub
Private Function GetTime(ByVal time As Integer) As String
Dim Hrs As Integer 'number of hours '
Dim Min As Integer 'number of Minutes '
Dim Sec As Integer 'number of Sec '
'Seconds'
Sec = time Mod 60
'Minutes'
Min = ((time - Sec) / 60) Mod 60
'Hours'
Hrs = ((time - (Sec + (Min * 60))) / 3600) Mod 60
Return Format(Hrs, "00") & ":" & Format(Min, "00") & ":" & Format(Sec, "00")
End Function
End Class
OleDb Module:
Imports System.Data.OleDb
Module oledb
Dim AppPath As String = Application.StartupPath
Public conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + AppPath + "\ServerDatabase.mdb;User Id=Admin;Password=")
Public comm As OleDbCommand
Public reader As OleDbDataReader
Public query As String
Public count As Integer
End Module
(Can't add this post on my first post because it reached it's max capacity :P)
Here's the slightly changed Received function:
'receive msg from client
Private Sub Recieve(ByVal ar As IAsyncResult)
Try
Dim ns As NetworkStream = CType(ar.AsyncState, NetworkStream)
Dim message As String = ""
ByteSize = ns.EndRead(ar)
message = String.Concat(message, System.Text.ASCIIEncoding.ASCII.GetString(byteData, 0, ByteSize))
ns.BeginRead(byteData, 0, byteData.Length, New AsyncCallback(AddressOf Recieve), ns)
'if there are still data left in the network stream
While ns.DataAvailable
ns.BeginRead(byteData, 0, byteData.Length, New AsyncCallback(AddressOf Recieve), ns)
End While
Invoke(New _Read(AddressOf Read), message)
Catch ex As Exception
'check for Disconnection or Force Disconnection
Invoke(New _dc(AddressOf dc))
End Try
End Sub
I saw on the MS Documentation about NetworkStream.EndRead that the EndRead comes first before BeginRead. Maybe it is only applicable on Read.
NetworkStream.EndRead Method (IAsyncResult)
But the problem still persist :(
Related
How to get ipv4 addresses of all computers on a network in VB.NET
I have a Windows Forms app in Visual basic that is currently sending messages back and forth between two computers. Currently, the user has to manually enter the ipv4 address of the receiver of the message. what I would like to do is put the ipv4 addresses of all the computers on the network into a combo box so the user has a list to pick from. I have searched a whole bunch of different forums and am unable to find a working solution. Public Class Form1 Dim strHostName As String Dim strIPAddress As String Dim running As Boolean = False Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load strHostName = System.Net.Dns.GetHostName() strIPAddress = System.Net.Dns.GetHostByName(strHostName).AddressList(0).ToString() Me.Text = strIPAddress txtIP.Text = strIPAddress running = True 'run listener on separate thread Dim listenTrd As Thread listenTrd = New Thread(AddressOf StartServer) listenTrd.IsBackground = True listenTrd.Start() End Sub Private Sub Form1_FormClosing(sender As Object, e As EventArgs) Handles MyBase.FormClosing running = False End Sub Sub StartServer() Dim serverSocket As New TcpListener(CInt(txtPort.Text)) Dim requestCount As Integer Dim clientSocket As TcpClient Dim messageReceived As Boolean = False While running messageReceived = False serverSocket.Start() msg("Server Started") clientSocket = serverSocket.AcceptTcpClient() msg("Accept connection from client") requestCount = 0 While (Not (messageReceived)) Try requestCount = requestCount + 1 Dim networkStream As NetworkStream = clientSocket.GetStream() Dim bytesFrom(10024) As Byte networkStream.Read(bytesFrom, 0, bytesFrom.Length) Dim dataFromClient As String = System.Text.Encoding.ASCII.GetString(bytesFrom) dataFromClient = dataFromClient.Substring(0, dataFromClient.Length) 'invoke into other thread txtOut.Invoke(Sub() txtOut.Text += dataFromClient txtOut.Text += vbNewLine End Sub) messageReceived = True Dim serverResponse As String = "Server response " + Convert.ToString(requestCount) Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(serverResponse) networkStream.Write(sendBytes, 0, sendBytes.Length) networkStream.Flush() Catch ex As Exception End End Try End While clientSocket.Close() serverSocket.Stop() msg("exit") Console.ReadLine() End While End Sub Sub msg(ByVal mesg As String) mesg.Trim() Console.WriteLine(" >> " + mesg) End Sub Public Sub WriteData(ByVal data As String, ByRef IP As String) Try txtOut.Text += data.PadRight(1) txtOut.Text += vbNewLine txtMsg.Clear() Console.WriteLine("Sending message """ & data & """ to " & IP) Dim client As TcpClient = New TcpClient() client.Connect(New IPEndPoint(IPAddress.Parse(IP), CInt(txtPort.Text))) Dim stream As NetworkStream = client.GetStream() Dim sendBytes As Byte() = Encoding.ASCII.GetBytes(data) stream.Write(sendBytes, 0, sendBytes.Length) Catch ex As Exception msg(ex.ToString) End Try End Sub Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click If Not (txtMsg.Text = vbNullString) AndAlso Not (txtIP.Text = vbNullString) Then WriteData(txtMsg.Text, txtIP.Text) End If End Sub Private Sub txtMsg_KeyDown(sender As Object, e As KeyEventArgs) Handles txtMsg.KeyDown If e.KeyCode = Keys.Enter Then If Not (txtMsg.Text = vbNullString) AndAlso Not (txtIP.Text = vbNullString) Then WriteData(txtMsg.Text, txtIP.Text) End If End If End Sub Private Sub BtnFind_Click(sender As Object, e As EventArgs) Handles btnFind.Click 'find all local addresses and put in combobox (button will be removed later) End Sub End Class
For PC names "as you suggested in your comments", I used this at work to get pc names i was on domain, try it: AFAIK it works on domains... Make sure you have a listbox on your form, or change listbox and populate in your combobox directly, play with that as you like :) Private Delegate Sub UpdateDelegate(ByVal s As String) Dim t As New Threading.Thread(AddressOf GetNetworkComputers) Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load t.IsBackground = True t.Start() End Sub Private Sub AddListBoxItem(ByVal s As String) ListBox1.Items.Add(s) End Sub Private Sub GetNetworkComputers() Try Dim alWorkGroups As New ArrayList Dim de As New DirectoryEntry de.Path = "WinNT:" For Each d As DirectoryEntry In de.Children If d.SchemaClassName = "Domain" Then alWorkGroups.Add(d.Name) d.Dispose() Next For Each workgroup As String In alWorkGroups de.Path = "WinNT://" & workgroup For Each d As DirectoryEntry In de.Children If d.SchemaClassName = "Computer" Then Dim del As UpdateDelegate = AddressOf AddListBoxItem Me.Invoke(del, d.Name) End If d.Dispose() Next Next Catch ex As Exception 'MsgBox(Ex.Message) End Try End Sub POC:
cancelling async task using progress bar causes targetinvocationexception error using vb.net
I am trying to load a datatable async so that the UI remains responsive. I've used the dt.RowChanged event to handle reporting progress back to the progress bar and label. But when the Stop button is clicked, it causes the following error: An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll. I'm not sure how to find my way around this issue. Any guidance is appreciated. The following is code from sample project using AdventureWorks DB Imports System.Threading Imports System.Threading.Tasks Public Class AsyncProgressCancel Public strConnectionString As String = "data source=010XXX01;initial catalog=AdventureWorks2012;integrated security=SSPI;" Private dt As DataTable Private ds As DataSet Dim dataset Dim RecordCount As Integer = 1000000 Dim Counter As Integer Dim myProgress As Progress(Of Integer) Private Delegate Sub AsyncDelegate(ByVal value As Integer) Private ProgressUpdater As New AsyncDelegate(AddressOf UpdateProgress) Private TargetCounter As Integer = 1000 Private cts As CancellationTokenSource Private Cancelled As Boolean Private Sub AsyncProgressCancel_Load(sender As Object, e As EventArgs) Handles MyBase.Load ProgressBar1.Visible = False lblProgress.Visible = False btnStop.Enabled = False End Sub Private Async Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click btnStart.Enabled = False btnStop.Enabled = True Cancelled = False ProgressBar1.Value = 0 ProgressBar1.Maximum = RecordCount ProgressBar1.Visible = True lblProgress.Visible = True DataGridView1.Enabled = False cts = New CancellationTokenSource() Try Dim completed As Boolean = Await LoadDataAsync(myProgress, cts.Token) Catch ex As OperationCanceledException lblProgress.Text = "Retrieve cancelled." DataGridView1.DataSource = Nothing DataGridView1.Enabled = True btnStop.Enabled = False btnStart.Enabled = True ProgressBar1.Visible = False Catch ex As Exception MsgBox(ex) End Try End Sub Private Sub UpdateProgress(ByVal value As Integer) If Cancelled = True Then cts.Cancel() Else If ProgressBar1.InvokeRequired Then ProgressBar1.Invoke(ProgressUpdater, New Object() {value}) ElseIf value > ProgressBar1.Maximum Then value = ProgressBar1.Maximum ProgressBar1.Value = value End If lblProgress.Text = Math.Round((value / RecordCount) * 100).ToString & "% complete" '"Step Number: " & myInt.ToString ProgressBar1.Value = value End If End Sub Private Async Function LoadDataAsync(ByVal myProgress As IProgress(Of Integer), token As CancellationToken) As Task(Of Boolean) Dim comSQL As SqlClient.SqlCommand Dim strSQL As String Dim da As SqlClient.SqlDataAdapter Dim dt As New DataTable Dim ReturnValue As Boolean Try DataGridView1.Enabled = Await Task(Of Boolean).Run(Function() Using conn As SqlClient.SqlConnection = New SqlClient.SqlConnection(strConnectionString) conn.Open() strSQL = "SELECT * FROM (SELECT TOP 1000000 PRODUCTION.PRODUCT.* FROM sales.SalesOrderDetail CROSS JOIN production.Product) A" comSQL = New SqlClient.SqlCommand(strSQL, conn) da = New SqlClient.SqlDataAdapter(comSQL) AddHandler dt.RowChanged, Sub(obj, e) If e.Action.Add Then Counter = obj.Rows.Count If Counter > RecordCount Then Counter = RecordCount Else Counter = Counter + 1 ' Math.Ceiling(0.1 * RecordCount) End If End If If token.IsCancellationRequested = True Then token.ThrowIfCancellationRequested() Else If Counter = TargetCounter Then UpdateProgress(Counter) TargetCounter = TargetCounter + 1000 End If End If End Sub If Counter > 0 Then myProgress.Report(Counter) End If da.Fill(dt) dataset = dt ReturnValue = True Return ReturnValue End Using End Function, token) Catch ex As Exception MsgBox(ex) End Try End Function Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click Try If Not cts Is Nothing Then cts.Cancel() End If Catch ex As Exception MsgBox(ex) End Try End Sub End Class
How do I close the tcp client (client.close) with a button?
I have a client server application. if the client has disconnected the server can detect it automatically and remove it from the connected clients list. I am going to focus on the server now. I would like to have a Stop Server button. To stop the Listener and Tcp Client Connections. I can easily stop the listener, but I am having a hard time trying to figure out how to stop the tcp client ( or issue a Client.Close ) [SERVER] Public Class Server Dim ClientList As New Hashtable Dim Listener As TcpListener Dim ListenerThread As System.Threading.Thread Private Sub ButtonStart_Click(sender As Object, e As EventArgs) Handles ButtonStart.Click ListenerThread = New System.Threading.Thread(AddressOf Listen) ListenerThread.IsBackground = True ListenerThread.Start(TextBoxPort.Text) ButtonStart.Enabled = False ButtonStop.Enabled = True ListBox1.Items.Add("[SERVER] Waiting For A Connection...") End Sub Sub ClientDisconnected(ByVal Client As ConnectedClient) ClientList.Remove(Client) 'remove the client from the hashtable ListBox2.Items.Remove(Client.Name) 'remove it from our listbox End Sub Sub Listen(ByVal Port As Integer) Try Listener = New TcpListener(IPAddress.Any, Port) Listener.Start() Do Dim Client As New ConnectedClient(Listener.AcceptTcpClient) AddHandler Client.ReceivedMessage, AddressOf ReceivedMessage AddHandler Client.ClientDisconnected, AddressOf ClientDisconnected Loop Until False Catch End Try End Sub Dim TotalItemCount As String Sub ReceivedMessage(ByVal Msg As String, ByVal Client As ConnectedClient) Dim Message() As String = Msg.Split("|") Select Case Message(0) Case "CHAT" 'if it's CHAT ListBox1.Items.Add(Client.Name & " Says: " & " " & Message(1)) Case "SAVETRAN" ListBox1.Items.Add("Transaction Number: " + Message(1) + vbCrLf + "Customer Number: " + Message(2)) Case "TRANDETAIL" ListBox1.Items.Add("Barcode: " + Message(1) + vbCrLf + "Quantity: " + Message(2) + vbCrLf + "Price Sold: " + Message(3)) ProgressBar1.Value += 1 Label1.Text = ProgressBar1.Value If Label1.Text = ProgressBar1.Maximum Then ProgressBar1.Value = 0 End If Case "ITEMCOUNT" ListBox1.Items.Add("SERVER IS EXPECTED TO RECEIVE " + Message(1) + " ITEMS.") TotalItemCount = Message(1) ProgressBar1.Maximum = TotalItemCount Case "LOGIN" 'A client has connected ClientList.Add(Client, Client.Name) ListBox2.Items.Add(Client.Name) End Select End Sub Private Sub ButtonStop_Click(sender As Object, e As EventArgs) Handles ButtonStop.Click Listener.Stop() ListBox1.Items.Add("Server Stopped") ButtonStop.Enabled = False ButtonStart.Enabled = True End Sub Private Sub Server_Load(sender As Object, e As EventArgs) Handles MyBase.Load CheckForIllegalCrossThreadCalls = False End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ListBox1.Items.Clear() End Sub End Class In the Server Application there is a class call ConnectedClient [Connected Client] Public Class ConnectedClient Public Cli As TcpClient Private UniqueID As String Public Property Name Get Return UniqueID End Get Set(ByVal Value) UniqueID = Value End Set End Property Public Sub New(Client As TcpClient) Dim r As New Random Dim x As String = String.Empty For i = 0 To 7 x &= Chr(r.Next(65, 89)) Next Me.Name = Client.Client.RemoteEndPoint.ToString().Remove(Client.Client.RemoteEndPoint.ToString().LastIndexOf(":")) & " - " & x Cli = Client Cli.GetStream.BeginRead(New Byte() {0}, 0, 0, AddressOf Reading, Nothing) End Sub Public Event ReceivedMessage(ByVal Message As String, ByVal Client As ConnectedClient) Public Event ClientDisconnected(ByVal Client As ConnectedClient) Sub Reading(ByVal AR As IAsyncResult) Try Dim Reader As New StreamReader(Cli.GetStream) Dim Msg As String = Reader.ReadLine() RaiseEvent ReceivedMessage(Msg, Me) Cli.GetStream.BeginRead(New Byte() {0}, 0, 0, AddressOf Reading, Nothing) Catch ex As Exception 'Try and read again Try Dim Reader As New StreamReader(Cli.GetStream) Dim Msg As String = Reader.ReadLine() RaiseEvent ReceivedMessage(Msg, Me) Cli.GetStream.BeginRead(New Byte() {0}, 0, 0, AddressOf Reading, Nothing) Catch RaiseEvent ClientDisconnected(Me) End Try End Try End Sub Sub SendData(ByVal Message As String) Dim Writer As New StreamWriter(Cli.GetStream) Writer.WriteLine(Message) Writer.Flush() End Sub End Class I was trying somehow to link to the connected client class and get the Client.Close, but I cannot figure it out.
Issue with socket chat not being able to send full messages
I am having a little issue with this socket chat, if I send little messages like "hello world" it works perfectly fine but if I try to send huge messages with about 10,000 characters it just crashes, i've been trying to fix this for the past 3 days with no luck, what should I be doing? Server source: Imports System.Text Imports System.Net Imports System.Net.Sockets Enum Command Login 'Log into the server Logout 'Logout of the server Message 'Send a text message to all the chat clients List 'Get a list of users in the chat room from the server Null 'No command End Enum Public Class Form1 'The ClientInfo structure holds the required information about every 'client connected to the server Private Structure ClientInfo Public socket As Socket 'Socket of the client Public strName As String 'Name by which the user logged into the chat room End Structure 'The collection of all clients logged into the room (an array of type ClientInfo) Private clientList As ArrayList 'The main socket on which the server listens to the clients Private serverSocket As Socket Private byteData As Byte() = New Byte(1023) {} Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Try clientList = New ArrayList() 'We are using TCP sockets serverSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) 'Assign the any IP of the machine and listen on port number 1000 Dim ipEndPoint As New IPEndPoint(IPAddress.Any, 2277) 'Bind and listen on the given address serverSocket.Bind(ipEndPoint) serverSocket.Listen(4) 'Accept the incoming clients serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing) Catch ex As Exception MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.[Error]) End Try End Sub Private Sub OnAccept(ar As IAsyncResult) Try Dim clientSocket As Socket = serverSocket.EndAccept(ar) 'Start listening for more clients serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing) 'Once the client connects then start receiving the commands from her clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), clientSocket) Catch ex As Exception MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.[Error]) End Try End Sub Private Sub OnReceive(ar As IAsyncResult) Try Dim clientSocket As Socket = DirectCast(ar.AsyncState, Socket) clientSocket.EndReceive(ar) 'Transform the array of bytes received from the user into an 'intelligent form of object Data Dim msgReceived As New Data(byteData) 'We will send this object in response the users request Dim msgToSend As New Data() Dim message As Byte() 'If the message is to login, logout, or simple text message 'then when send to others the type of the message remains the same msgToSend.cmdCommand = msgReceived.cmdCommand msgToSend.strName = msgReceived.strName Select Case msgReceived.cmdCommand Case Command.Login 'When a user logs in to the server then we add her to our 'list of clients Dim clientInfo As New ClientInfo() clientInfo.socket = clientSocket clientInfo.strName = msgReceived.strName clientList.Add(clientInfo) 'Set the text of the message that we will broadcast to all users msgToSend.strMessage = "<<<" & msgReceived.strName & " has joined the room>>>" Exit Select Case Command.Logout 'When a user wants to log out of the server then we search for her 'in the list of clients and close the corresponding connection Dim nIndex As Integer = 0 For Each client As ClientInfo In clientList If client.socket Is clientSocket Then clientList.RemoveAt(nIndex) Exit For End If nIndex += 1 Next clientSocket.Close() msgToSend.strMessage = "<<<" & msgReceived.strName & " has left the room>>>" Exit Select Case Command.Message 'Set the text of the message that we will broadcast to all users msgToSend.strMessage = msgReceived.strName & ": " & msgReceived.strMessage Exit Select Case Command.List 'Send the names of all users in the chat room to the new user msgToSend.cmdCommand = Command.List msgToSend.strName = Nothing msgToSend.strMessage = Nothing 'Collect the names of the user in the chat room For Each client As ClientInfo In clientList 'To keep things simple we use asterisk as the marker to separate the user names msgToSend.strMessage += client.strName & "*" Next message = msgToSend.ToByte() 'Send the name of the users in the chat room clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), clientSocket) Exit Select End Select If msgToSend.cmdCommand <> Command.List Then 'List messages are not broadcasted message = msgToSend.ToByte() For Each clientInfo As ClientInfo In clientList If clientInfo.socket IsNot clientSocket OrElse msgToSend.cmdCommand <> Command.Login Then 'Send the message to all users clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), clientInfo.socket) End If Next Debug.Print(msgToSend.strMessage) End If 'If the user is logging out then we need not listen from her If msgReceived.cmdCommand <> Command.Logout Then 'Start listening to the message send by the user clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), clientSocket) End If Catch ex As Exception MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.[Error]) End Try End Sub Public Sub OnSend(ar As IAsyncResult) Try Dim client As Socket = DirectCast(ar.AsyncState, Socket) client.EndSend(ar) Catch ex As Exception MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.[Error]) End Try End Sub End Class 'The data structure by which the server and the client interact with 'each other Class Data Public strName As String 'Name by which the client logs into the room Public strMessage As String 'Message text Public cmdCommand As Command 'Command type (login, logout, send message, etcetera) 'Default constructor Public Sub New() cmdCommand = Command.Null strMessage = Nothing strName = Nothing End Sub 'Converts the bytes into an object of type Data Public Sub New(data__1 As Byte()) 'The first four bytes are for the Command cmdCommand = CType(BitConverter.ToInt32(data__1, 0), Command) 'The next four store the length of the name Dim nameLen As Integer = BitConverter.ToInt32(data__1, 4) 'The next four store the length of the message Dim msgLen As Integer = BitConverter.ToInt32(data__1, 8) 'This check makes sure that strName has been passed in the array of bytes If nameLen > 0 Then Me.strName = Encoding.UTF8.GetString(data__1, 12, nameLen) Else Me.strName = Nothing End If 'This checks for a null message field If msgLen > 0 Then Me.strMessage = Encoding.UTF8.GetString(data__1, 12 + nameLen, msgLen) Else Me.strMessage = Nothing End If End Sub 'Converts the Data structure into an array of bytes Public Function ToByte() As Byte() Dim result As New List(Of Byte)() 'First four are for the Command result.AddRange(BitConverter.GetBytes(CInt(cmdCommand))) 'Add the length of the name If strName IsNot Nothing Then result.AddRange(BitConverter.GetBytes(strName.Length)) Else result.AddRange(BitConverter.GetBytes(0)) End If 'Length of the message If strMessage IsNot Nothing Then result.AddRange(BitConverter.GetBytes(strMessage.Length)) Else result.AddRange(BitConverter.GetBytes(0)) End If 'Add the name If strName IsNot Nothing Then result.AddRange(Encoding.UTF8.GetBytes(strName)) End If 'And, lastly we add the message text to our array of bytes If strMessage IsNot Nothing Then result.AddRange(Encoding.UTF8.GetBytes(strMessage)) End If Return result.ToArray() End Function End Class Client source: Enum Command Login '0 Log into the server Logout '1 Logout of the server Message '2 Send a text message to all the chat clients List '3 Get a list of users in the chat room from the server Null '4 No command End Enum Public Class frmMain Public clientSocket As System.Net.Sockets.Socket 'The main client socket Public strName As String 'Name by which the user logs into the room Private byteData As Byte() = New Byte(1023) {} Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load Call StartChat() End Sub Private Sub StartChat() clientSocket = New System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp) Dim ipAddress As System.Net.IPAddress = System.Net.IPAddress.Parse("127.0.0.1") Dim ipEndPoint As New System.Net.IPEndPoint(ipAddress, 2277) clientSocket.BeginConnect(ipEndPoint, New AsyncCallback(AddressOf OnLoginConnect), Nothing) End Sub Private Sub OnLoginConnect(ar As IAsyncResult) clientSocket.EndConnect(ar) 'We are connected so we login into the server Dim msgToSend As New Data() msgToSend.cmdCommand = Command.Login msgToSend.strName = txtUser.Text msgToSend.strMessage = Nothing Dim b As Byte() = msgToSend.ToByte() 'Send the message to the server clientSocket.BeginSend(b, 0, b.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnLoginSend), Nothing) End Sub Private Sub OnLoginSend(ar As IAsyncResult) clientSocket.EndSend(ar) strName = txtUser.Text Call LoggedIn() End Sub '*************** Private Sub LoggedIn() 'The user has logged into the system so we now request the server to send 'the names of all users who are in the chat room Dim msgToSend As New Data() msgToSend.cmdCommand = Command.List msgToSend.strName = strName msgToSend.strMessage = Nothing byteData = msgToSend.ToByte() clientSocket.BeginSend(byteData, 0, byteData.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnSend), Nothing) byteData = New Byte(1023) {} 'Start listening to the data asynchronously clientSocket.BeginReceive(byteData, 0, byteData.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnReceive), Nothing) End Sub 'Broadcast the message typed by the user to everyone Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click 'Fill the info for the message to be send Dim msgToSend As New Data() '.ToString("M/d/yyyy h:mm:ss tt") msgToSend.strName = "[" & Date.Now.ToString("h:mm:ss tt") & "] <" & strName & ">" msgToSend.strMessage = txtMessage.Text msgToSend.cmdCommand = Command.Message Dim byteData As Byte() = msgToSend.ToByte() 'Send it to the server clientSocket.BeginSend(byteData, 0, byteData.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnSend), Nothing) txtMessage.Text = Nothing End Sub Private Sub OnSend(ar As IAsyncResult) clientSocket.EndSend(ar) End Sub Private Sub OnReceive(ar As IAsyncResult) 'clientSocket.EndReceive(ar) Dim bytesReceived As Long = clientSocket.EndReceive(ar) If (bytesReceived > 0) Then Me.Invoke(New iThreadSafe(AddressOf iThreadSafeFinish), New Object() {byteData}) End If byteData = New Byte(1023) {} clientSocket.BeginReceive(byteData, 0, byteData.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnReceive), Nothing) End Sub Private Delegate Sub iThreadSafe(ByVal ibyteData As Byte()) Private Sub iThreadSafeFinish(ByVal ibyteData As Byte()) Dim msgReceived As New Data(ibyteData) 'Accordingly process the message received Debug.Print(msgReceived.cmdCommand) Select Case msgReceived.cmdCommand Case 0 'login lstChatters.Items.Add(msgReceived.strName) Exit Select Case 1 'log out lstChatters.Items.Remove(msgReceived.strName) Exit Select Case 2 'msg Exit Select Case 3 'List lstChatters.Items.AddRange(msgReceived.strMessage.Split("*"c)) lstChatters.Items.RemoveAt(lstChatters.Items.Count - 1) txtChatBox.Text += "<<<" & strName & " has joined the room>>>" & vbCr & vbLf Exit Select End Select If msgReceived.strMessage IsNot Nothing AndAlso msgReceived.cmdCommand <> Command.List Then txtChatBox.Text += msgReceived.strMessage & vbCr & vbLf End If End Sub Private Sub txtMessage_TextChanged(sender As Object, e As KeyEventArgs) Handles txtMessage.KeyDown If e.KeyCode = Keys.Enter Then btnSend_Click(sender, Nothing) End If End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click strName = txtUser.Text End Sub End Class 'The data structure by which the server and the client interact with 'each other Class Data Public strName As String 'Name by which the client logs into the room Public strMessage As String 'Message text Public cmdCommand As Command 'Command type (login, logout, send message, etcetera) 'Default constructor Public Sub New() cmdCommand = Command.Null strMessage = Nothing strName = Nothing End Sub 'Converts the bytes into an object of type Data Public Sub New(data__1 As Byte()) 'The first four bytes are for the Command cmdCommand = CType(BitConverter.ToInt32(data__1, 0), Command) 'The next four store the length of the name Dim nameLen As Integer = BitConverter.ToInt32(data__1, 4) 'The next four store the length of the message Dim msgLen As Integer = BitConverter.ToInt32(data__1, 8) 'This check makes sure that strName has been passed in the array of bytes If nameLen > 0 Then strName = System.Text.Encoding.UTF8.GetString(data__1, 12, nameLen) Else strName = Nothing End If 'This checks for a null message field If msgLen > 0 Then strMessage = System.Text.Encoding.UTF8.GetString(data__1, 12 + nameLen, msgLen) Else strMessage = Nothing End If End Sub 'Converts the Data structure into an array of bytes Public Function ToByte() As Byte() Dim result As New List(Of Byte)() 'First four are for the Command result.AddRange(BitConverter.GetBytes(CInt(cmdCommand))) 'Add the length of the name If strName IsNot Nothing Then result.AddRange(BitConverter.GetBytes(strName.Length)) Else result.AddRange(BitConverter.GetBytes(0)) End If 'Length of the message If strMessage IsNot Nothing Then result.AddRange(BitConverter.GetBytes(strMessage.Length)) Else result.AddRange(BitConverter.GetBytes(0)) End If 'Add the name If strName IsNot Nothing Then result.AddRange(System.Text.Encoding.UTF8.GetBytes(strName)) End If 'And, lastly we add the message text to our array of bytes If strMessage IsNot Nothing Then result.AddRange(System.Text.Encoding.UTF8.GetBytes(strMessage)) End If Return result.ToArray() End Function End Class
You are assuming that you will receive an entire message at a time. TCP does not guarantee to preserve the chunks that you wrote. Use the return value bytesReceived to determine how many bytes are actually in the buffer. Your code must be able to deal with the possibility of receiving all outstanding data one byte at a time.
vb.net server Socket dismiss previous client after new accepting new client
as i told in title , server doesnt listen previous client's packets. I just need server to read all packets coming from multiple clients. here s my code , thanks for your help serverSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Dim ipAddress As IPAddress = ipAddress.Parse("192.168.2.202") Dim IpEndPoint As IPEndPoint = New IPEndPoint(ipAddress, 15002) serverSocket.Bind(IpEndPoint) serverSocket.Listen(1500) serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing) Delegate Sub _OnAccept(ByVal ar As IAsyncResult) Private Sub OnAccept(ByVal ar As IAsyncResult) If InvokeRequired Then Invoke(New _OnAccept(AddressOf OnAccept), ar) Exit Sub End If clientSocket = serverSocket.EndAccept(ar) serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing) Try clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnRecieve), clientSocket) Catch ex As Exception End Try AddClient(clientSocket) End Sub Delegate Sub _AddClient(ByVal client As Socket) 'delege used to invoke AddCLient() Private Sub AddClient(ByVal client As Socket) If InvokeRequired Then Invoke(New _AddClient(AddressOf AddClient), client) Exit Sub End If Dim lvi As New ListViewItem(client.LocalEndPoint.ToString) lvi.Tag = client ListBox1.Items.Add(client.RemoteEndPoint.ToString & " Bağlandı") End Sub Delegate Sub _OnRecieve(ByVal ar As IAsyncResult) Private Sub OnRecieve(ByVal ar As IAsyncResult) If InvokeRequired Then Invoke(New _OnRecieve(AddressOf OnRecieve), ar) Exit Sub End If Dim client As Socket = ar.AsyncState Try client.EndReceive(ar) Catch ex As Exception End Try Dim bytesRec As Byte() = byteData Dim paket As String = System.Text.ASCIIEncoding.ASCII.GetString(bytesRec) Dim temizip As String temizip = Replace(paket, Chr(0), Chr(32)) temizip = temizip.Trim Dim msg As String = temizip Try Dim boyut As Integer boyut = msg(0) & msg(1) boyut = boyut - 10 Dim externalip As String externalip = msg.Remove(0, 2) externalip = externalip.Remove(boyut, (externalip.Length - boyut)) If clientlist.Contains(externalip) Then Else clientlist.Add(externalip) End If Catch ex As Exception End Try Try clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnRecieve), clientSocket) Catch ex As Exception End Try End Sub thanks people i solved this , i declare new clientsocket for each client and its solved. i just delete clientSocket variable from the header code , and i re-declared it on every thread.