0

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.

Calixt0
  • 1
  • 1
  • 5
  • **First of all**, you must always call `EndRead`, `EndWrite` or anything beginning with `End` once you've called `Begin...`, or else you'll end up with memory leaks. Alternatively skip calling `Begin...` and just call `Write`/`Read`. **Secondly**, we don't really see what all your variables do or are declared as, so it'll be harder troubleshooting the problem. – Visual Vincent Mar 05 '16 at 16:17
  • **Thirdly (AND THE MOST IMPORTANT)**, if this is TCP, use [Length-prefixed packets](http://stackoverflow.com/a/35240061/3740093). **Fourthly**, yet if this is TCP, consider something like a `List(Of TcpClient)` or `List(Of Socket)`. – Visual Vincent Mar 05 '16 at 16:18

2 Answers2

0

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)

Calixt0
  • 1
  • 1
  • 5
  • The sockets have a protocol too, not just the TcpClient. _AHEM AHEM_: `New Socket(AddressFamily.InterNetwork, SocketType.Stream,` _**ProtocolType.Tcp**_). So you are using TCP. --- And since you're using TCP with NetworkStreams you really should implement length-prefixed packets, or else your messages will at some point be lumped together, or split into many parts. – Visual Vincent Mar 06 '16 at 10:23
  • And the `EndRead`/`End...` methods are supposed to be **after** `Begin...`. But you're really just better of calling `Write`, `Accept` or so directly - it will not be asynchronous, but there's really no notable delay. I have a file transfer application which uses the normal methods. The send speed to my friends computer was around 130 KB/s (peer-to-peer is sometimes slow as your internet connections might differ). If I'd switch to `Begin...`/`End...` there would probably not be any difference. The `End...` methods themselves actually do block for a short while, just like the normal methods. – Visual Vincent Mar 06 '16 at 10:33
  • (Sorry for the comment spam) Also, using `Begin...` and `End...` doesn't just go for sockets, it goes for everything where you use `Begin...`. Besides, the upside with length-prefixing is that you'll always know how much data has been sent to you in the packet (I see you currently use a buffer of 1024 bytes or 1 KB. This can too cause split or lumped together messages). --- **Final note:** TCP does not support multiple connections. You require one socket for each connection. – Visual Vincent Mar 06 '16 at 10:37
  • So here, i checked the **EndRead** as integer (i think that is the length of the message received). I received 25bytes (i also think that it is a byte :P) from my computer, and 27 from the virtual machine. I also checked the **Data Available** from the network stream, and it is always false no matter what, from both clients. I would still use the **EndRead** just in case and also for better formatting. The only problem that i see here is a deadlock. The 1st try receives both of the message from them, but on the next tries it only receive one and one only. – Calixt0 Mar 07 '16 at 06:09
  • Can you show me how can i avoid this deadlock in this particular scenario. Thank you very much again Visual Vincent ^_^. And what do you mean by "TCP does not support multiple connections. You require one socket for each connection? And also, it's okay to spam as long as the comments make sense ^_^ – Calixt0 Mar 07 '16 at 06:10
  • What I mean is that for each new connection to the server, you require a completely new socket. The TCP protocol doesn't support having one socket handling all connections. – Visual Vincent Mar 07 '16 at 13:11
  • So here again, i asked Brother Google if there is/are alternatives for TCP. He told me about UDP, it says that it is connectionless? Some of the forums (especially here) prefers UDP rather than TCP (some says TCP are better for file transfers). Should i switch to UDP or stick to TCP and find a workaround for multiple connections? – Calixt0 Mar 07 '16 at 17:27
  • Also, i dont get any errors or catching any exceptions about multiple client connections. Maybe i just dont see the error yet because i just have 2 clients connected. I'll try on 5 clients, maybe Saturday on my friend's Internet Cafe, and see if it catches the error, or maybe lags or something like that. Anyways, i'll try your suggestion to have a fresh socket (or maybe a new instance) after a new connection. Thank you for your help ^_^ sorry for bothering you... – Calixt0 Mar 07 '16 at 17:38
  • Oh you're not bothering :). Though UDP implements packet handling, I do not recommend it. UDP is mostly used for real-time applications such as games due to that it's usually faster than TCP - but it's not as reliable. UDP uses as much internet speed as possible, while TCP adapts to _try_ to not make your internet unstable. – Visual Vincent Mar 07 '16 at 18:26
  • This _does not_ however make TCP slow. TCP has a fair advantage over UDP - which is that TCP will _ensure_ that your data is sent and received properly, and also that it is received in _the order you sent it_. --- As for your CyberCafe program (which I suppose is a normal text-chat program) it doesn't really matter that TCP might be slower in some cases, _infact you will don't even notice it_. Sending simple text messages takes so small space, and is not sent every millisecond, that there's no trouble with delays or something like that. TCP has infact even been used by some games. – Visual Vincent Mar 07 '16 at 18:34
  • Using raw sockets is also a bit tricker. I recommend you to use TCP as it's very reliable and still very fast (unlike HTTP). --- Switch from sockets to TcpClient/TcpListener instead (it's way simpler), and use my answer in this question (http://stackoverflow.com/a/35240061/3740093) to implement packet handling through TCP. The packet handling will ensure that you don't get split up messages or messages that are lumped together. **As for the problem with multiple clients**, on the server create a `List(Of ExtendedTcpClient)` and add a new client to it every time someone connects to the server. – Visual Vincent Mar 07 '16 at 18:41
  • _(Hope you cope with reading my long comments)_ I use the same code (that I linked you to) for my TCP file transfer application. The send and receive speed between two computers at different locations is about about 80-120 KB/s. 120 KB is roughly 122880 characters per second, meaning you can send roughly 24580 words in one second (which is a **REALLY LARGE** essay ;) ). And I don't think your users will send an essay to each other every second. (: – Visual Vincent Mar 07 '16 at 18:51
  • (Great, now I'm spamming again) Please tell me if you need more help, I'm glad to be able to assist you. You can keep writing here, but I also have an e-mail which you can find in the "Support" section of my website (which can be found in my StackOverflow profile). ;) – Visual Vincent Mar 07 '16 at 18:54
0

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 :(

Community
  • 1
  • 1
Calixt0
  • 1
  • 1
  • 5
  • `EndRead` disposes threads and release memory. It is supposed to be called after `BeginRead`. I still recommend only calling `Read()`. And as said, you need multiple sockets for multiple connections. – Visual Vincent Mar 07 '16 at 13:06