I am working on a project that have a server, whenever a clients connects it stores its user_id, ip in the dictionary which i have used. When I store the information between the different threads it is working but when I try to access the dictionary from different threads, it's not working well.
Let me clear what my code should do: There is one main thread active and listening for clients, when a clients wants to connect, main thread creates a child thread and that thread gets connected with client, client sends it a user_id, this user_id (as key for dictionary) and Tcpclient (as Value) get stored in dictionary. Further one client sends a message for particular client to server, that message contains the user_id for receiver. Now this client is connected with a particular thread which will check the key(user_id) in dictionary and then send the data to that client but dictionary is not giving the correct value for connected clients it just returns false even that client is connected.
Below is my code example.
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.IO
Public Class Mainform
Dim _server As TcpListener
Dim _listOfClients As New Dictionary(Of String, TcpClient)
Public MessageQueue As New Dictionary(Of String, Queue(Of String))
'Dim ClientData As StreamReader
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Dim port As Integer = 8888
_server = New TcpListener(System.Net.IPAddress.Any, port)
_server.Start()
Threading.ThreadPool.QueueUserWorkItem(AddressOf NewClient)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub NewClient()
Dim client As TcpClient = _server.AcceptTcpClient()
Dim toRec(100000) As Byte
Dim nss As NetworkStream = client.GetStream()
nss.Read(toRec, 0, toRec.Length)
Dim ClientData As String = Encoding.ASCII.GetString(toRec)
MsgBox("Client Connected: " & ClientData)
Dim too() As String
Dim status As Boolean = False
Dim sendto As String
Try
_listOfClients.Add(ClientData, client)
Threading.ThreadPool.QueueUserWorkItem(AddressOf NewClient)
While True
Dim thisClient As String = ClientData
Dim ns As NetworkStream = client.GetStream()
Dim toRecieve(100000) As Byte
ns.Read(toRecieve, 0, toRecieve.Length)
Dim txt As String = Encoding.ASCII.GetString(toRecieve)
'MsgBox(txt)
too = txt.Split("#") 'server receives data in single string where user_id and message is connected with '#'
sendto = String.Copy(too(0)) 'this is the user_id of receiver client
If _listofclients.ContainsKey(sendto) Then
Dim data As String
data = String.Join("#", too)
Dim buffer As Byte() = Encoding.ASCII.GetBytes(data)
Dim nets As NetworkStream = _listofclients(sendto).GetStream()
nets.Write(buffer, 0, buffer.Length)
End If
End While
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
Related
I want to send a file over the internet with a tcp connection. My code handles this for IpV4 well (creddits here go to http://technotif.com/creating-simple-tcpip-server-client-transfer-data-using-c-vb-net/, i just changed minor things to correct the file output)
I tried to use this with a friend of mine, but his router is uteer garbage, and it cant forward any ports whatsoever and wont even work with upnp. It is set to IpV6 as well, and as far as I know IPv6 doesnt need anymore port forwarding since every device has its own public ip.
sadly my program doesnt work with IPv6 adresses, and I have a hard time finding any information regarding this topic.
Here is my code:
Public Class Form1
Private nSockets As ArrayList
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim IPHost As IPHostEntry
IPHost = Dns.GetHostByName(Dns.GetHostName())
lblStatus.Text = "My IP address is " +
IPHost.AddressList(0).ToString()
nSockets = New ArrayList()
Dim thdListener As New Thread(New ThreadStart _
(AddressOf listenerThread))
thdListener.Start()
End Sub
Public Sub listenerThread()
Control.CheckForIllegalCrossThreadCalls = False
Dim tcpListener As New TcpListener(7080)
Dim handlerSocket As Socket
Dim thdstHandler As ThreadStart
Dim thdHandler As Thread
tcpListener.Start()
Do
handlerSocket = tcpListener.AcceptSocket()
If handlerSocket.Connected Then
lbConnections.Items.Add(
handlerSocket.RemoteEndPoint.ToString() +
"connected.")
SyncLock (Me)
nSockets.Add(handlerSocket)
End SyncLock
thdstHandler = New ThreadStart(AddressOf _
handlerThread)
thdHandler = New Thread(thdstHandler)
thdHandler.Start()
End If
Loop
End Sub
Public Sub handlerThread()
Dim handlerSocket As Socket
handlerSocket = nSockets(nSockets.Count - 1)
Dim networkStream As NetworkStream = New _
NetworkStream(handlerSocket)
Dim blockSize As Int16 = 16
Dim thisRead As Int16
Dim dataByte(blockSize) As Byte
SyncLock Me
' Only one process can access the
' same file at any given time
Dim fileStream As Stream
fileStream = File.OpenWrite("C:\Whatever.file")
While (True)
thisRead = networkStream.Read(dataByte,
0, dataByte.Length)
fileStream.Write(dataByte, 0, thisRead)
If thisRead = 0 Then Exit While
End While
fileStream.Close()
networkStream.Close()
End SyncLock
lbConnections.Items.Add("File Written")
handlerSocket = Nothing
End Sub
How do i make it IPv6 capable?
Forgot to put in my client, what do i have to change here to make it work? Since even with the changes to my server, its still not connecting properly.
Private Sub Sendfile()
Dim filebuffer As Byte()
Dim fileStream As Stream
fileStream = File.OpenRead(tbFilename.Text)
' Alocate memory space for the file
ReDim filebuffer(fileStream.Length)
fileStream.Read(filebuffer, 0, fileStream.Length)
' Open a TCP/IP Connection and send the data
Dim clientSocket As New TcpClient(tbServer.Text, 7080)
Dim networkStream As NetworkStream
networkStream = clientSocket.GetStream()
networkStream.Write(filebuffer, 0, fileStream.Length)
networkStream.Close()
End Sub
Your listener is currently listening to IPv4-address 0.0.0.0, which is the default when you only specify a port to the listener.
You need to use the TcpListener(IPAddress, Integer) overload and specify IPv6Any to listen to IPv6-addresses.
Dim tcpListener As New TcpListener(IPAddress.IPv6Any, 7080)
As a side note you should rather use a List(Of T) than an ArrayList. The latter is typeless and not as optimized for .NET as the former.
I have a thread and a socket server for listening to client. Client software is not for me and it is a Laboratory Software that sends data to my program.
when listening starts there is no problem but when the client software is closed and reopened, that can not send any data to my software.
My listener must be run every time like a service.
This is my code:
Delegate Sub WriteMsgHandle(ByVal Msg As String)
Dim handler As WriteMsgHandle
Dim THS As ThreadStart
Dim TH As Thread
Private Sub btnListen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnListen.Click
Try
btnListen.Enabled = False
THS = New ThreadStart(AddressOf Listen)
TH = New Thread(THS)
TH.Start()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Public Sub Listen()
Dim bytesReceived As Integer = 0
Dim recv() As Byte = New Byte(1) {}
Dim clientSocket As Socket
Dim listenerSocket As New Socket _
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Dim IPHost As IPHostEntry = Dns.GetHostEntry(Dns.GetHostName())
Dim localadd As IPAddress = IPAddress.Parse(txt_ip.Text)
Dim ipepServer As IPEndPoint = New IPEndPoint(localadd, txt_port.Text)
handler = AddressOf WriteMsg
listenerSocket.Bind(ipepServer)
listenerSocket.Listen(-1)
clientSocket = listenerSocket.Accept()
Dim msgcount As Integer = 0
If clientSocket.Connected Then
MsgBox("Connected")
Do
bytesReceived = clientSocket.Receive(recv)
Dim Msg As String
Msg = Encoding.ASCII.GetString(recv)
Invoke(handler, Msg)
Loop While bytesReceived <> 0
End If
End Sub
You're only accepting once. You need to accept in a loop.
If clientSocket.Connected Then why did you add this? Delete that check. The socket was just accepted so it is connected. Even if it was disconnected do you want to just ignore that error condition?!
The receive loop is correct.
You probably want to start each accepted client on a new thread (or use async IO).
I have a working TCP / IP server that can listen to one or many clients, it is working great! It can received and send data from one client.
My problem is whenever I clicked the listen button then un-listen by clicking again the button my application freeze. The only way to free my application from this freeze is to connect another client while my system is still in the process of un-listening.
The second problem involves receiving data from multiple clients, yes it can listen and allow multiple clients to be connected to the server but it doesn't received all the messages sent by the client, it only receives the message of the first client.
Here's what my system look like.
And here's my code
Imports System.Net.Sockets
Imports System.Net
Imports System.Threading 'Imports Threading Namespace
Imports System.Text
Imports System.Reflection
Public Class Form1
Dim stream As NetworkStream
Dim client As TcpClient
Dim port As Int32
Dim localAddr As IPAddress = IPAddress.Any
Dim server As TcpListener
Dim tcpClientThread As System.Threading.Thread
Dim PublicIP = String.Empty 'The IP and Port of the Client that connects to port 7700
Private Sub Tcpclient()
port = NUD_Tcp_Port.Value
' The statement of TCPClient function
server = Nothing
' Buffer for reading data
Dim bytes(1024) As Byte
Try
server = New TcpListener(localAddr, port) 'Set the TcpListener on port 13000.
server.Start() 'Start listening for client requests.
writeData(Server_IP_Port) 'Outputs the server's ip and port listening
'Perform a blocking call to accept requests.
'You could also user server.AcceptSocket() here.
client = server.AcceptTcpClient()
writeData("Connected: " & Client_IP_Port())
Dim data As String = Nothing 'The data we received from client, set the default value to nothing
stream = client.GetStream() 'Get a stream object for reading and writing
Dim i As Int32 = stream.Read(bytes, 0, bytes.Length) 'Loop to receive all the data sent by the client.
While (i <> 0)
'Translate data bytes to a ASCII string.
data = Encoding.ASCII.GetString(bytes, 0, i)
writeData("Received: " & data)
'Process the data sent by the client.
data = data.ToUpper()
Dim msg As Byte() = Encoding.ASCII.GetBytes(data)
i = stream.Read(bytes, 0, bytes.Length)
End While
Catch haha As SocketException
Console.WriteLine("SocketException: {0}", haha)
Finally
'server.Stop()
End Try
End Sub
Function Client_IP_Port() As String 'Gets the IP and port number of clients who connected to our server
If PublicIP = String.Empty Then
Try
' Get the clients IP address using Client property
Dim ipend As Net.IPEndPoint = client.Client.RemoteEndPoint
If Not ipend Is Nothing Then
PublicIP = ipend.Address.ToString & " : " & ipend.Port.ToString
End If
Catch ex As System.ObjectDisposedException
PublicIP = String.Empty
Catch ex As SocketException
PublicIP = String.Empty
End Try
End If
Return PublicIP
End Function
Function Server_IP_Port() 'Get the IP and port number of server that it listens
Dim IPListening = IPAddress.Parse(CType(server.LocalEndpoint, IPEndPoint).Address.ToString()).ToString
Dim PortListening = CType(server.LocalEndpoint, IPEndPoint).Port.ToString()
If IPListening = "0.0.0.0" Then
IPListening = "any IP Address"
End If
Return "Listening on " & IPListening & " : " & PortListening
End Function
Private Sub Tcp_Send(Msg_Send As String)
Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(Msg_Send)
stream.Write(sendBytes, 0, sendBytes.Length)
writeData("Sent: " & Msg_Send)
End Sub
Public Sub StopListen() 'Function to telll to the server to stop listening
Try
client.Close()
Catch err As Exception
Console.WriteLine(err)
End Try
tcpClientThread.Abort()
server.Stop()
Btn_Listen.Text = "Listen"
End Sub
Private Sub Btn_Listen_Click(sender As Object, e As EventArgs) Handles Btn_Listen.Click
If Btn_Listen.Text = "Listen" Then
tcpClientThread = New System.Threading.Thread(AddressOf Me.Tcpclient)
tcpClientThread.Start()
Btn_Listen.Text = "Close"
Else
StopListen()
End If
End Sub
Private Sub writeData(ByVal data As Object)
If InvokeRequired Then
Invoke(New Action(Of Object)(AddressOf writeData), data)
Else
RichTextBox1.AppendText(Environment.NewLine & data)
End If
End Sub
Private Sub Btn_Send_Click(sender As Object, e As EventArgs) Handles Btn_Send.Click
Tcp_Send(TB_Tcp_Send.Text)
End Sub
End Class
I'm trying to build a windows service tcpip server to install on some computer to be able to send messages to them...
The following code is working perfectly if I run it as a normal windows application but if I use it to create a windows service it doesn't run as expected.
Throught the Visual studio "attach debug" I can see the debug and every time I send a request from the client I see this:
The thread 0xf34 has exited with code 259 (0x103).
That means the thread was entered but no output, or console.write...
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
Public Class Main
Private serverSocket As TcpListener
Private Delegate Sub WriteMessageDelegate(ByVal msg As String)
Dim listenThread As New Thread(New ThreadStart(AddressOf ListenForClients))
Private Sub ListenForClients()
serverSocket = New TcpListener(IPAddress.Any, 11000)
serverSocket.Start()
Console.WriteLine("Listen for clients...")
While True 'blocks until a client has connected to the server
Dim client As TcpClient = Me.serverSocket.AcceptTcpClient()
Dim clientThread As New Thread(New ParameterizedThreadStart(AddressOf HandleClientComm))
clientThread.Start(client)
End While
End Sub
Private Sub HandleClientComm(ByVal client As Object)
Dim tcpClient As TcpClient = DirectCast(client, TcpClient)
Dim clientStream As NetworkStream = tcpClient.GetStream()
Dim message As Byte() = New Byte(4095) {}
Dim bytesRead As Integer
Console.WriteLine("Handle client comm...")
While True
bytesRead = 0
bytesRead = clientStream.Read(message, 0, 4096) 'blocks until a client sends a message
If bytesRead = 0 Then
Exit While 'the client has disconnected from the server
End If
'message has successfully been received
'Dim encoder As New ASCIIEncoding()
'Dim serverResponse As String = "Response to send"
'Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(serverResponse)
'clientStream.Write(sendBytes, 0, sendBytes.Length)
Console.WriteLine(bytesRead)
'message has successfully been received
Dim encoder As New ASCIIEncoding()
' Convert the Bytes received to a string and display it on the Server Screen
Dim msg As String = encoder.GetString(message, 0, bytesRead)
Console.WriteLine(msg)
'WriteMessage(msg)
End While
tcpClient.Close()
End Sub
Private Function BytesToString(
ByVal bytes() As Byte) As String
Return Encoding.Default.GetString(bytes)
End Function
Private Sub WriteMessage(ByVal msg As String)
If Me.MessagesLog.InvokeRequired Then
Dim d As New WriteMessageDelegate(AddressOf WriteMessage)
Me.MessagesLog.Invoke(d, New Object() {msg})
Else
Me.MessagesLog.AppendText(msg & Environment.NewLine)
End If
End Sub
Protected Overrides Sub OnStart(ByVal args() As String)
listenThread.Start()
Console.WriteLine("Starting...")
End Sub
Protected Overrides Sub OnStop()
' Add code here to perform any tear-down necessary to stop your service.
'listenThread.Abort()
End Sub
End Class
Can someone help me?
Found the problem...
Windows services dont do output to console.write()... it has to be with debug.print()
"The Thread..." output is normal..
Thank you,
AP
I'm basically trying to write a spam filter for incoming email on a mail server. I'd like to write a VB.NET program that can listen for any incoming mail on port 25 and then run my script on it and then pass it to the mail server running on a different port.
What do I need to do to have my program just sit and wait for a message to come in on port 25 and then react to it?
Thanks.
Here, as an example, is part of a socket listening service I modified from a tutorial a while ago in VB.NET. Basically, a socket listens for traffic on port 25 when the service is started, accepts a connection and then assigns that connection to a new thread, sends a response, and then closes the TCP connection.
Dim serverSocket As New TcpListener(IPAddress.Any, "25")
Dim ipAddress As System.Net.IPAddress = System.Net.Dns.Resolve(System.Net.Dns.GetHostName()).AddressList(0)
Dim ipLocalEndPoint As New System.Net.IPEndPoint(IPAddress, 25)
Protected Overrides Sub OnStart(ByVal args() As String)
Dim listenThread As New Thread(New ThreadStart(AddressOf ListenForClients))
listenThread.Start()
End Sub
Protected Overrides Sub OnStop()
' Add code here to perform any tear-down necessary to stop your service.
End Sub
Private Sub ListenForClients()
serverSocket = New TcpListener(ipLocalEndPoint)
serverSocket.Start()
While True
Dim client As TcpClient = Me.serverSocket.AcceptTcpClient
Dim clientThread As New Thread(New ParameterizedThreadStart(AddressOf HandleClientComm))
clientThread.Start(client)
End While
End Sub
Private Sub HandleClientComm(ByVal client As Object)
Dim tcpClient As TcpClient = DirectCast(client, TcpClient)
Dim clientStream As NetworkStream = tcpClient.GetStream
Dim message As Byte() = New Byte(4095) {}
Dim bytesRead As Integer
While True
If (bytesRead = 0) Then
Exit While
End If
Dim encoder As New asciiencoding()
Dim serverResponse As String = "Response to send"
'Response to send back to the testing client
Dim sendBytes As [Byte]() = encoding.ascii.getbytes(serverResponse)
clientStream.Write(sendBytes, 0, sendBytes.Length)
End While
tcpClient.Close()
End Sub