Page 1 of 7 1234 ... LastLast
Results 1 to 40 of 273

Thread: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

  1. #1

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Someone asked recently if there were any existing components out there that would allow them to send text messages between a client and server using the TcpClient without locking up the UI and without their having to learn the intricacies of the TcpClient class. I don't know for sure but I'm guessing that the answer is "no", so I decided to create one.

    I've attached the project below, so you're welcome to use the source code as a learning tool or as a basis for your own code. If you do use the code, in part or in full, I don't require any recognition but I do require that you don't claim the code as your own creation. You can also just compile the library and slot it straight into your own project as a black box if you don't care about how it works.

    FEATURES:

    * Uses TcpListener and TcpClient to provide communication between server and multiple clients.
    * All connection, read and write operations performed asynchronously to avoid UI issues.
    * Simple interface for send text messages, i.e. just call Send and specify the message.
    * Server can send a message to a single client or all clients with a single method call in each case.
    * Uses event model to provide notifications regarding connections and messages.
    * Events can be raised in background threads or the UI thread simply by setting a property.
    * Solution includes WinForms projects for testing server and multiple clients.
    * Code demonstrates various techniques including inheritance, custom events, asynchronous programming and LINQ.

    USAGE:

    To test out the features you can simply open the project in VS and run it. The test projects for the client and server will both run and present you with two windows: one for the server and one for the client. Click the Connect button in the client window to connect to the server.

    Both server and client provide a log window to notify you of all connection and communication events. To send a message from the client to the server simply type into the TextBox at the bottom of the window and click the Send button. The same goes for the server sending a message to the client.

    The client test rig is an MDI application. Each child window represents a client and multiple clients can connect to the server simultaneously. Use the File menu to create a new client.

    When multiple clients are connected to the server you can select the client to send a message to using the ComboBox at the bottom of the server window. Clicking the Send All button will send the message to all connected clients.

    To use the Wunnell.Net.MessageClientServer.dll assembly in your own applications you'll first want to open the References page of your project properties, add a reference to the assembly and then import the Wunnell.Net namespace. You can add instances of the client and server classes in code like so:
    vb.net Code:
    1. Private WithEvents client As New MessageClient(hostName, remotePort)
    2. Private WithEvents server As New MessageServer(port)
    In the case of the client, the host name and remote port are the name or address and port number of the server. In the case of the server, the port is the port number to listen on. The server's port and the client's remote port must be the same.

    Note that by using WithEvents in the declarations you can use the drop-down lists at the top of the code window to generate event handlers with Handles clauses. You can use AddHandler if you prefer.

    Note that you don't necessarily have to handle any events if you don't want to, but if you want to provide feedback on what's happening you will obviously need to. Note also that, if you using the library in a WinForms app and you want events raised in the UI thread then you should assign your form to the SynchronisingObject property of the client or server. All operations will still be performed on background threads. It's only notifications that will occur on the UI thread.
    vb.net Code:
    1. Me.client.SynchronisingObject = Me
    To be able to communicate you will first have to call the client's Connect method. You can then call Send to send a message, e.g.
    vb.net Code:
    1. Me.client.Connect()
    2. Me.client.Send("Hello Server")
    To send a message from the server to a specific client you simply call Send and specify the client host details and the message. To send a message to all clients you call Send and just specify the message, e.g.
    vb.net Code:
    1. For Each host In Me.server.Hosts
    2.     Me.server.Send(host, "Hello " & host.ToString())
    3. Next
    4.  
    5. Me.server.Send("Hello All Clients")
    To disconnect you simply dispose the client or the server.

    KNOWN ISSUES:

    1. If you try to close a client window in the test application without having connected the window will not close. [Fixed in v1.0.0.1 on 2009-10-11. See post #2]
    2. HostInfo.Equals throws an exception if passed a value that is not type HostInfo. [Fixed in v1.0.1.0 on 2009-11-10. See post #6]
    3. IOException may be thrown when closing client child window. [Fixed in v1.1.0.1 on 2010-10-10]

    The whole solution has been tested but more rigorous testing is still required. I'll be looking to improve the feature set and address any issues that arise so please feel free to post comments, suggestions and questions here, although I can't guarantee if and when I'll get to them.

    UPDATES:

    25 Oct 2009: v1.1.0.0 posted. See post #22 for details of changes.
    10 Oct 2010: v1.1.0.1 posted. Fixes occasional crash when closing client child window.
    Attached Files Attached Files
    Last edited by jmcilhinney; Oct 9th, 2010 at 09:53 PM. Reason: Uploaded version 1.1.0.1

  2. #2

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: Fixed Known Issue 1

    The problem was that the 'stream' field of the MessageClient class was not set until the connection was established and Close was being called on that field in the Dispose method regardless. The exception was preventing the form closing. To resolve the issue the Dispose method was changed from this:
    vb.net Code:
    1. Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    2.     If Not Me.isDisposed Then
    3.         If disposing Then
    4.             'Close the connection and the underlying stream.
    5.             Me.stream.Close()
    6.             Me.client.Close()
    7.         End If
    8.  
    9.         Me.stream = Nothing
    10.     End If
    11.  
    12.     MyBase.Dispose(disposing)
    13.     Me.isDisposed = True
    14. End Sub
    to this:
    vb.net Code:
    1. Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    2.     If Not Me.isDisposed Then
    3.         If disposing Then
    4.             'Close the connection and the underlying stream.
    5.             If Me.stream IsNot Nothing Then
    6.                 Me.stream.Close()
    7.             End If
    8.  
    9.             Me.client.Close()
    10.         End If
    11.  
    12.         Me.stream = Nothing
    13.     End If
    14.  
    15.     MyBase.Dispose(disposing)
    16.     Me.isDisposed = True
    17. End Sub

  3. #3

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by jmcilhinney View Post
    To be able to communicate you will first have to call the client's Connect method. You can then call Send to send a message, e.g.
    vb.net Code:
    1. Me.client.Connect()
    2. Me.client.Send("Hello Server")
    I just wanted to point out that you can't really use code quite like that. When you call Connect the connection request is made asynchronously and the ConnectionAccepted event will be raised when that operation completes. I haven't actually tested the scenario but I imagine that, if you call Connect and then you call Send before receiving the ConnectionAccepted event, an exception will be thrown.

  4. #4
    Addicted Member
    Join Date
    Aug 2009
    Posts
    175

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    I'm afraid I've run into an immediate problem. As soon as I start up the program, the server starts running, but as soon as I hit 'Connect' on the client, I get the error message 'When casting from a number, the value must be less than infinity' in this section of code....

    Code:
        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            With DirectCast(obj, HostInfo)
                Return Me.HostName.Equals(.HostName, StringComparison.CurrentCultureIgnoreCase) AndAlso _
                       Me.Port = .Port
            End With
        End Function
    It's on the line 'With DirectCast.......'

    One other thing, would it be possible to seperate this into two seperate programs, one for the server and one for the client? I realise it's much easier to test like this but it'll be necessary to split them eventually. Or give me a rough idea which files I'll need for each seperate program?

  5. #5

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by Farflamex View Post
    I'm afraid I've run into an immediate problem. As soon as I start up the program, the server starts running, but as soon as I hit 'Connect' on the client, I get the error message 'When casting from a number, the value must be less than infinity' in this section of code....

    Code:
        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            With DirectCast(obj, HostInfo)
                Return Me.HostName.Equals(.HostName, StringComparison.CurrentCultureIgnoreCase) AndAlso _
                       Me.Port = .Port
            End With
        End Function
    It's on the line 'With DirectCast.......'
    I'd have to know more about exactly how you're using it to know exactly what the problem is. Are you running my test apps or are you trying to use the library in your own project? I'm not sure how you could come up with that error if you're using my test apps as I've checked where HostInfo.Equals method is called in my code and I can't see how that error could occur. Maybe I've missed something though so, if you are using my test apps, please give me a step by step run down of EXACTLY what you did so I can do the same thing and see if I get the same result.

    If you're calling that method then I can only assume that you're using it incorrectly. The HostInfo.Equals method overrides the Object.Equals method so it will accept any object, but it's supposed to compare HostInfo objects. It sounds like you're passing it a value that isn't a HostInfo object. If it is your own code, what is the type and value of 'obj' when that error occurs and can you show me the code that calls that method.

    That said, I guess that that method should really return False if the value passed in isn't a HostInfo object. That's not going to make your code work correctly if you're passing in an object of the wrong type but it will stop it crashing. I'll make that change and post a new version of the solution.
    Quote Originally Posted by Farflamex View Post
    One other thing, would it be possible to seperate this into two seperate programs, one for the server and one for the client? I realise it's much easier to test like this but it'll be necessary to split them eventually. Or give me a rough idea which files I'll need for each seperate program?
    There's no need or point to breaking it up into two assemblies. The MessageClient and MessageServer classes both inherit the MessageClientServerBase class so you will need a common assembly somewhere regardless. The idea is that, if you have two separate applications, i.e. a client and a server, then they both reference the Wunnell.Net.MessageClientServer.dll assembly. The server application would simply ignore the MessageClient class and only instantiate the MessageServer class, while the client application would do the opposite. If you have one application that uses a TextBox and another that uses a ComboBox, is it a problem that both those apps have to reference System.Windows.Forms.dll because both those controls are defined in that same assembly?

  6. #6

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by Farflamex View Post
    I'm afraid I've run into an immediate problem. As soon as I start up the program, the server starts running, but as soon as I hit 'Connect' on the client, I get the error message 'When casting from a number, the value must be less than infinity' in this section of code....

    Code:
        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            With DirectCast(obj, HostInfo)
                Return Me.HostName.Equals(.HostName, StringComparison.CurrentCultureIgnoreCase) AndAlso _
                       Me.Port = .Port
            End With
        End Function
    It's on the line 'With DirectCast.......'
    It seems I may have done you a disservice. I changed my code a bit and when I ran it I saw that the HostInfo.Equals method was being called by the system when the items were added to the ComboBox and the value they were compared to was DBNull, which would have failed the cast. Maybe those exceptions were being swallowed on my system but not on yours. Anyway, I've changed that method from this:
    vb.net Code:
    1. Public Overrides Function Equals(ByVal obj As Object) As Boolean
    2.     With DirectCast(obj, HostInfo)
    3.         Return Me.HostName.Equals(.HostName, StringComparison.CurrentCultureIgnoreCase) AndAlso _
    4.                Me.Port = .Port
    5.     End With
    6. End Function
    to this:
    vb.net Code:
    1. Public Overloads Function Equals(ByVal host As HostInfo) As Boolean
    2.     Return Me.HostName.Equals(host.HostName, StringComparison.CurrentCultureIgnoreCase) AndAlso _
    3.            Me.Port = host.Port
    4. End Function
    5.  
    6. Public Overloads Overrides Function Equals(ByVal obj As Object) As Boolean
    7.     Return TypeOf obj Is HostInfo AndAlso _
    8.            Me.Equals(DirectCast(obj, HostInfo))
    9. End Function
    Download version 1.0.1.0 once I've uploaded it and see if that solves your problem.

    I also found an InvalidOperationException being thrown sometimes when the server is closed while clients are connected that wasn't being caught, so I've addressed that too.

  7. #7
    Addicted Member
    Join Date
    Aug 2009
    Posts
    175

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Thanks, with my level of incompetence, I'm sure we can sort these problems out

    Hopefully you've sorted that one out, but all I did was load up the program and run it. I didn't make any changes at all. The server starts automatically and I just clicked 'Connect' on the client, and the error appeared. Hopefully the update will resolve that.

    As for having two seperate assemblies, this is probably due to my incompetence with VB, but what I was looking to do was to have one program for my server and one for my clients. But I assume what you're saying is, they would both be identical anyway, I just need to set one up as a server, which runs as it does now but doesn't start any clients, and one which only starts the client. I'll tinker around with it once you've uploaded the new code and see if I can sort that without any problems.

  8. #8

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by Farflamex View Post
    Thanks, with my level of incompetence, I'm sure we can sort these problems out

    Hopefully you've sorted that one out, but all I did was load up the program and run it. I didn't make any changes at all. The server starts automatically and I just clicked 'Connect' on the client, and the error appeared. Hopefully the update will resolve that.
    That makes sense. From what I saw after I changed the code, that's where I would expect the problem to be because that's when the HostInfo gets added to the ComboBox. For some reason that exception was crashing the app on your system but it was getting swallowed on mine and the app continued. I don't know whether that's because of my VS settings or it's a Win7 thing but I'll be looking more closely at the Output window for first-chance exceptions in future. I think the change I made should fix that issue.
    Quote Originally Posted by Farflamex View Post
    As for having two seperate assemblies, this is probably due to my incompetence with VB, but what I was looking to do was to have one program for my server and one for my clients. But I assume what you're saying is, they would both be identical anyway, I just need to set one up as a server, which runs as it does now but doesn't start any clients, and one which only starts the client. I'll tinker around with it once you've uploaded the new code and see if I can sort that without any problems.
    I think you misunderstand how this is supposed to work. You say that you want two separate applications for the client and the server. That's exactly what you already have. That solution contains three separate projects. One is the client/server library, one is the client application and one is the server application.

    When you run the solution and the two windows pop up, they are two completely separate applications, and each of them references the third. That's how it would work for you. You would most likely create a solution with two projects: one for the client and one for the server. To each of those projects you would add a reference to the Wunnell.Net.MessageClientServer.dll assembly that you created by building my solution, or at least the Wunnell.Net.MessageClientServer project in my solution.

  9. #9
    Addicted Member
    Join Date
    Aug 2009
    Posts
    175

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Ok, just to let you know it now works fine and is sending and receiving messages with no problems between server and client.

    Now I just have to work out how where I add my own code for my server and client. The whole MDI thing confuses me. Don't worry, it's not your job to teach me VB, I'll delve into it and see how far I get

  10. #10

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by Farflamex View Post
    Ok, just to let you know it now works fine and is sending and receiving messages with no problems between server and client.

    Now I just have to work out how where I add my own code for my server and client. The whole MDI thing confuses me. Don't worry, it's not your job to teach me VB, I'll delve into it and see how far I get
    In your server app you create a MessageServer object and handle at least its ConnectionAccepted and MessageReceived events. Additionally, call its Send method to send messages to the client(s).

    For the client, create a MessageClient instance and handle at least its ConnectionAccepted event and, if you want to receive messages from the server, its MessageReceived event too. Call its Connect method, wait for the ConnectionAccepted event and then you can start calling Send.

    That's pretty much it.

  11. #11
    Addicted Member
    Join Date
    Aug 2009
    Posts
    175

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    No probs. I understand the basic calls. What I don't understand at the moment is how the program is laid out. I'd like, for example, to just have the single client window, instead of the window within the window which opens multiple clients.

    The problem stems from the fact that I've 'upgraded' to VB.net from VB6 and even further back from very old types of BASIC. Whilst I can understand the beauty and power of modern languages, it's a struggle to change my mindset to this new style of programming. So whilst I understand the whole sockets issue, I don't understand all the OOP that it's wrapped up in. Infact when I think about it, there's nothing about the sockets issue that I don't understand - but I have no idea how to translate that into VB.net. All that stuff with delegates and synclocks put my brain into a synclock

    Anyhoo, I'm learning as I go along. I'll try to break this down into something I understand and then build onto it.

  12. #12
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Nice to see that it wasnt just me that had to ignore the ObjectDisposed exception when calling EndAcceptTcpClient. Same for the IOException when calling EndRead.
    I assumed there was a better way to handle this that I just couldnt figure out but seeing you do the same thing makes me feel a bit better about it
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  13. #13

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by chris128 View Post
    Nice to see that it wasnt just me that had to ignore the ObjectDisposed exception when calling EndAcceptTcpClient. Same for the IOException when calling EndRead.
    I assumed there was a better way to handle this that I just couldnt figure out but seeing you do the same thing makes me feel a bit better about it
    Yeah, I was hunting and hunting for some property that I could test before calling EndWhatever but I couldn't find anything, so I can only assume that catching the exceptions is the only way to go.

  14. #14
    Lively Member
    Join Date
    Aug 2007
    Posts
    108

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    is is possible to send attachments such as pictures from a picturebox in the same way as the text it sent? it may not have anything all to do with the tcpclient but i was wondering.

  15. #15

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by paintballgod View Post
    is is possible to send attachments such as pictures from a picturebox in the same way as the text it sent? it may not have anything all to do with the tcpclient but i was wondering.
    The point of this submission is specifically to send text between a client and server without feezing the UI. My wrapper class provides only the ability to send and receive text, but that's a decision I made. It's certainly not a limitation of the TcpClient class. It sits on top of a NetworkStream, which, like all streams, simply passes binary data form one place to another without any regard for what that data represents. As such they can send any data you like. It's up to the application to interpret the binary data and give it meaning.

    If you check out my code you'll see that, internally, my MessageServer and MessageClient convert the text passed in to binary form before transmitting it and they convert the binary data received across the connection in text before passing it out to the caller. You can convert anything at all to binary form, thus you can write your own code to send anything you want using the TcpClient class.

    If you want any further information on that, please start your own thread in the appropriate forum as it goes beyond the scope of this topic. If you want to discuss the asynchronous aspect of my code though, feel free to post here.

  16. #16
    New Member
    Join Date
    Oct 2009
    Posts
    1

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    As a newbie forgive my ignorance. Your solution of 3 projects works fine on my desktop, uncompiled, just in debug. It also works fine on my laptop in debug. As I understand it I will use the entire solution on both computers. My question is how I would specify IP addresses. On my desktop that I would use as the server my first adapter is tied up on an intranet, and that is the adapter that the your test detects. I have a crossover between my laptop and a second adapter on my desktop that pings correct. How do I default your solution to the second adapter? thank you very much for your help.

  17. #17

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by nuster View Post
    As a newbie forgive my ignorance. Your solution of 3 projects works fine on my desktop, uncompiled, just in debug. It also works fine on my laptop in debug. As I understand it I will use the entire solution on both computers. My question is how I would specify IP addresses. On my desktop that I would use as the server my first adapter is tied up on an intranet, and that is the adapter that the your test detects. I have a crossover between my laptop and a second adapter on my desktop that pings correct. How do I default your solution to the second adapter? thank you very much for your help.
    My MessageServer class accepts a port number in the constructor and then passes that to the Initialise method, which gets the first IPv4 address on the system and then starts listening on that combination. You would need to add one or more new constructors that also took an IP address and then use that in a new overload of Initialise. I should probably make that change myself but, for now, this is the sort of change you'd need to make, from this:
    vb.net Code:
    1. Public Sub New(ByVal port As Integer)
    2.     Me.Initialise(port)
    3. End Sub
    4.  
    5. Private Sub Initialise(ByVal port As Integer)
    6.     Me._port = port
    7.  
    8.     'Listen on the first IPv4 address assigned to the local machine.
    9.     Me.server = New TcpListener(Me.GetLocalIPv4Address(), port)
    10.     Me.server.Start()
    11.  
    12.     'Start listen asynchronously.
    13.     Me.server.BeginAcceptTcpClient(AddressOf AcceptTcpClient, Nothing)
    14. End Sub
    to this:
    vb.net Code:
    1. Public Sub New(ByVal port As Integer)
    2.     Me.Initialise(port)
    3. End Sub
    4.  
    5. Public Sub New(ByVal address As String, ByVal port As Integer)
    6.     Dim ipAddress As IPAddress = Nothing
    7.  
    8.     If ipAddress.TryParse(address, ipAddress) Then
    9.         Me.Initialise(ipAddress, port)
    10.     Else
    11.         Throw New ArgumentException("String must represent a valid IP address.", "address")
    12.     End If
    13. End Sub
    14.  
    15. Private Sub Initialise(ByVal port As Integer)
    16.     'Listen on the first IPv4 address assigned to the local machine.
    17.     Me.Initialise(Me.GetLocalIPv4Address(), port)
    18. End Sub
    19.  
    20. Private Sub Initialise(ByVal address As IPAddress, ByVal port As Integer)
    21.     Me._port = port
    22.  
    23.     Me.server = New TcpListener(address, port)
    24.     Me.server.Start()
    25.  
    26.     'Start listen asynchronously.
    27.     Me.server.BeginAcceptTcpClient(AddressOf AcceptTcpClient, Nothing)
    28. End Sub

  18. #18
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Would it not make sense to have the default be to listen on any IP address rather than just the first IP it finds? I'm pretty sure that is what the constructor for TcpListener does when you just pass it a port and no IP address.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  19. #19

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by chris128 View Post
    Would it not make sense to have the default be to listen on any IP address rather than just the first IP it finds? I'm pretty sure that is what the constructor for TcpListener does when you just pass it a port and no IP address.
    Sounds reasonable.

  20. #20
    Junior Member rydinophor's Avatar
    Join Date
    Jul 2009
    Location
    Missouri, USA
    Posts
    18

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Im getting a lot of issues I can hardly do anything :S. Here is what i have:
    Server:
    Code:
    Imports Wunnell.Net
    Module ModMain
        Private WithEvents server As New MessageServer(4000)
        Sub Main()
            AddHandler server.MessageReceived, AddressOf MessageRecieved
    
            Console.ReadLine()
        End Sub
        Private Sub MessageRecieved(ByVal Sender As Object, ByVal e As MessageReceivedEventArgs)
            Console.WriteLine(e.Message)
            For Each host In server.Hosts
                server.Send(host, "Hello " & host.ToString())
            Next
            server.Send("Hello All Clients")
        End Sub
        Private Sub Accepted(ByVal Sender As Object, ByVal e As ConnectionEventArgs)
            Console.WriteLine(e.Host.Port)
            For Each host In server.Hosts
                server.Send(host, "Hello " & host.ToString())
            Next
            server.Send("Hello All Clients")
        End Sub
    
    End Module
    Client Side
    Code:
    Imports Wunnell.Net
    Public Class Form1
        Private WithEvents client As New MessageClient("localhost", 4000)
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.client.SynchronisingObject = Me
            Me.client.Connect()
            AddHandler client.ConnectionAccepted, AddressOf Accepted
            AddHandler client.MessageReceived, AddressOf MessageRecieved
        End Sub
        Private Sub MessageRecieved(ByVal Sender As Object, ByVal e As MessageReceivedEventArgs)
            MsgBox(e.Message)
        End Sub
        Private Sub Accepted(ByVal Sender As Object, ByVal e As ConnectionEventArgs)
            Me.client.Send("Hello Server")
        End Sub
    End Class

  21. #21

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by rydinophor View Post
    Im getting a lot of issues I can hardly do anything :S. Here is what i have:
    Server:
    Code:
    Imports Wunnell.Net
    Module ModMain
        Private WithEvents server As New MessageServer(4000)
        Sub Main()
            AddHandler server.MessageReceived, AddressOf MessageRecieved
    
            Console.ReadLine()
        End Sub
        Private Sub MessageRecieved(ByVal Sender As Object, ByVal e As MessageReceivedEventArgs)
            Console.WriteLine(e.Message)
            For Each host In server.Hosts
                server.Send(host, "Hello " & host.ToString())
            Next
            server.Send("Hello All Clients")
        End Sub
        Private Sub Accepted(ByVal Sender As Object, ByVal e As ConnectionEventArgs)
            Console.WriteLine(e.Host.Port)
            For Each host In server.Hosts
                server.Send(host, "Hello " & host.ToString())
            Next
            server.Send("Hello All Clients")
        End Sub
    
    End Module
    Client Side
    Code:
    Imports Wunnell.Net
    Public Class Form1
        Private WithEvents client As New MessageClient("localhost", 4000)
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.client.SynchronisingObject = Me
            Me.client.Connect()
            AddHandler client.ConnectionAccepted, AddressOf Accepted
            AddHandler client.MessageReceived, AddressOf MessageRecieved
        End Sub
        Private Sub MessageRecieved(ByVal Sender As Object, ByVal e As MessageReceivedEventArgs)
            MsgBox(e.Message)
        End Sub
        Private Sub Accepted(ByVal Sender As Object, ByVal e As ConnectionEventArgs)
            Me.client.Send("Hello Server")
        End Sub
    End Class
    First up, let me point out that there's no point declaring your fields WithEvents if you're going to use AddHandler to attach event handlers. The whole and sole point of WithEvents is so that you can use that field in the Handles clause of your event handler methods.

    As for the issue, you're telling the client to connect to "localhost", which is IP address 127.0.0.1, while the server is listening on its network IPv4 address, which will likely be 192.168.x.x. If you change "localhost" to Environment.MachineName in the client then it will work.

    I'm going to make some changes to my code, including making the server listen on any address by default. Doing so should mean that "localhost" can be used at the client. As it stands, if you do want to use "localhost" at the client you need to explicitly tell the server to listen on that local loopback address.

  22. #22

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Improvements in version 1.1.0.0

    Version 1.1.0.0 now attached to post #1.

    1. Server now listens on IPAddress.Any by default. The caller can also specify an IP address, the machine name or "localhost".

    2. Server now listens on a random port in the range 1024 to 5000 by default. The caller can also specify a port number.

    3. Removed SynchronisingObject property. Client and server both now use the SynchronizingContext class to raise all events on the same thread on which the object was created. This means that, in a WinForms app, you must ensure that the object is created on the UI thread if you want to update the UI from event handlers.

  23. #23
    Junior Member rydinophor's Avatar
    Join Date
    Jul 2009
    Location
    Missouri, USA
    Posts
    18

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    jmcilhinney, I have another question. Is your library based off the TCPClient and TCPListener, Or based off the Socket Library Or Both.
    I prefer using Asynchronous Sockets, A friend of mine told me Threaded sockets are terrible thats the reason I asked.


    Regards,
    Rydinophor

    EDIT:
    I keep getting these errors:
    Code:
    Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
    and
    Click this link to see where its coming from: http://i36.tinypic.com/243fg4k.png
    Last edited by rydinophor; Oct 25th, 2009 at 11:56 AM.

  24. #24

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by rydinophor View Post
    jmcilhinney, I have another question. Is your library based off the TCPClient and TCPListener, Or based off the Socket Library Or Both
    Have you read the code? That would answer your question. Reading the title of this thread should provide a clue too.
    Quote Originally Posted by rydinophor View Post
    I prefer using Asynchronous Sockets, A friend of mine told me Threaded sockets are terrible thats the reason I asked.
    I'm no expert when it comes to network programming. I've only ever used the TcpClient/TcpListener once before and never used a Socket directly.
    Quote Originally Posted by rydinophor View Post
    I keep getting these errors:
    Code:
    Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
    and
    Click this link to see where its coming from: http://i36.tinypic.com/243fg4k.png
    I've never seen that error in my own testing so I'd have to know more about how you're using my library to know whether it's an issue with my code or how you're using it. As I said at the beginning of this thread, I have tested but not as rigorously as I'd like so there amy still be issues lurking.

  25. #25
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    jmcilhinney, I have another question. Is your library based off the TCPClient and TCPListener, Or based off the Socket Library Or Both.
    I prefer using Asynchronous Sockets, A friend of mine told me Threaded sockets are terrible thats the reason I asked.
    You do realise that the TcpClient and TcpListener classes are just wrappers around the Socket class anyway? They just make it a bit easier to use the sockets, they dont do anything differently internally when actually sending/receiving data via the sockets as far as I know.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  26. #26

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by chris128 View Post
    You do realise that the TcpClient and TcpListener classes are just wrappers around the Socket class anyway? They just make it a bit easier to use the sockets, they dont do anything differently internally when actually sending/receiving data via the sockets as far as I know.
    Quite true. The TcpClient class has a Client property to get its underlying Socket. As I said, I've never used the Socket directly though; only the TcpClient and its underlying NetworkStream.

  27. #27
    Junior Member rydinophor's Avatar
    Join Date
    Jul 2009
    Location
    Missouri, USA
    Posts
    18

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Error:
    Code:
    System.Reflection.TargetInvocationException was unhandled
      Message="Exception has been thrown by the target of an invocation."
      Source="mscorlib"
      StackTrace:
           at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
           at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
           at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
           at System.Delegate.DynamicInvokeImpl(Object[] args)
           at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
           at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
           at System.Threading.ExecutionContext.runTryCode(Object userData)
           at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
           at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
           at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
           at System.Windows.Forms.Control.WndProc(Message& m)
           at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
           at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
           at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
           at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
           at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
           at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
           at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
           at System.Windows.Forms.Application.Run(ApplicationContext context)
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
           at WindowsApplication1.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
           at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ThreadHelper.ThreadStart()
      InnerException: System.IndexOutOfRangeException
           Message="Index was outside the bounds of the array."
           Source="WindowsApplication1"
           StackTrace:
                at WindowsApplication1.ModHandleData.HandleData(String Data) in C:\Users\ubersaiyanx\Desktop\Pokemon Cobalt Online\Latest\Client\WindowsApplication1\WindowsApplication1\ModHandleData.vb:line 23
                at WindowsApplication1.Form1.client_MessageReceived(Object sender, MessageReceivedEventArgs e) in C:\Users\ubersaiyanx\Desktop\Pokemon Cobalt Online\Latest\Client\WindowsApplication1\WindowsApplication1\Form1.vb:line 16
                at Wunnell.Net.MessageClientServerBase.RaiseMessageReceived(Object e) in C:\Users\ubersaiyanx\Desktop\Message Client-Server\Wunnell.Net.MessageClientServer\MessageClientServerBase.vb:line 240
           InnerException:

  28. #28

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by rydinophor View Post
    Error:
    Here's your issue:
    Message="Index was outside the bounds of the array."
    at WindowsApplication1.ModHandleData.HandleData(String Data) in C:\...\ModHandleData.vb:line 23
    Exceptions can be a bit confusing at first but make sure you DO read the information provided. Don't just assume it's too hard because, as you can see, the exact location and cause of your issue was in there.

  29. #29
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    3. Removed SynchronisingObject property. Client and server both now use the SynchronizingContext class to raise all events on the same thread on which the object was created. This means that, in a WinForms app, you must ensure that the object is created on the UI thread if you want to update the UI from event handlers.
    Why did you do this? I've often wanted my classes that use background threads to be able to raise their events on another thread but didnt think it was possible - after reading your post here http://www.vbforums.com/showthread.php?t=589212 I realise that it is possible but I'm wondering if there was some problem you found with doing this that caused you to remove such a feature?
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  30. #30

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by chris128 View Post
    Why did you do this? I've often wanted my classes that use background threads to be able to raise their events on another thread but didnt think it was possible - after reading your post here http://www.vbforums.com/showthread.php?t=589212 I realise that it is possible but I'm wondering if there was some problem you found with doing this that caused you to remove such a feature?
    There was no problem per se. The way I was doing it originally, i.e. with a SynchronisingObject property, is the same as some classes in the Framework do it. One advantage of this is that it gives you the choice of leaving the SynchronisingObject property empty and having events raised on a thread pool thread or setting it and having events raised on a specific thread. I didn't really see a reason why you specifically want my classes to raise their events on thread pool threads though, so the change I made did three things for me:

    1. It meant that a caller could completely ignore the fact that there was multi-threading involved and, in fact, wouldn't even know it from the interface. All interaction with an instance of one of my classes would occur on the same thread without any indication that any other threads were involved. There was no need for the caller to go to the (admittedly tiny) effort of setting the SynchronisingObject property to get synchronous events.

    2. It made my code a bit cleaner.

    3. It gave me a chance to play with the SynchronizationContext class, which I haven't had the pleasure of previously.

    Like I said, there was nothing actually wrong with the old implementation. If you're interested in doing something similar but aren't 100% sure how then I'm happy to provide the old code. That said, you might also be interested in using the SynchronizationContext class as the new code does.

  31. #31
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Ahh I see, sorry from reading your post saying that you must be certain to create the object on the UI thread if you want to update a form/control I thought that you were no longer providing any kind of 'easy' way of handling the cross thread calls. However, I now realise that the way your class works now is that it raises the events on whatever thread it was created on. So if you create an instance of your class on the UI thread then you dont need to worry about marshaling across the threads in the events that are raised from it, correct?
    The MSDN doc on the SynchronizationContext class seems to be pretty light, did you find any other good sources of info on it? I'm currently reading through this: http://www.codeproject.com/KB/cpp/Sy...tTutorial.aspx
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  32. #32

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by chris128 View Post
    So if you create an instance of your class on the UI thread then you dont need to worry about marshaling across the threads in the events that are raised from it, correct?
    Correct.
    Quote Originally Posted by chris128 View Post
    The MSDN doc on the SynchronizationContext class seems to be pretty light, did you find any other good sources of info on it? I'm currently reading through this: http://www.codeproject.com/KB/cpp/Sy...tTutorial.aspx
    That page and the MSDN doco are all I've read on the subject too.

  33. #33
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Just found an interesting video here about the alternatives to SynchronizationContext in .NET 4 http://rocksolidknowledge.com/Screen...adAffinity.wmv

    Sorry if thats a little off topic for this thread
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  34. #34
    Member
    Join Date
    Nov 2009
    Posts
    39

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Very nice Socket.
    I would replace the combobox by a listview but u don't really know how to do...
    Someone can help me ?

  35. #35

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by Ianis View Post
    Very nice Socket.
    I would replace the combobox by a listview but u don't really know how to do...
    Someone can help me ?
    The point of this thread and the attached solution is the asynchronous client/server library. The WinForms projects were simply to demonstrate that. Displaying information in a ListView really has nothing to do with the topic of this thread. I suggest that you start a thread in the VB.NET forum dedicated to displaying information in a ListView.

  36. #36
    Member
    Join Date
    Nov 2009
    Posts
    39

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Hello,
    I found a little problem ( but didn't found solution ).

    Code:
    FR : Une exception de première chance de type 'System.IO.IOException' s'est produite dans System.dll
    EN : A first chance exception of type 'System.IO.IOException' occurred in System.dll
    I think that Error is occur when the socket is unloaded during a reception of data.

    The Debugger report me here :
    Code:
    Dim byteCount = Me.stream.EndRead(ar)

  37. #37

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by Ianis View Post
    Hello,
    I found a little problem ( but didn't found solution ).

    Code:
    FR : Une exception de première chance de type 'System.IO.IOException' s'est produite dans System.dll
    EN : A first chance exception of type 'System.IO.IOException' occurred in System.dll
    I think that Error is occur when the socket is unloaded during a reception of data.

    The Debugger report me here :
    Code:
    Dim byteCount = Me.stream.EndRead(ar)
    A first chance exception is not a problem. It just indicates that an exception was thrown, which is perfectly legal. It's when an exception is thrown and not caught that there's an issue. If you look at the code you'll see that there are several exception handlers in there to catch the exceptions that are thrown when a connection is closed while an asynchronous operation is in progress. I'm guessing that this is one of those cases.

    If the app crashes due to an unhandled exception then by all means let me know exactly where, i.e. which line in which file. Otherwise it's all part of the plan.

  38. #38
    Member
    Join Date
    Nov 2009
    Posts
    39

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Hmm i don't reall know why but the bug don't happen in the original source.
    Only with mine ( i modified a the class for working a Chat app) .
    And not always.

  39. #39
    Hyperactive Member
    Join Date
    Jun 2005
    Posts
    265

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Is there VB.Net 2005 version of this class?
    thank's

  40. #40

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,274

    Re: [VB2008/.NET 3.5] Asynchronous TcpListener & TcpClient

    Quote Originally Posted by Visual Basic.Net View Post
    Is there VB.Net 2005 version of this class?
    thank's
    The code uses various VB 2008 and .NET 3.5 features. You could certainly implement the same functionality in VB 2005 but you'd have to use loops where I've used LINQ queries, etc.

Page 1 of 7 1234 ... LastLast

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