Results 1 to 11 of 11

Thread: TCP server-multiclients problem

  1. #1

    Thread Starter
    New Member
    Join Date
    Apr 2009
    Posts
    8

    Question TCP server-multiclients problem

    From Atheist example and msdn examples i managed to do this small application : i can send and receive text from a client to a server and back.
    The problem is i got stuck on : making multiple client connexions , identify the clients and can send msg to a certain client . any help pls ?
    i use vb 2009
    The server source code :
    ---------------------------
    Code:
    Imports System.Net.Sockets
    Imports System.Net.Sockets
    Public Class Form1
        Dim server As TcpListener
        Dim port As Int32 = 13000
        '  Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1")
        Dim bytes(1024) As Byte
        Dim data As String = Nothing
        Dim stream As NetworkStream
        Dim client As TcpClient
        Dim listenThread As System.Threading.Thread
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Try
                server = New TcpListener(System.Net.IPAddress.Any, port)
                server.Start()
                Label1.Text = "server up"
                listenThread = New System.Threading.Thread(AddressOf doListen)
                listenThread.IsBackground = True
                listenThread.Start()
            Catch ex As Exception
                Label1.Text = "server down"
            End Try
    
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(TextBox1.Text)
            stream = client.GetStream()
            stream.Write(msg, 0, msg.Length)
            TextBox1.Text = ""
        End Sub
        Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
            server.Stop()
            client.Close()
        End Sub
        Private Delegate Sub StringDelegate(ByVal text As String)
        Private Sub SetConnectionLabelText(ByVal text As String)
            If Me.TextBox2.InvokeRequired Then
                Me.Invoke(New StringDelegate(AddressOf SetConnectionLabelText), text)
            Else
                Me.TextBox2.Text = text
            End If
        End Sub
        Private Sub doListen()
            client = server.AcceptTcpClient()
            Do
                data = Nothing
                stream = client.GetStream()
                Dim iq As Int32
                iq = stream.Read(bytes, 0, bytes.Length)
                data = System.Text.Encoding.ASCII.GetString(bytes, 0, iq)
                SetConnectionLabelText(data)
            Loop
        End Sub
    End Class
    -------------------------------------------------------------------
    the client source code:
    -----------------------
    Code:
    Imports System.Net.Sockets
    Public Class Form1
        Dim port As Integer = 13000
        Dim server As String
        Dim client As TcpClient
        Dim stream As NetworkStream
        Dim listenThread As System.Threading.Thread
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Try
                server = TextBox3.Text
                client = New TcpClient(server, port)
                stream = client.GetStream()
                Label1.Text = "connected"
                listenThread = New System.Threading.Thread(AddressOf doListen)
                listenThread.IsBackground = True
                listenThread.Start()
            Catch ex As Exception
                Label1.Text = "not connected"
            End Try
    
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(TextBox1.Text)
            stream.Write(data, 0, data.Length)
            TextBox1.Text = ""
        End Sub
        Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
            client.Close()
        End Sub
        Private Delegate Sub StringDelegate(ByVal text As String)
        Private Sub SetConnectionLabelText(ByVal text As String)
            If Me.TextBox2.InvokeRequired Then
                Me.Invoke(New StringDelegate(AddressOf SetConnectionLabelText), text)
            Else
                Me.TextBox2.Text = text
            End If
        End Sub
        Private Sub doListen()
            Do
                Dim data As [Byte]() = New [Byte](256) {}
                Dim responseData As [String] = [String].Empty
                Dim bytes As Int32 = stream.Read(data, 0, data.Length)
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)
                SetConnectionLabelText(responseData)
            Loop
        End Sub
    End Class
    Last edited by ancientrd; Apr 10th, 2009 at 09:07 AM.

  2. #2
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: TCP server-multiclients problem

    Could you please wrap your code in code tags? IT makes it alot easier to read. [CODE] code goes here [/CODE]
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  3. #3

    Thread Starter
    New Member
    Join Date
    Apr 2009
    Posts
    8

    Re: TCP server-multiclients problem

    done ... i edited it thx a lot for that info , indeed i guess is much better

  4. #4
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: TCP server-multiclients problem

    Your AcceptTcpClient call is outside of the loop in the doListen method, and so the server will only accept one connection and attempt to read from this connection endlessly. You need to repeatedly call AcceptTcpClient in order to always accept new connections. Furthermore, you really need to read from each connection on a separate thread, or else your chat application will be quite useless.
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  5. #5

    Thread Starter
    New Member
    Join Date
    Apr 2009
    Posts
    8

    Re: TCP server-multiclients problem

    like this ?
    Code:
    Private Sub doListen()
            Do
                client = server.AcceptTcpClient()
                data = Nothing
                stream = client.GetStream()
                Dim iq As Int32
                iq = stream.Read(bytes, 0, bytes.Length)
                data = System.Text.Encoding.ASCII.GetString(bytes, 0, iq)
                SetConnectionLabelText(data)
            Loop
        End Sub
    ok so if this solve the multiple clients how can i identify them now ?
    for example by ip (client(1).ip = .... or start working with the client class ?
    i saw u made that connected client but i wasn;t able to understand how it works ....
    can u help me create one connected property for my case ?
    i saw u used a streamwriter and a streamreader ...i used only the stream for both read and write...( that was in the msdn example) .... the thread system i took from you wich was great.... i still have a little problem with the write in the textbox too since in u;re example u have to define a write for each textbox or label ... how can i make that for general ?
    Code:
      Private Delegate Sub StringDelegate(ByVal text As String)
        Private Sub SetConnectionLabelText(ByVal text As String)
            If Me.TextBox2.InvokeRequired Then
                Me.Invoke(New StringDelegate(AddressOf SetConnectionLabelText), text)
            Else
                Me.TextBox2.Text = text
            End If
        End Sub
    and when i see the client that connects how can i see it;s properties ? the ip , mac or other identifyers? to can start use them becouse the next step is to add a ssl connect maybe a credential certificate .... not sure but something to encrypt and secure the data on the stream , not to be intercepted or to protect the server from other clients (make the user/pass)
    i saw in u;re example u did a string split by the "|" wich is good but how can i put the server read and compare the stream i get from the client with a database with the clients usernames and passwords ?

  6. #6

    Thread Starter
    New Member
    Join Date
    Apr 2009
    Posts
    8

    Re: TCP server-multiclients problem

    oh i saw 1 more thing ....
    when u write in a textbox i saw u use that invoke request... .now the problem is how can i make it read from the textbox .... like a chat channel ?
    to add the new string received to the existing one ?

  7. #7
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: TCP server-multiclients problem

    Quote Originally Posted by ancientrd View Post
    like this ?
    Code:
    Private Sub doListen()
            Do
                client = server.AcceptTcpClient()
                data = Nothing
                stream = client.GetStream()
                Dim iq As Int32
                iq = stream.Read(bytes, 0, bytes.Length)
                data = System.Text.Encoding.ASCII.GetString(bytes, 0, iq)
                SetConnectionLabelText(data)
            Loop
        End Sub
    Yes, but you still need to do more modifications. Currently the server will accept connections one by one, and as soon as a host has connected it'll read all available data from it, then accepting the next connection. etc. This is why you need to do some threading. You must be able to handle communication with multiple hosts at the same time.
    Quote Originally Posted by ancientrd View Post
    ok so if this solve the multiple clients how can i identify them now ?
    for example by ip (client(1).ip = .... or start working with the client class ?
    i saw u made that connected client but i wasn;t able to understand how it works ....
    You can choose any type of identification you see fit. A common and simple way is just to let each client identify himself with a username as soon as he connects, this username will be the clients unique identifier in this distributed system.
    It is a very good idea to create a class that contains all logic for a connected client, as I showed in my example.
    Quote Originally Posted by ancientrd View Post
    i saw u used a streamwriter and a streamreader ...i used only the stream for both read and write...( that was in the msdn example) ....
    The StreamReader/StreamWriter just provides a simpler interface to reading and writing to streams, but there's nothing you can do with a StreamReader/StreamWriter that you can not directly do with the Stream object. So you can choose to use them, or you can choose not to, any way is fine.
    There is also the BinaryReader/BinaryWriter, which can be good for some occasions.
    Quote Originally Posted by ancientrd View Post
    i still have a little problem with the write in the textbox too since in u;re example u have to define a write for each textbox or label ... how can i make that for general ?
    Code:
      Private Delegate Sub StringDelegate(ByVal text As String)
        Private Sub SetConnectionLabelText(ByVal text As String)
            If Me.TextBox2.InvokeRequired Then
                Me.Invoke(New StringDelegate(AddressOf SetConnectionLabelText), text)
            Else
                Me.TextBox2.Text = text
            End If
        End Sub
    I'm not entirely sure I understand what you mean, but are you talking about something like this?
    Code:
      Private Delegate Sub SetTextDelegate(ByVal ctrl As Control, ByVal text As String)
        Private Sub SetText(ByVal ctrl As Control, ByVal text As String)
            If ctrl.InvokeRequired Then
                ctrl.Invoke(New StringDelegate(AddressOf SetConnectionLabelText), ctrl, text)
            Else
                ctrl.Text = text
            End If
        End Sub
    Quote Originally Posted by ancientrd View Post
    and when i see the client that connects how can i see it;s properties ? the ip , mac or other identifyers? to can start use them becouse the next step is to add a ssl connect maybe a credential certificate .... not sure but something to encrypt and secure the data on the stream , not to be intercepted or to protect the server from other clients (make the user/pass)
    To find the IP of the host, you'll have to use the TcpClients Client property to get a reference to the underlying socket. The Socket class has a RemoteEndPoint property that'll give you the remote IP and port.
    Read up on the System.Net.Security.SslStream class if you want to use SSL, you can find some good information on it on MSDN.
    Quote Originally Posted by ancientrd View Post
    i saw in u;re example u did a string split by the "|" wich is good but how can i put the server read and compare the stream i get from the client with a database with the clients usernames and passwords ?
    My example isnt really optimal in that sense that it uses a delimiter character, but.. never mind that for now.
    I'm not sure I know what you're asking. If you get the username and the password (or MD5 hash of password!), you can simply perform an SQL query to see if they exist and match.
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  8. #8

    Thread Starter
    New Member
    Join Date
    Apr 2009
    Posts
    8

    Re: TCP server-multiclients problem

    1. i need the get text function , u added in your example how to write text in a control from other thread , ineed to know how you can get the text from a control in other thread
    control or variable

    thank you
    atm i am trying to make the client class
    i will post as soon as i finish to make it or broke it :d

  9. #9

    Thread Starter
    New Member
    Join Date
    Apr 2009
    Posts
    8

    Re: TCP server-multiclients problem

    i couldn;t make the client class ... (the server to work with a lot of clients) ... all i did was to can see if a client is allowed to connect or not ...
    Code:
    Private Sub doListen()
            client = server.AcceptTcpClient()
            data = Nothing
            stream = client.GetStream()
            Dim iq2 As Int32
            iq2 = stream.Read(bytes, 0, bytes.Length)
            data = System.Text.Encoding.ASCII.GetString(bytes, 0, iq2)
            Dim verclient() As String = Split(data, "~")
            If verclient(1) = "Client1" Then 'add query to ceck the client if is allowed to connect or not by pwd,user,ip
                SetText(TextBox2, data)
                Do
                    data = Nothing
                    stream = client.GetStream()
                    Dim iq As Int32
                    iq = stream.Read(bytes, 0, bytes.Length)
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, iq)
                    SetText(TextBox2, data)
                Loop
            Else
                client.Close()
            End If
           
        End Sub

  10. #10
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: TCP server-multiclients problem

    Quote Originally Posted by ancientrd View Post
    1. i need the get text function , u added in your example how to write text in a control from other thread , ineed to know how you can get the text from a control in other thread
    control or variable

    thank you
    atm i am trying to make the client class
    i will post as soon as i finish to make it or broke it :d
    I believe it is thread safe to get values from properties, but not setting them. So just do like you'd normally do if you want the text value from a TextBox.
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  11. #11

    Thread Starter
    New Member
    Join Date
    Apr 2009
    Posts
    8

    Re: TCP server-multiclients problem

    Atheist i am not sure if u got any msg but i will say here too :
    I managed to make the server,class and client
    I have 1 problem when i connect more clients ( from same comp i tested) the server send msg to only the 1st client that connected not to all. to receive i can receive from all clients
    i will post the code here :
    SERVER :
    Code:
    Imports System.Net.Sockets
    Imports System.Net.Security
    Public Class Form1
        Dim server As TcpListener
        Dim port As Int32 = 13000
        '  Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1")
        Dim stream As NetworkStream
        Dim listenThread As System.Threading.Thread
        Private clients As New List(Of connected)
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Try
                server = New TcpListener(System.Net.IPAddress.Any, port)
                server.Start()
                Label1.Text = "server up"
                listenThread = New System.Threading.Thread(AddressOf doListen)
                listenThread.IsBackground = True
                listenThread.Start()
            Catch ex As Exception
                Label1.Text = "server down"
            End Try
    
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            For Each cc As connected In clients
                cc.sendmsg(TextBox1)
            Next
        End Sub
        Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
            server.Stop()
        End Sub
        Private Sub doListen()
            Dim incomingClient As System.Net.Sockets.TcpClient
            Do
                incomingClient = server.AcceptTcpClient 'Accept the incoming connection. This is a blocking method so execution will halt here until someone tries to connect.   
                Dim connClient As New connected(incomingClient, Me, TextBox2) 'Create a new instance of ConnectedClient (check its constructor to see whats happening now).    
                clients.Add(connClient) 'Adds the connected client to the list of connected clients.   
            Loop
        End Sub
    End Class
    CLASS ;
    Code:
    Public Class connected
        Private mClient As System.Net.Sockets.TcpClient
        Private mParentForm As Form
        Private readThread As System.Threading.Thread
        Private mctrltxt As Control
        Private bytes(1024) As Byte
        Private data As String = Nothing
        Private stream As System.Net.Sockets.NetworkStream
        Public ip As String
        Sub New(ByVal client As System.Net.Sockets.TcpClient, ByVal parentForm As Form, ByVal ctrltxt As Control)
            mParentForm = parentForm
            mClient = client
            mctrltxt = ctrltxt
            readThread = New System.Threading.Thread(AddressOf doread)
            readThread.IsBackground = True
            readThread.Start()
        End Sub
        Private Delegate Sub StringDelegate(ByRef ctrl As Control, ByVal text As String)
        Private Sub SetText(ByRef ctrl As Control, ByVal text As String)
            If ctrl.InvokeRequired Then
                ctrl.BeginInvoke(New StringDelegate(AddressOf SetText), ctrl, text)
            Else
                ctrl.Text = text
            End If
        End Sub
        Private Function gettext(ByRef ctrl As Control)
            Return (ctrl.Text)
        End Function
        Private Sub doread()
            data = Nothing
            stream = mClient.GetStream()
            Dim iq2 As Int32
            iq2 = stream.Read(bytes, 0, bytes.Length)
            data = System.Text.Encoding.ASCII.GetString(bytes, 0, iq2)
            Dim verclient() As String = Split(data, "~")
            ip = verclient(0)
            Dim squad As String = Nothing
            squad = gettext(mctrltxt) + vbCrLf + data
            If verclient(1) <> "Client1" Then 'add query to ceck the client if is allowed to connect or not by pwd,user,ip
                SetText(mctrltxt, squad)
                Do
                    data = Nothing
                    stream = mClient.GetStream()
                    Dim iq As Int32
                    iq = stream.Read(bytes, 0, bytes.Length)
                    data = verclient(1) + " " + System.Text.Encoding.ASCII.GetString(bytes, 0, iq)
                    Dim squad2 As String = Nothing
                    squad2 = gettext(mctrltxt) + vbCrLf + data
                    SetText(mctrltxt, squad2)
                Loop
            Else
                MsgBox(data)
                mClient.Close()
            End If
        End Sub
        Public Sub sendmsg(ByVal ctrl As TextBox)
            Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(ctrl.Text)
            SyncLock mClient.GetStream
                stream = mClient.GetStream()
                stream.Write(msg, 0, msg.Length)
            End SyncLock
            ctrl.Text = ""
        End Sub
    End Class
    CLIENT :
    Code:
    Imports System.Net.Sockets
    Imports System.Net.Security
    Public Class Form1
        Dim port As Integer = 13000
        Dim server As String
        Dim client As TcpClient
        Dim stream As NetworkStream
        Dim listenThread As System.Threading.Thread
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Try
                server = TextBox3.Text
                client = New TcpClient(server, port)
                stream = client.GetStream()
                Label1.Text = "connected"
    
                Dim identification As String = client.Client.LocalEndPoint.ToString + "~" + TextBox4.Text + "~" + "Password1"
                Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(identification)
                stream.Write(data, 0, data.Length)
    
                TextBox1.Text = ""
                listenThread = New System.Threading.Thread(AddressOf doListen)
                listenThread.IsBackground = True
                listenThread.Start()
            Catch ex As Exception
                Label1.Text = "not connected"
            End Try
    
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(TextBox1.Text)
            stream.Write(data, 0, data.Length)
            TextBox1.Text = ""
        End Sub
        Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
            client.Close()
        End Sub
        Private Delegate Sub StringDelegate(ByVal ctrl As Control, ByVal text As String)
        Private Sub SetText(ByVal ctrl As Control, ByVal text As String)
            If ctrl.InvokeRequired Then
                ctrl.Invoke(New StringDelegate(AddressOf SetText), ctrl, text)
            Else
                ctrl.Text = text
            End If
        End Sub
        Private Function gettext(ByRef ctrl As Control)
            Return (ctrl.Text)
        End Function
        Private Sub doListen()
            Do
                Dim data As [Byte]() = New [Byte](1024) {}
                Dim responseData As [String] = [String].Empty
                Dim bytes As Int32 = stream.Read(data, 0, data.Length)
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)
                Dim squad As String = Nothing
                squad = gettext(TextBox2) + vbCrLf + responseData
                SetText(TextBox2, squad)
            Loop
        End Sub
    End Class


    I will need help with the following please :
    1. add ssl conection
    2. add encripted connection
    3. add certificate to the connection (client and server)
    4. when a client got disconected how can i see ? and event or something like that ... to ceck connected clients when they disconect so can trace them .... and remove them from the conencted list
    5. help for any improvment of the actual code

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width