Have gained minimal knowledge as c#, not .net sockets. This is not what I want to achieve, can you help?
Printable View
Have gained minimal knowledge as c#, not .net sockets. This is not what I want to achieve, can you help?
Alright, here I'll give you some base code to play around with.
listenSocket is the main socket, the one that does all the listening. It is declared at class level, so that it doesnt goes out of scope until the form is closed.
It calls the Accept method on a different thread, in order to avoid blocking the main thread.
Make sure you understand all of this code before you continue. Dont hesitate to ask questions.
(This could be done simpler using the TcpClient/TcpListener classes, but I'll go for the Socket class)
As you can see, this is a very simple piece of code, altough the only thing you need to implement now is sending the reply back to the client.VB.NET Code:
Option Strict On Public Class Form1 Private listenThread As System.Threading.Thread Private listenSocket As System.Net.Sockets.Socket Private Const PORT_NUMBER As Integer = 80 Private Const BACKLOG As Integer = 10 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load listenSocket = New System.Net.Sockets.Socket(Net.Sockets.AddressFamily.InterNetwork, Net.Sockets.SocketType.Stream, Net.Sockets.ProtocolType.Tcp) listenSocket.Bind(New System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), PORT_NUMBER)) ' Bind the socket to 127.0.0.1:PORT_NUMBER listenSocket.Listen(BACKLOG) ' Start listening on the port listenThread = New System.Threading.Thread(AddressOf doListen) ' Create the thread that will be used for listening and responding listenThread.IsBackground = True ' Set IsBackground to true to make the thread terminate when the main thread terminates. listenThread.Start() ' Start the the thread End Sub Private Sub doListen() Dim client As System.Net.Sockets.Socket Do client = listenSocket.Accept() ' When this method returns, "client" will hold the connection to the remote host. ' Send the data here, using the client.Send method. Loop End Sub End Class
Are you looking to send different responses depending on what the client requests?
hi,
lol a bit confused. I have two questions:
1. By declaring in class do you mean the Imports. I gather this is what you mean.
2. What does console.writeline do? (off topic)
3. Sorry, said I had two, this does not open a new connection every time right, I will only ever return one page.
In answer to your question, I only will ever return a single page that is static. SO like a webserver but returning the same page. E.g http://localhost/ returns the same page as http://localhost/even-if-i-type-a-url-in-here.html
Thanks
noticed how the prog doesn't freeze anymore, great. Backlog is number of concurrent connections allowed? Will I need more than one connection if the page may be accessed more than once at a time. What would happen if say I needed 3 cons and only provided one, I would get a page cannot be displayed right.
Small problem:
set msgbox to display on connection to port, works fine. but if i refresh the page it does not happen again.
I noticed the Do Listen, what is calling the subroutine on connection, i see no reference to it.
Edit: I should place Client.Close, now I think it may be working.
I have no idea how to listen.Send. The subroutine is never called so how the accept occurs i do not understand. I understand listen=accept, so listen.Send would be a send on accept but do not understand how I can send my file.
C:\alert.html as a byte stream i presume
I get an error with option strict on, IE now declares an unknown protocol, looks like I'm getting there. I see Sub Declared when you created a new thread, by new thread do you mean process separate from the main app.Code:Dim msg As String = "Sending data to client"
client.Send(msg, 100, 80)
so do i open html file with fso as msg and then just Client.Send(msg,100,80)
Thanks
You need to send a HTTP response.
Here's a function I've written for you that'll give you a HTTP request as a byte array:
Call this function, pass the file you wish to send to it, then send the returned byte array using Client.Send.VB.NET Code:
Private Function BuildResponse(ByVal file As String) As Byte() Dim response As New System.Text.StringBuilder Dim sReader As System.IO.StreamReader Dim fileContents As String If System.IO.File.Exists(file) Then sReader = New System.IO.StreamReader(file) fileContents = sReader.ReadToEnd() response.AppendLine("HTTP/1.1 200 OK") response.AppendLine("Content-type: text/html") ' You might want to make this dynamical if you are ever going to use this in a more "dynamic" situation response.Append("Content-Length: ") response.AppendLine(fileContents.Length.ToString()) response.Append(Environment.NewLine) response.Append(fileContents) sReader.Close() Else response.AppendLine("HTTP/1.1 404") response.Append(Environment.NewLine) End If Return System.Text.Encoding.UTF8.GetBytes(response.ToString()) End Function
Note that this function is not the ultimate way to go about this. (It can only send documents that is not in binary format, ie text-documents, html-documents etc. And it would be more memory efficient to read and send the file sequentially in parts.)
Can you answer my previous questions, will I be able to access two pages of this at the same time.
What is console.writeline
Memory usage/resources is a priority - i want to use no more than 32mb of ram.
Should that work? Unfortunately Response claims to not be declared as it is only declared after the function is performed. Should I define it on load?Code:Option Strict On
Imports System.Net.Sockets
Imports System.Net
Public Class webFilter
Private listenThread As System.Threading.Thread
Private listenSocket As System.Net.Sockets.Socket
Private Const PORT_NUMBER As Integer = 79
Private Const BACKLOG As Integer = 10
Private Sub webFilter_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
listenSocket = New System.Net.Sockets.Socket(Net.Sockets.AddressFamily.InterNetwork, Net.Sockets.SocketType.Stream, Net.Sockets.ProtocolType.Tcp)
listenSocket.Bind(New System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), PORT_NUMBER)) ' Bind the socket to 127.0.0.1:PORT_NUMBER
listenSocket.Listen(BACKLOG) ' Start listening on the port
listenThread = New System.Threading.Thread(AddressOf doListen) ' Create the thread that will be used for listening and responding
listenThread.IsBackground = True ' Set IsBackground to true to make the thread terminate when the main thread terminates.
listenThread.Start() ' Start the the thread
End Sub
Private Sub doListen()
Dim client As System.Net.Sockets.Socket
Do
client = listenSocket.Accept() ' When this method returns, "client" will hold the connection to the remote host.
' Send the data here, using the client.Send method.
Call BuildResponse("C:\page.html")
client.Send(Response)
client.Close()
Loop
End Sub
Private Function BuildResponse(ByVal file As String) As Byte()
Dim response As New System.Text.StringBuilder
Dim sReader As System.IO.StreamReader
Dim fileContents As String
If System.IO.File.Exists(file) Then
sReader = New System.IO.StreamReader(file)
fileContents = sReader.ReadToEnd()
response.AppendLine("HTTP/1.1 200 OK")
response.AppendLine("Content-type: text/html") ' You might want to make this dynamical if you are ever going to use this in a more "dynamic" situation
response.Append("Content-Length: ")
response.AppendLine(fileContents.Length.ToString())
response.Append(Environment.NewLine)
response.Append(fileContents)
sReader.Close()
Else
response.AppendLine("HTTP/1.1 404")
response.Append(Environment.NewLine)
End If
Return System.Text.Encoding.UTF8.GetBytes(response.ToString())
End Function
End Class
Why are you defining some variables with Dim and some with Constant, I thought constant was for integers.
No, as of currently, there is only one thread that handles all the host- replying. So during the tiny bit of time it takes to reply to one host, the others will have to wait. You'll have to spawn a new thread directly after the Accept method, pass the new connection to the thread and reply on this separate thread, in order to be able to reply to several hosts at once.Quote:
Originally Posted by samtheman
When you create console applications, Console.WriteLine is used to write one line of text to the standard output stream (that is, the console window).Quote:
Originally Posted by samtheman
Well, it should be no problem to send files the way I showed you in my last post, unless you're planning to send a really large file to the hosts.Quote:
Originally Posted by samtheman
You need to handle the return value of BuildResponse, like this:Quote:
Originally Posted by samtheman
VB.NET Code:
Private Sub doListen() Dim client As System.Net.Sockets.Socket Dim responseBytes() As Byte Do client = listenSocket.Accept() ' When this method returns, "client" will hold the connection to the remote host. ' Send the data here, using the client.Send method. responseBytes = BuildResponse("C:\page.html") client.Send(responseBytes, responseBytes.Length, Net.Sockets.SocketFlags.None) client.Close() Loop End SubWell, since BACKLOG and PORT_NUMBER will not have their values changed anywhere during the applications lifetime, it is good practise to declare them as constants.Quote:
Originally Posted by samtheman
i'm sending maybe 2 kbytes html file and if i want to include images I will just put a path to c:\ in the page.
I do not mean exactly same time but if I opened up two ie windows and opened to localhost://79 would they both load 'eventually'
I am giving the app a test now. Hold on.
Ok, so it functions, great. But if I make a new tab and refresh, maybe 1/3 times it works. othertimes I get incorrect protocol or page cannot be displayed. As it is being used as a host file, it may get more than one redirect per page.
See thats where you'll encounter problems.Quote:
Originally Posted by samtheman
When the browser finds that the HTML document includes images, it will send additional HTTP requests to your server requesting for these images, but since you're responding with the same page every time no matter what the request contained, no images will be returned to the browser.
Yeah, you will be able to request this page how many times you want.Quote:
Originally Posted by samtheman
I'm not including images yet though. Just a html file with connection to server complete.
127.0.0.1 or ip address doesn't work but localhost does. Noticed I get an error unless I specify http:// will this be ok when I apply it to a hosts file.
edit: yes it will.
Are you using port 80?
net Explorer cannot display the webpage
Most likely causes:
You are not connected to the Internet.
The website is encountering problems.
There might be a typing error in the address.
Occurs if I open up more than one 127.0.0.1. Even if done after 5 seconds of previous request, takes a couple of refreshes to fix this. Anyway I can fix this, simply by increasing number of connections to say 10?
Yes I have stopped iis
hmmm...could you post your doListen method for me to have a look at?
Code:Private Sub doListen()
Dim client As System.Net.Sockets.Socket
Dim responseBytes() As Byte
Do
client = listenSocket.Accept() ' When this method returns, "client" will hold the connection to the remote host.
' Send the data here, using the client.Send method.
responseBytes = BuildResponse("C:\page.html")
client.Send(responseBytes, responseBytes.Length, Net.Sockets.SocketFlags.None)
client.Close()
Loop
So you're saying that you can access http://localhost/ once, but the next time it fails? Odd... Try this:
Change your doListen subroutine to this:
And add this subroutine:VB.NET Code:
Private Sub doListen() Dim client As System.Net.Sockets.Socket Dim clientThread As System.Threading.Thread Do client = listenSocket.Accept() ' When this method returns, "client" will hold the connection to the remote host. ' Start a new thread to respond to the client, this will let us ' continue listening for new connections while responding to other hosts. clientThread = New System.Threading.Thread(AddressOf RespondToHost) clientThread.IsBackground = True clientThread.Start(client) Loop End Sub
I find it hard to believe that its the cause, but it might still be busy with the former connection when you try to connect again. This new code will let the server respons to several hosts simultaneously.VB.NET Code:
Private Sub RespondToHost(ByVal obj As Object) Dim resp() As Byte Dim client As System.Net.Sockets.Socket = DirectCast(obj, System.Net.Sockets.Socket) resp = BuildResponse("c:\doc.html") client.Send(resp, resp.Length, Net.Sockets.SocketFlags.None) client.Close() End Sub
testing right now
Nope, still received an error on second refresh. Took 8 refreshes to receive page.What's wierd is once I receive the page I can keep refreshing that tab and never miss a beat.
Problem is that the file is still open maybe?
Ok I will try build app and try on client computer in practice instead of server box.
me.hide or me.visible = 0, or me.visible = false does not make the form invisible.
I need it invisible as I am going to Shell "C:\AppPath" from another program.
You are probably trying to hide it on Form_Load, correct? The form hasnt been displayed when Form_Load is executing so setting Visible to false there isnt going to do much good, as it will be set to True shortly after anyways. You'd need to use the Shown event instead :)
Me.Shown = False
Error 1 'Public Event Shown(sender As Object, e As System.EventArgs)' is an event, and cannot be called directly. Use a 'RaiseEvent' statement to raise an event.
Thinks I am trying to Say Me.Show as in show form.
no, you'll have to handle the event, double-click your form, check the list of event in the upper right corner of the code-area, select Shown in there.Quote:
Originally Posted by samtheman
Thats where you need to set Visible = false.
Done.
So how is it all working for you now? Is it working better on that other computer of yours?
Hi,
Not sure yet as I am installing .NET 3.5 (only had 3 on all my clients). Thank you for all your help, I rated a post of yours, is there a way I can help you in return?
Oh no mate, I'm just happy to help as much as I can. Thanks for the rating :thumb:
Be sure to post here with your results from trying on that other computer.
Perfect. Just one last question, as the application is going to be joined to another. Can I harvest the exe on it's own from the bin release folder. I noticed that most .NET apps use Inno or Nullsoft or their own installer. I have to admit there are no digital signature warnings etc making it better. Point is, can I harvest the exe, will this not make the EXE 'install' but run standalone.
Plus installs do not seem correct with VS2K8, they seem to place inside application data and not C:\Program Files. I have no control over destination with vb installer.
Yes, you can take that EXE and run it without needing to install it, its when you use additional depencies etc that it can be a good idea packaging it in an install package.Quote:
Originally Posted by samtheman
Yeah, thats how it works with the VS installer.Quote:
Originally Posted by samtheman