Results 1 to 8 of 8

Thread: [2008] TCP Sockets

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Sep 2005
    Posts
    540

    [2008] TCP Sockets

    Yes, i know, another TCP Sockets thread. There are many around, i've been reading them!

    Athiest has been a big help here, reading up on his code, but my head just doesn't want to move from the VB6 mindset of winsock.

    Any way, i'm attempting to create a P2P chat program. It's both a client and a server chat application in one. Let me describe it a bit:

    There are a list of IP addresses (And ports, and alias names) that are kept, which is where all your messages are sent to (I know the IP Address and Port are the only bits needed).

    If someone connects to you, then they are added to your list, so that any message you send is delivered to them (And anyone else on your list). Also you are added to their list, so that any message they send is delivered to you (and everyone else on their list).

    This is the same if you connect to someone.

    So in both instances of the program, there's a client and a server.

    Now the bit that I'm having a hard time understanding is how to organize connected client sockets this way. Well just how these sockets work in general is still a bit confusing.

    I'm confused about how to setup clients on a server, that have some type of ID (which in VB6 i would have used the index in an array of winsocks for and then used an array to keep the index binded to an IP, port, alias and anything else i wanted).

    It also didn't matter who initiated the connection, because the listening winsock would just pass off the incoming connection (RequestID) to a newly created winsock for that client.

    I'm having a hard time trying to think how this would be designed to achieve the same result in VB.NET.

    Here is some of my code (That's been taken from Athiest any way):


    Code:
    Dim ListenThread As Threading.Thread
        Dim Listener As Net.Sockets.TcpListener
        Dim Clients As New List(Of ConnectedClient)
        Dim readBuffer(255) As Byte
        Private Client As Net.Sockets.TcpClient
    
        Private ListenPort As Long
    
    Private Sub Deactivate_Listening_Winsock()
    'I Hope this is how it's done
            Listener.Stop()
            ListenThread.Abort()
    
        End Sub
    
        Private Sub Initiate_Listening_Winsock()
    
            Listener = New Net.Sockets.TcpListener(Net.IPAddress.Any, ListenPort)
            Listener.Start()
            ListenThread = New Threading.Thread(AddressOf DoListen)
            ListenThread.IsBackground = True
            ListenThread.Start()
    
        End Sub
    
        Private Sub DoListen()
    
            Dim incomingClient As System.Net.Sockets.TcpClient
    
            Do
                incomingClient = Listener.AcceptTcpClient 'Accept the incoming connection. This is a blocking method so execution will halt here until someone tries to connect.
                Dim connClient As New ConnectedClient(incomingClient, Me) 'Create a new instance of ConnectedClient (check its constructor to see whats happening now).
                AddHandler connClient.dataReceived, AddressOf Me.messageReceived
                Clients.Add(connClient) 'Adds the connected client to the list of connected clients.
            Loop
    
        End Sub
        Private Sub DoRead(ByVal ar As IAsyncResult)
    
            Try
                'EndRead returns the number of bytes that were recieved, so we will need to check so that something was recieved
                Dim TotalBytes As Integer = Client.GetStream.EndRead(ar)
                If TotalBytes > 0 Then
                    Dim strMessage As String = System.Text.Encoding.ASCII.GetString(readBuffer, 0, TotalBytes)
    
                    Data_Reciever(strMessage, Client.GetStream) 'This was an attempt here to try to
    ' Findout where this message came from
    
                    'Calling this method again is important, it begins the read again.
                    Client.GetStream.BeginRead(readBuffer, 0, 255, AddressOf DoRead, Nothing)
                End If
            Catch e As Exception
                MessageBox.Show(e.Message)
            End Try
    
    
        End Sub
    
        Private Sub Data_Reciever(ByVal Data_ As String, ByVal Client_ As Net.Sockets.NetworkStream)
    'This is the sub that is going to be used to add new clients to the little database
    'Also going to be used to parse the message data, or remove clients when they disconnect.
    
            Dim RMsg() As String
            Dim RMsgType() As String
    
            RMsg = Split(Data_, "|:|")
            RMsgType = Split(RMsg(0), "|")
    
            If RMsgType(0) = "NEWCA" Then 'New Client Asking for connection
    
                Incomming_Connection(Data_)
    
            End If
    
        End Sub
    
    
        Public Sub removeClient(ByVal client As ConnectedClient)
    
            If Clients.Contains(client) Then
    
                Clients.Remove(client)
    
            End If
    
        End Sub
    
    
        Private Function Incomming_Connection(ByVal Data_ As String) As Boolean
    
            Dim RMsg() As String
            Dim RMsgType() As String
    
            RMsg = Split(Data_, "|:|")
            RMsgType = Split(RMsg(0), "|")
    
    
            If RMsgType(0) = "NEWCA" Then 'New Client Asking for connection
    
                If RMsgType(1) = "PASSW=1" Then
    
                    For I = 1 To UBound(RMsg)
    
                        RMsg(I) = Simple_Decrypt(RMsg(I)) 'Just decrypts it if it was encrypted.
    
                    Next
    
                End If
    
                Dim Ask_ As Integer
    
                Ask_ = MsgBox(RMsg(1) & " With Hostname " & RMsg(3) & " And Alias " & RMsg(2) & " Is trying to connect to you, do you wish to allow this?", MsgBoxStyle.YesNo, "Allow Connection?")
    
                If Ask_ = vbYes Then
    
                    If Len(Add_To_Clients(RMsg(1), RMsg(2), RMsg(3), RMsg(4), RMsg(5))) = 0 Then Incomming_Connection = True
    
                End If
    
            End If
    
    
        Public Function Add_To_Clients(ByVal IP_ As String, ByVal Alias_ As String, ByVal Hostname_ As String, ByVal RPort_ As String, Optional ByVal Client_Pass As String = "", Optional ByVal ConID As Long = 0) As String
    ' A DatagridView is being used as the database to store everything.
            If IP_ = "" Then
                Add_To_Clients = "No Specified IP"
                Exit Function
            End If
    
            If RPort_ = "" Then
                Add_To_Clients = "Invalid Remote Port"
                Exit Function
            End If
    
            If Hostname_ = "" Then
                Add_To_Clients = "Invalid Hostname"
                Exit Function
            End If
    
            Dim I_ As Integer
    
            I_ = 0
            Dim AlreadyExists As Integer
            AlreadyExists = -1
    
            For I_ = 0 To (ClientLst.Rows.Count - 1)
    
                If ClientLst.Rows(I_).Cells(0).Value = TxtIP.Text Then
                    AlreadyExists = I_
                End If
            Next
    
            'Check for duplicate server IDs
            If Trim(ClientLst.Rows(0).Cells(0).Value) = "" Then
    
                If AlreadyExists >= 0 Then
                    ClientLst.Rows(0).Cells(1).Value = IP_
                    ClientLst.Rows(0).Cells(2).Value = Alias_
                    ClientLst.Rows(0).Cells(3).Value = Hostname_
                    ClientLst.Rows(0).Cells(4).Value = RPort_
                    ClientLst.Rows(0).Cells(5).Value = Client_Uses_Pass(Client_Pass)
                    ClientLst.Rows(0).Cells(6).Value = Client_Pass
                    ClientLst.Rows(AlreadyExists).Dispose()
                Else
                    ClientLst.Rows.Add()
                    ClientLst.Rows(0).Cells(1).Value = IP_
                    ClientLst.Rows(0).Cells(2).Value = Alias_
                    ClientLst.Rows(0).Cells(3).Value = Hostname_
                    ClientLst.Rows(0).Cells(4).Value = RPort_
                    ClientLst.Rows(0).Cells(5).Value = Client_Uses_Pass(Client_Pass)
                    ClientLst.Rows(0).Cells(6).Value = Client_Pass
                End If
            Else
                If AlreadyExists <= -1 Then
                    ClientLst.Rows.Add()
                    For D_ = 0 To (ClientLst.Rows.Count - 1)
                        If Trim(ClientLst.Rows(D_).Cells(0).Value) = "" Then
                            ClientLst.Rows(D_).Cells(1).Value = IP_
                            ClientLst.Rows(D_).Cells(2).Value = Alias_
                            ClientLst.Rows(D_).Cells(3).Value = Hostname_
                            ClientLst.Rows(D_).Cells(4).Value = RPort_
                            ClientLst.Rows(D_).Cells(5).Value = Client_Uses_Pass(Client_Pass)
                            ClientLst.Rows(D_).Cells(6).Value = Client_Pass
                            Exit For
                        End If
                    Next D_
                Else
                    Add_To_Clients = "Client Already Exists"
                End If
    
    
            End If
    
            Add_To_Clients = ""
    
    
        End Function

    Hope that i included everything necessary.

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

    Re: [2008] TCP Sockets

    Im having a bit of trouble understanding the problem... is it the "general design" you cant figure out? You must keep a collection of connected hosts, and continously listen for incoming connections. This is basically what you've already got in that 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
    Fanatic Member
    Join Date
    Sep 2005
    Posts
    540

    Re: [2008] TCP Sockets

    Yes, it's the general design. I'm having trouble understanding how it can be coded in VB.NET.

    I know that the clients are stored in Dim Clients As New List(Of ConnectedClient), and to add more parameters (If needed), i just make it a dictionary. But this data needs to be displayed to the user, organized (To avoid, or allow duplicate IP addresses for example) and used to send data to clients. I can't make the data (Client As Net.Sockets.TcpClient) into something that i can manipulate or understand how to reference to it. And after that send information to a client based on their IP, or Client As Net.Sockets.TcpClient. I plan not to use a dictionary and use Cell 0 of the Datagridview (Which is hidden) for Client As Net.Sockets.TcpClient, and convert the datatypes as needed.

    I provided code to show what i have done so far.

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: [2008] TCP Sockets

    Actually, a dictionary doesn't sound like the right way to go for me. It sounds like you want a class. The class would hold the identifying characteristics of a server. I call it a server, because each program will be a server, listening for incoming calls, but each will also maintain a list of others, and when they call them, they will call as a client. That list can be maintained and built as new clients call in to the server portion of the program. The class will contain all the information necessary to create an endpoint such that it can expose a method that takes a message as an argument, establishes a connection, and sends the data.

    This may be a misunderstanding of what you are trying to accomplish. It seems to me that the whole design could be that a server is listening, when an incoming connection request is received, it accepts the connection, gets the remote endpoint from the connection, checks to see if it is on the list of known communicants (and adds it if it is not), then either just takes the message and drops the connection, or takes the message, returns a reply, then drops the connection. That last part might not be ideal, but most of my experience is with UDP. My thinking is that if each server is accepting a connection, receiving a message, then dropping the connection, the tasks are pretty simple, as you are not maintaining the state of a series of connections. Each client establishes a connection, sends a message, then exits. What I don't know is how much time is spent establishing a connection in TCP. If that time is insignificant, then this model would work well, because you don't have to know what the connection status is with any given client.

    Alternatively, when you accept a connection in the server side, you get a new socket. Check the list of classes to see if that particular client is on the list, and if it is not, create it, while passing the new socket to the class. If the client is already on the list, then just pass the new socket to the client. All communication over that socket is encompassed by the class. The class maintains the socket as long as the connection is maintained, but even after the socket is destroyed, the endpoint information for that client is maintained in the class such that a new communication can be established as needed.
    My usual boring signature: Nothing

  5. #5
    Frenzied Member
    Join Date
    Feb 2008
    Location
    Texas
    Posts
    1,288

    Re: [2008] TCP Sockets

    So when you create a New 'ConnectedClient' object, is that a new thread in itself?

    I've done client/server in java, and I had to create a class that extends the thread class for my listening function and each client.

    Just wanted to see.

    Thanks,

    Justin Fox
    You down with OOP? Yeah you know me!
    MCAD and MCMICKEYMOUSE (vb.net)

    ----

    If it even kinda helps... rate it : )

    Edit a Multi-page .tif file and save.

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

    Re: [2008] TCP Sockets

    Quote Originally Posted by MonkOFox
    So when you create a New 'ConnectedClient' object, is that a new thread in itself?

    I've done client/server in java, and I had to create a class that extends the thread class for my listening function and each client.

    Just wanted to see.

    Thanks,

    Justin Fox
    Yes each ConnectedClient class reads from its networkstream on a separate thread.
    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)

  7. #7
    Frenzied Member
    Join Date
    Feb 2008
    Location
    Texas
    Posts
    1,288

    Re: [2008] TCP Sockets

    Sweet! That makes things a lot easier!

    Thanks,

    Justin Fox
    You down with OOP? Yeah you know me!
    MCAD and MCMICKEYMOUSE (vb.net)

    ----

    If it even kinda helps... rate it : )

    Edit a Multi-page .tif file and save.

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Sep 2005
    Posts
    540

    Re: [2008] TCP Sockets

    Quote Originally Posted by Shaggy Hiker
    Actually, a dictionary doesn't sound like the right way to go for me. It sounds like you want a class. The class would hold the identifying characteristics of a server. I call it a server, because each program will be a server, listening for incoming calls, but each will also maintain a list of others, and when they call them, they will call as a client. That list can be maintained and built as new clients call in to the server portion of the program. The class will contain all the information necessary to create an endpoint such that it can expose a method that takes a message as an argument, establishes a connection, and sends the data.

    This may be a misunderstanding of what you are trying to accomplish. It seems to me that the whole design could be that a server is listening, when an incoming connection request is received, it accepts the connection, gets the remote endpoint from the connection, checks to see if it is on the list of known communicants (and adds it if it is not), then either just takes the message and drops the connection, or takes the message, returns a reply, then drops the connection. That last part might not be ideal, but most of my experience is with UDP. My thinking is that if each server is accepting a connection, receiving a message, then dropping the connection, the tasks are pretty simple, as you are not maintaining the state of a series of connections. Each client establishes a connection, sends a message, then exits. What I don't know is how much time is spent establishing a connection in TCP. If that time is insignificant, then this model would work well, because you don't have to know what the connection status is with any given client.

    Alternatively, when you accept a connection in the server side, you get a new socket. Check the list of classes to see if that particular client is on the list, and if it is not, create it, while passing the new socket to the class. If the client is already on the list, then just pass the new socket to the client. All communication over that socket is encompassed by the class. The class maintains the socket as long as the connection is maintained, but even after the socket is destroyed, the endpoint information for that client is maintained in the class such that a new communication can be established as needed.
    Yes, this is what i mean. I was thinking about designing the code that's connectionless, but still on the TCP protocol. This however is not what TCP was designed for. I was going to make a connection to an IP address on a specific port, send the message and then disconnect. But for some reason, this just doesn't feel right. This is why i was going to make it a normal TCP connection, where it connects once, and uses those connections to send the data by. This could also be useful to find out if a client is still online without pinging them in some sort of fashion. If i use the connectionless way, then extra code will be needed on the server to verify that it's a client on their "contact list", It will also be harder to keep 2 clients synchronized, especially if one gets improperly disconnected, also error checking would have to be done to make sure the message got through properly, but it is certainly possible to do this.

    Which way would be the better way to go?

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