1

I have an application which uses the hosts file to block certain websites. The websites can't connect because of the hosts file, so that works great, however, my program is supposed to raise an event when a website is blocked.

I'm using this code:

Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    Dim blocker As BlockListener
        Dim thread As Thread
        blocker = New BlockListener
        thread = New Thread(New ThreadStart(AddressOf blocker.listen))
        thread.Start()

    AddHandler blocker.Blocked, AddressOf User_Blocked
End Sub


Private Sub User_Blocked()
    My.Computer.Audio.Play("Sounds\Website-Blocked.wav")
    WebsiteDetected.ShowDialog()
    SetForegroundWindow(WebsiteDetected.Handle)
End Sub

Public Class BlockListener

    Private port As Integer = 80

    Private listener As TcpListener

    Private BlockUsers As Boolean = True
    Public Event Blocked As EventHandler

    Public Sub listen()
        listener = New TcpListener(IPAddress.Parse("127.0.0.1"), port)
        listener.Start()
        While (BlockUsers)
            Dim clientConnection As TcpClient = listener.AcceptTcpClient

            clientConnection.Close()
            BlockUsers = False

            RaiseEvent Blocked(Me, EventArgs.Empty)
        End While


        listener.Stop()
    End Sub

After I wait for a while (say for about two minutes) then the program can detect bad websites that are visited, however, I don't really want to wait, as I think it's a lot more practical if you just run the program, and done, you won't have to wait for the program to start listening for incoming connections.

Is there anyway I can listen on the server quicker?

Also, could it be because I have lots of websites on my hosts file? I've got a total of 80, 000 infected websites, and since Visual Basic is a lot slower than some certain languages, could that be the reason why?

  • _"and since Visual Basic is a lot slower than some certain languages"_ - Visual Basic isn't particularly slower than other languages. Where did you get this from? For instance, VB.NET and C# are both compiled into IL, which is then compiled into machine code at run time. If you take out factors like code optimization and such, the two languages are equally fast (assuming you write the equivalent code in both languages). – Visual Vincent Sep 06 '18 at 11:57
  • Of course the term "slow" depends on what you compare with, but .NET Framework is highly optimized and can, thanks to runtime optimization, _sometimes_ outperform languages like C++. – Visual Vincent Sep 06 '18 at 12:07
  • I read something up about something to do with C++ and Visual Basic. I don't remember exactly, but they said something about Visual Basic having to inject something (probs a dll), rather C++ doesn't have to do that and is quicker and more robust? @VisualVincent – Zorin OS Development Team Sep 06 '18 at 12:13
  • That depends on what topic you were reading about, but to my knowledge .NET doesn't have to do any kind of injection to run (at least not with DLLs). Once the JIT compiler has compiled your code into machine code it has the potential to run just as fast as C++ code, but due to the (minor) overhead of the framework it usually doesn't. It's still really fast, though. – Visual Vincent Sep 06 '18 at 13:34

1 Answers1

3

I don't know why the TcpListener takes such a long time to detect the connection, but I can confirm that it does.

What seems to solve the problem is to switch to a HttpListener instead, which can be used to host an actual HTTP server.

Finally, you need to marshal the call from User_Blocked to the UI thread before you can start opening forms and accessing UI elements. This is because your Blocked event is run in the background thread, and all UI-related code must run on the UI thread only.

Private port As Integer = 80

Private listener As New HttpListener

Private BlockUsers As Boolean = True
Public Event Blocked As EventHandler

Public Sub listen()
    listener.Start()
    listener.Prefixes.Add("http://*:80/")

    While (BlockUsers)
        Dim context As HttpListenerContext = Listener.GetContext()
        context.Response.Close()

        BlockUsers = False

        RaiseEvent Blocked(Me, EventArgs.Empty)
    End While

    listener.Close()
End Sub

In your form:

Private Sub User_Blocked()
    If Me.InvokeRequired Then 'Do we need to invoke or are we already on the UI thread?
        Me.Invoke(New MethodInvoker(AddressOf User_Blocked))
    Else 'We are on the UI thread.
        My.Computer.Audio.Play("Sounds\Website-Blocked.wav")
        WebsiteDetected.Show() 'Note that if you use ShowDialog(), the next line won't execute until the form has been closed.
        SetForegroundWindow(WebsiteDetected.Handle)
    End If
End Sub

NOTE: Your application must run with administrative privileges for the HttpListener to work.

Visual Vincent
  • 17,424
  • 5
  • 24
  • 66
  • Thanks for this solution. For some reason, my WebsiteDetected form doesn't appear. Why is this? @VisualVincent – Zorin OS Development Team Sep 07 '18 at 03:09
  • @ZorinOSDevelopmentTeam : Hard to tell, it works when I tested it. Start by checking the Immediate Window to make sure that no exceptions are thrown. Then please paste your new code over at [Pastebin](https://pastebin.com/) and send me the link. – Visual Vincent Sep 07 '18 at 09:00
  • Ok, I'll test it out now in a different form. I don't need to put any subs in the `Main_Load` sub? – Zorin OS Development Team Sep 07 '18 at 09:07
  • Cause if I put `listen()` in `Main_Load` the main form doesn't show. If you could paste the code on pastebin you exactly used when you tried it out that would be great. @VisualVincent – Zorin OS Development Team Sep 07 '18 at 09:15
  • My code is just the code you have in your question, with the changes in my answer. – Visual Vincent Sep 07 '18 at 09:47
  • Ok. So I don't need to put anything in the `Main_Load` sub? – Zorin OS Development Team Sep 07 '18 at 09:48
  • @ZorinOSDevelopmentTeam : Yes, you still need to start the thread like you do in your question. I used the exact code from your question and just displayed what I changed in my answer. – Visual Vincent Sep 07 '18 at 09:49
  • Ahh, I see. Ok, I'm trying it out now. – Zorin OS Development Team Sep 07 '18 at 09:54
  • Hmm, odd. When I compile the code, I get an error: `System.NullReferenceException: 'Object reference not set to an instance of an object.' listener was Nothing. ` in the "listen" sub. I'll post you my full code on pastebin: https://pastebin.com/2t7tVjKP – Zorin OS Development Team Sep 07 '18 at 09:56
  • @ZorinOSDevelopmentTeam : Here is my exact code (had to start to my PC before I could post it): https://pastebin.com/tEiLk1vY – Visual Vincent Sep 07 '18 at 09:58
  • My bad, missed `Private listener As NEW HttpListener` in my answer. Updated. – Visual Vincent Sep 07 '18 at 09:59
  • Oh right, my bad. I actually did `listener As New HttpListener` cause I was getting the NullReferenceException ealier, but went right off my head, doh. – Zorin OS Development Team Sep 07 '18 at 10:00
  • The MessageBox still doesn't appear.. I wonder why? Is it because of the Me.Invoke code in the `User_Blocked` sub? Could you please explain to me what that does. – Zorin OS Development Team Sep 07 '18 at 10:01
  • @ZorinOSDevelopmentTeam : If anything, `Me.Invoke` will _improve_ the chances of your code working properly. `Invoke` basically calls the specified method (`User_Blocked`) on the UI thread, rather than on the background thread that you're currently in. This is necessary because background threads should **never** try to access the UI thread directly as that can cause concurrency issues such as the _Race condition_. For more information about `Invoke` see: https://stackoverflow.com/a/45571728 – Visual Vincent Sep 07 '18 at 10:07
  • Ok, thanks for telling me this. I tried your code, but the message still doesn't come up. Maybe is it because the program doesn't know what file to look for (which is the hosts file) so it knows which websites to block? – Zorin OS Development Team Sep 07 '18 at 10:39
  • @ZorinOSDevelopmentTeam : The OS takes care of the hosts file, not your app. Your app only waits for the connection that the OS will _redirect to it_ from another application, based on the hosts file. – Visual Vincent Sep 07 '18 at 11:03
  • My mistake, it now works. I was going onto one of my whitelisted sites, but I misspelled it. Thanks so much! – Zorin OS Development Team Sep 08 '18 at 00:24
  • @ZorinOSDevelopmentTeam : Glad you got it working! Good luck with your project! – Visual Vincent Sep 08 '18 at 07:12