Trying to connect to second Laptop. - Page 3-VBForums
Page 3 of 3 FirstFirst 123
Results 81 to 88 of 88

Thread: Trying to connect to second Laptop.

  1. #81

    Thread Starter
    Frenzied Member Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Near Barnsley South Yorkshire, England.
    Posts
    1,344

    Re: Trying to connect to second Laptop.

    Quote Originally Posted by PlausiblyDamp View Post
    You might need to either declare it as an IpEndPoint or if it is being returned from a method try casting it to an IpEndPoint, EndPoint is a base class which doesn't have an Address property.

    https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx
    Thanks PlausiblyDamp,

    That's pointed me in the right direction, it's a bit of a roundabout route but it gets there.
    Code:
        Private Sub SvrGot(ByVal token As IAsyncResult)
            Dim ipa As String
            Dim Ears As TcpListener = CType(token.AsyncState, TcpListener)
    
            palPC = Ears.EndAcceptTcpClient(S_Token)
            ipa = palPC.Client.RemoteEndPoint.ToString
            ipa = ipa.Substring(0, InStr(ipa, ":") - 1)
            Pal = IPAddress.Parse(ipa)
            palName = System.Net.Dns.GetHostEntry(ipa).HostName.ToString
            UpDate_T(palName & " connected !")
            S_Token = Nothing
    
            ' Since we have a client connection, there's no good reason to keep listening!
            Ears.Stop()
    
            ' Start listening for messages from the client.
            ListenToClient(palPC)
        End Sub
    All that just to get the name of the 'remote' computer !
    Sadly it's not a vital part of my project, but it highlights one of my problems... I like to get all the bells and whistles working as I go along instead of getting the bare bones working first.


    Poppa.
    Along with the sunshine there has to be a little rain sometime.

  2. #82

    Thread Starter
    Frenzied Member Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Near Barnsley South Yorkshire, England.
    Posts
    1,344

    Question to Sitten Spynne

    Hi Sitten Spynne, I've just found a problem, or a question at least with regard to your attached code for Async Chat in post #54 on the 1st September.
    Code:
        Private Sub WhenClientConnectsToServer(ByVal state As Object)
            ' Note that sometimes asynchronous things don't return a result. You still have to call the 'End' method!
            _remoteClient.EndConnect(_clientConnectToken)
            _clientConnectToken = Nothing
            SetStatus("Connected!")
    
            ListenToClient(_remoteClient)
        End Sub
    I don't understand the 'ByVal state As Object', yes I understand what it means, but what does it do?

    'state' doesn't seem to be used anywhere else in the subroutine. Maybe the 'Nothing' in the subroutine...
    Code:
        Private Sub ConnectToServer(ByVal ipInput As String)
            Dim remoteAddress = IPAddress.Parse(ipInput)
            Dim port = 3000
            _remoteClient = New TcpClient()
    
            _clientConnectToken = _remoteClient.BeginConnect(remoteAddress, port, AddressOf WhenClientConnectsToServer, Nothing)
            SetStatus("Connecting...")
        End Sub
    ... is what's being passed? And maybe the '(ByVal state As Object)' is a requirement of that form of call to a subroutine?

    I'm trying to use a version of this subroutine in a test project and have a problem in this area and wonder if this is where my problem lays.


    Poppa.
    Along with the sunshine there has to be a little rain sometime.

  3. #83
    Fanatic Member PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Newport, UK
    Posts
    518

    Re: Trying to connect to second Laptop.

    Quote Originally Posted by Poppa Mintin View Post
    Thanks PlausiblyDamp,

    That's pointed me in the right direction, it's a bit of a roundabout route but it gets there.
    Code:
        Private Sub SvrGot(ByVal token As IAsyncResult)
            Dim ipa As String
            Dim Ears As TcpListener = CType(token.AsyncState, TcpListener)
    
            palPC = Ears.EndAcceptTcpClient(S_Token)
            ipa = palPC.Client.RemoteEndPoint.ToString
            ipa = ipa.Substring(0, InStr(ipa, ":") - 1)
            Pal = IPAddress.Parse(ipa)
            palName = System.Net.Dns.GetHostEntry(ipa).HostName.ToString
            UpDate_T(palName & " connected !")
            S_Token = Nothing
    
            ' Since we have a client connection, there's no good reason to keep listening!
            Ears.Stop()
    
            ' Start listening for messages from the client.
            ListenToClient(palPC)
        End Sub
    All that just to get the name of the 'remote' computer !
    Sadly it's not a vital part of my project, but it highlights one of my problems... I like to get all the bells and whistles working as I go along instead of getting the bare bones working first.


    Poppa.
    Did you try casting the palPC to an IPEndPoint rather than going via string conversion / parsing?

  4. #84

    Thread Starter
    Frenzied Member Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Near Barnsley South Yorkshire, England.
    Posts
    1,344

    Re: Question to Sitten Spynne

    Quote Originally Posted by Poppa Mintin View Post
    Hi Sitten Spynne, I've just found a problem, or a question at least with regard to your attached code for Async Chat in post #54 on the 1st September.
    Ok, I've sorted that out... My surmise was correct it seems.

    My problem was that although the two computers were connecting, my code said they weren't.
    It also turns out that my Win.7 lappy isn't as fast as my i7 Win.10 lappy! So I have to build-in a short delay.


    Poppa.
    Along with the sunshine there has to be a little rain sometime.

  5. #85
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    3,789

    Re: Trying to connect to second Laptop.

    Post #54 is one of your own posts. I'm not quite sure when that code was featured, but there's "no reason" and "a good reason" why that parameter was there. It's a bit of a mistake on my part, but not a very serious one.

    If you read the documentation for BeginConnect() (and most async methods using this pattern), you'll see that callback parameter is an AsyncCallback delegate type. That is a Sub that takes an IAsyncResult parameter.

    Remember that the pattern dictates after you call BeginSomething(), you must call EndSomething(). Usually, you pass along a "state" object which has a reference to "the thing I called BeginSomething() on". That object is part of the IAsyncResult, and that IAsyncResult is passed as a parameter to the callback so it can properly call EndSomething().

    But in this case, I already had a more convenient reference to "the thing that called BeginSomething()", so I used that and ignored the parameter. It was Object because this was a very early bit of code, and I couldn't remember that the parameter to the callback was IAsyncResult. Since IAsyncResult can be cast to Object, VB didn't complain that it didn't exactly match. Don't ask me to explain the delegate conversion rules, I've never understood them.

    But since that parameter is part of AsyncCallback's required signature, I have to provide it even if I don't use it.

    Similar things happen with the Thread class, it wants a delegate that is a Sub that takes 1 Object parameter for state. Even if you don't use it, you have to have that parameter.

    As usual: "I had to build in a short delay" means nothing to me. When you speak in paragraphs I can't understand you. When you show me code, I can comprehend.

    I say this because "when something is broken", we have to write "bad" code that won't work on other machines to make it work. That doesn't mean "the bad code is sometimes good". That means "I need to fix the problem with my network configuration so the code that works everywhere else can work on my machine." So I need to see what you did to "fix" it to maybe gain some insight into what went wrong.

    Otherwise every bit of code I write will be broken on your machine, and you'll have to solve the, 'How do I tweak it to make it work?' game. That is a tiring game of 20 questions where almost none of my experience helps me help you. I don't want to play that game and don't want to write more code examples until the code that works on 99% of computers also works on yours.
    Last edited by Sitten Spynne; Yesterday at 09:24 AM.
    Nothing I post is production-ready. It is provided as-is, use it at your own risk.

  6. #86

    Thread Starter
    Frenzied Member Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Near Barnsley South Yorkshire, England.
    Posts
    1,344

    Re: Trying to connect to second Laptop.

    Quote Originally Posted by Sitten Spynne View Post
    Post #54 is one of your own posts.
    Ah... Yeah, I just checked, I don't know how that happened... Ought to've been post# 57.


    Poppa.
    Along with the sunshine there has to be a little rain sometime.

  7. #87

    Thread Starter
    Frenzied Member Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Near Barnsley South Yorkshire, England.
    Posts
    1,344

    Re: Trying to connect to second Laptop.

    Quote Originally Posted by Sitten Spynne View Post
    As usual: "I had to build in a short delay" means nothing to me. When you speak in paragraphs I can't understand you. When you show me code, I can comprehend.

    I say this because "when something is broken", we have to write "bad" code that won't work on other machines to make it work. That doesn't mean "the bad code is sometimes good". That means "I need to fix the problem with my network configuration so the code that works everywhere else can work on my machine." So I need to see what you did to "fix" it to maybe gain some insight into what went wrong.

    Otherwise every bit of code I write will be broken on your machine, and you'll have to solve the, 'How do I tweak it to make it work?' game. That is a tiring game of 20 questions where almost none of my experience helps me help you. I don't want to play that game and don't want to write more code examples until the code that works on 99% of computers also works on yours.
    I thought I'd fixed it, so code wasn't required. But you're right it's likely to be a 'Fix' rather than a solution, so first the code which didn't work, or rather the code which stopped working.

    I'm trying to avoid having to start with the decision 'Server or Client' so my project starts in Server mode but looks to see if any computers are active on the LAN (Same router). If one or more is found there's an option to choose which computer to try to connect to. Here there's only my missus and I so there's only ever one other computer, but doing it that way means that if we know the other has the game (to be) open either of us can start it.

    Currently Form1 contains just:
    1: ListBox. to display active computers. (excluding the host machine) thus '192.168.0.3. iKi_Lappy' (Address Space Name)
    1: TextBox. to display status.
    3: Buttons.
    'Exit'.
    'Start' (Look for other computers).
    'Test' Will be used to try communications.

    This is the previous code to connect to the other computer:
    Code:
        Private Sub Get_Clnt()
            palPC = New TcpClient()
            C_Token = palPC.BeginConnect(Pal, Port, AddressOf Got_Clnt, Nothing)
    
        End Sub 'Connect to Client.
        
        Private Sub Got_Clnt(ByVal state As Object)
            Try
                palPC.EndConnect(C_Token)
                C_Token = Nothing
                TextBox1.Text = vbCrLf & "Connected to " & palName
            Catch ex As Exception
                Dim txt As String = vbCrLf & "Sorry... Not connected !" & vbCrLf & vbCrLf
                UpDate_T(txt & "Listening for Friend")
                StartServer()
            End Try
    
        End Sub ' Connected to Client... Or not.
    This used to work almost immediately if the Win.7 machine tried to connect, but got to be that if the Win.10 machine tried to connect it didn't, although it did in fact connect some five or so seconds later. I'm pretty sure it worked at first before I started trying to actually use it.

    This is how the code is now, I've added other parts so that you can see (what I hope is all) the relevant bits.
    Code:
        Private Sub Lbx1() Handles ListBox1.SelectedValueChanged
            '       I am now the Client !
            Dim LbxS As String = CType(ListBox1.SelectedItem, String)
            Dim Splt() As String = Split(LbxS)
            Dim Adr As String = Splt(0).Substring(0, Splt(0).Length - 1)
            SvrStop()
            Pal = IPAddress.Parse(Adr)
            palName = Splt(3)
            TextBox1.Text = vbCrLf & "Trying to connect to " & palName
            TextBox1.Refresh()
            Get_Clnt()  '   Connect to Server
            GameStart()
    
        End Sub ' Make me the Client!
    
        Private Sub Get_Clnt()
            palPC = New TcpClient()
            C_Token = palPC.BeginConnect(Pal, Port, AddressOf Got_Clnt, Nothing)
    
        End Sub ' Client: Connect to Server.
    
        Private Sub Got_Clnt(ByVal state As Object)
            Try
                palPC.EndConnect(C_Token)
                C_Token = Nothing
            Catch ex As Exception
            End Try
    
        End Sub ' Client: Connected to Server... Or not.
    
        Private Sub SvrStop()
            Try
                S_Ears.Stop()
            Catch ex As Exception
            End Try
    
        End Sub ' Server: Stop listening.
    
        Private Sub GameStart()
            System.Threading.Thread.Sleep(6000) ' Allow time for 'Pal' to connect.
            If palPC.Connected Then
                TextBox1.Text = vbCrLf & "Connected to " & palName
                ListBox1.Dispose()
                Button2.Visible = False
                Button3.Visible = True
            Else
                Dim txt As String = vbCrLf & "Sorry... Not connected !" & vbCrLf & vbCrLf
                UpDate_T(txt & "Listening for Friend")
                StartServer()
                Exit Sub
            End If
    
        End Sub ' Both connected.
    Poppa.
    Along with the sunshine there has to be a little rain sometime.

  8. #88
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    3,789

    Re: Trying to connect to second Laptop.

    Yes. This is definitely a case of "doing the wrong thing and fixing it with wrong code".

    The word "asynchronous" means the idea of two things happening at the same time, in parallel. When you call code that is asynchronous, you are saying, "Start doing this, but let me keep going. Call me when you are finished." Let me try to express it with analogy, then tie it back to the code you wrote.

    Suppose you need to do two things today. You need to buy some groceries, and you need to watch a movie with your wife. The movie you want to watch is at the Redbox machine at the grocery store. She hands you a grocery list and says, "Please go to the store for me." That's BeginShopping(). Now one of two things can happen. Let's look at the code.


    That paragraph looks like this:
    Code:
    Sub DoThings()
        you.Items.Add(groceryList)
        you.BeginShopping(AddressOf EndShopping)
    
        wife.DoSomething()
    
        wife.TakeMovie() ' CRASH: you aren't even in the house anymore.
        wife.WatchMovie()
    End Sub
    
    Sub EndShopping()
        you.GiveMovieToWife()
        you.WatchMovie()
    End Sub
    Maybe the "DoSomething()" your wife does takes a long time. If it does, you might get back from shopping before she finishes. So by the time she does "TakeMovie()", you're back with the movie and it all works. This is what's happening on one of your PCs.

    But what if the "DoSomething()" is really quick, and she tries to TakeMovie() before you get back? You aren't there, so there's no movie, so the program crashes and the universe ends. Oops.

    So when you write asynchronous code, you have to make sure if something assumes the code is finished, it doesn't happen until AFTER the thing finishes:

    Code:
    Sub DoThings()
        you.Items.Add(groceryList)
        you.BeginShopping(AddressOf EndShopping)
    
        wife.DoSomething()
    End Sub
    
    Sub EndShopping()
        you.GiveMovie()
        wife.TakeMovie()
        you.WatchMovie()
        wife.WatchMovie()
    End Sub
    Back to your code.

    When you call BeginConnect(), you are telling the computer: "Go try to make a connection on another thread. Don't call me back until there is an error or it has finished." The method "Got_C1nt()" will be called from that other thread when it finishes.

    But your code barrels onwards and calls GameStart(), which assumes you've already finished making the connection. On one PC, the connection finishes fast enough that this is true by accident. On the other PC, it takes a little while longer, and GameStart() rightfully complains the connection isn't ready yet. When you add a Thread.Sleep(), you cause GameStart() to wait long enough for the connection to happen.

    But that defeats the purpose of using asynchronous code at all.. The whole point is "I don't want to freeze the UI thread", and nothing freezes the UI thread quite like Thread.Sleep().

    This is what your code should look like:
    Code:
    Private Sub ListBox1_SelectedValueChanged() Handles ...
        ' blah blah parsing code
        TextBox1.Text = vbCrLf & "Trying to connect to " & palName
        Get_C1nt()
    End Sub
    
    Private Sub Get_C1nt()
        palPC = New TcpClient()
        C_Token = palPC.BeginConnect(...)
    End Sub
    
    Private Sub Got_C1nt()
        Try
            palPC.EndConnect(C_Token)
            C_Token = Nothing
    
            Me.Invoke(AddressOf GameStart)
        Catch ex As Exception
            MessageBox.Show("Don't ever let me see an empty Catch again.")
        End Catch
    End Sub
    
    Private Sub GameStart()
        ...
    All I did was move the GameStart() call from the initial event handler to the thing that is called after the connection completes. I did add the call to Invoke(), because I know that will be on a worker thread and GameStart() wants to be on the UI thread.

    Remember: calling BeginConnect() is not "Make the connection and wait for it to finish." It is "Make the connection and call me back when you finish." IIRC the whole reason we started down this rabbit hole was, "Why does the UI freeze?" Any time you say, "Wait", it will freeze. Getting around UI freezes involves finding ways to say, "Do this and call me back when you finish." It's the difference between "going to the grocery store" and "getting the groceries delivered".
    Nothing I post is production-ready. It is provided as-is, use it at your own risk.

Page 3 of 3 FirstFirst 123

Posting Permissions

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



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.