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?
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.