Threading issue with TCP? - vb.net

I've written a Windows-based TCP server program based on some VB code I found on the internet several years ago (I can't find the link now, but it was called "multi-client server program" or something like that).
The server communicates with a couple of Enterprise iPhone client apps that I have also developed. I've successfully incorporated this code into two separate server programs that work just fine on both the development server and the production server. I'm working on a third iOS client application and a corresponding server program, which works fine on the development machine, but will not work on the production server -- the same machine that hosts the other two server programs with no problem.
It was working for a while, but as I have added more functionality to the server class, it seems to have stopped processing the incoming data, but only on the production machine.
The code that performs the connection functions is contained in a separate public class which is supposed to communicate with the Windows form that processes the incoming data. Using msgbox's for debugging tools, I have been able to confirm that the Client Connection class is connecting and is receiving the data, but it for some reason will not communicate that data with the Windows form.
My only thought is that it must be a threading issue, but I am not sure, and I have no idea how to find out.
To recap, just to be clear:
The code works fine on the development server, but not on the production server.
The client connection class is identical in every way with the other two working server programs.
That the client is communicating with the client connection class has been confirmed. The incoming data can be captured inside the connection class and displayed in msgbox's, so the data is getting through.
The Windows class that processes the incoming data is not receiving the data from the public client connection class.
EDIT: I should have included this in the original post: The development server is Win 7; the production sever is Windows Server 2012.
Because of the complexity of this code, I am not sure what snippets would be applicable for this, but I'll do my best to include what makes most sense to me here.
This is the entirety of the client connection class with the exception of the method that sends outgoing data. Again, this was copied from a website several years ago, and the comments are those of the original developer:
Imports System.IO
Imports System.Net.Sockets
Imports System.Data.SqlClient
Public Class ConnectedClient
Private cli As TcpClient 'declare a tcp client which will be the client that we assign to an instance of this class
Private uniqueid As String 'this will be used for the name property
Dim strErrorLogPath As String
Public Property name ''This will be the name of the ID containing its Unique ID
Get
Return uniqueid 'when we want to get it, it will return the Unique ID
End Get
Set(ByVal value)
uniqueid = value 'Used for setting the name
End Set
End Property
Sub New(ByVal client As TcpClient)
Dim r As New Random 'create a new random to serve as way to create our unique ID
Dim x As String = String.Empty 'declare a new variable to hold the ID
For i = 0 To 7 'we are going to have an ID of 7 randomly generated characters
x &= Chr(r.Next(65, 89)) 'create a generate dnumber between 65 and 89 and get the letter that has the same ascii value (A-Z)
' and add it onto the ID string
Next
Me.name = client.Client.RemoteEndPoint.ToString().Remove(client.Client.RemoteEndPoint.ToString().LastIndexOf(":")) & " - " & x 'set the name to the Unique ID
cli = client 'assign the client specified to the TCP client variable to we can operate with it
cli.GetStream.BeginRead(New Byte() {0}, 0, 0, AddressOf read, Nothing) 'start reading using the read subroutine
End Sub
Public Event gotmessage(ByVal message As String, ByVal client As ConnectedClient) 'this is raised when we get a message from the client
Public Event disconnected(ByVal client As ConnectedClient) 'this is raised when the client disconnects
Sub read(ByVal ar As IAsyncResult) 'this will process all messages being received
'bn-note: This is the entry point of the data being received from the client.
Try
Dim sr As New StreamReader(cli.GetStream) 'initialize a new streamreader which will read from the client's stream
Dim msg As String = sr.ReadLine() 'create a new variable which will be used to hold the message being read
If msg = "" Then
RaiseEvent disconnected(Me) 'WE CAN ASSUME THE CLIENT HAS DISCONNECTED
Exit Try
'msg = "Null Message"
End If
WriteToRawIncomingDataLog(msg)
RaiseEvent gotmessage(msg, Me) 'tell the server a message has been received. Me is passed as an argument which represents
' the current client which it has received the message from to perform any client specific
' tasks if needed
cli.GetStream.BeginRead(New Byte() {0}, 0, 0, AddressOf read, Nothing) 'continue reading from the stream
'End Ifz
'Catch ex As System.NullReferenceException
Catch ex As Exception
Try 'if an error occurs in the reading purpose, we will try to read again to see if we still can read
Dim sr As New StreamReader(cli.GetStream) 'initialize a new streamreader which will read from the client's stream
Dim msg As String = sr.ReadLine() 'create a new variable which will be used to hold the message being read
WriteToRawIncomingDataLog(msg)
RaiseEvent gotmessage(msg, Me) 'tell the server a message has been received. Me is passed as an argument which represents
' the current client which it has received the message from to perform any client specific
' tasks if needed
cli.GetStream.BeginRead(New Byte() {0}, 0, 0, AddressOf read, Nothing) 'continue reading from the stream
'End If
'Catch ex2 As System.NullReferenceException
' Stop
Catch ' IF WE STILL CANNOT READ
RaiseEvent disconnected(Me) 'WE CAN ASSUME THE CLIENT HAS DISCONNECTED
End Try
End Try
End Sub
Here is the Windows form code that processes the incoming data:
Private Sub formMain_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Try
Dim listener As New System.Threading.Thread(AddressOf listen) 'initialize a new thread for the listener so our GUI doesn't lag
listener.IsBackground = True
listener.Start(CInt(IncomingPortString)) 'start the listener, with the port specified as a parameter (textbox1 is our port textbox)
Catch ex As Exception
txtSystemMessages_AddText(String.Format("Error in formMain_Load sub: {0}{1}", ex.Message.ToString, vbNewLine))
End Try
End Sub
Sub listen(ByVal port As Integer)
Try
Dim t As New TcpListener(IPAddress.Any, port) 'declare a new tcplistener
t.Start() 'start the listener
Do
Dim client As New ConnectedClient(t.AcceptTcpClient) 'initialize a new connected client
AddHandler client.gotmessage, AddressOf received 'add the handler which will raise an event when a message is received
AddHandler client.disconnected, AddressOf disconnected 'add the handler which will raise an event when the client disconnects
Loop Until False
Catch ex As Exception
txtSystemMessages_AddText(String.Format("Error in Listen sub: {1}{2}", ex.Message.ToString, vbNewLine))
End Try
End Sub
Sub received(ByVal msg As String, ByVal client As ConnectedClient)
Try
If Not clients.ContainsKey(client) Then
clients.Add(client, client.name.ToString) 'add the client to our hashtable
End If
Catch ex As ArgumentException
End Try
(The sub that processes the incoming data string "msg".)
End Sub
I'm at a complete loss to know what could be causing this issue, and a threading issue is all that I can think of. Could a different machine have different threading schemes? Any help would be greatly appreciated.

Related

Why is my TCP connection closing?

I have developed an application for my game server. Now, in this application when I press "Connect" it sends data to my Game Server. And it does, but, the problem is, when it sends the connection it automatically closes it, and I don't want to close it because I have a socket plugin that kills the TCP connection after player leaves the game. Now on my localhost it works, the TCP doesn't "die" but on my vps it disconnects, can someone please check my code and see if I'm doing something wrong?
Dim p() As Process
Dim gta() As Process
p = Process.GetProcessesByName("samp")
gta = Process.GetProcessesByName("gta_sa")
If p.Count > 0 Then
MsgBox("Vec imate pokrenut SAMP - ugasite ga.")
ElseIf gta.Count > 0 Then
MsgBox("Vec imate pokrenut GTA San Andreas - ugasite ga.")
Else
Try
Dim prozess As Process = Process.GetProcessesByName("samp")(0)
prozess.Kill()
Catch ex As Exception
End Try
My.Computer.Registry.SetValue("HKEY_CURRENT_USER\Software\SAMP", "PlayerName", TextBox1.Text)
Process.Start("samp://164.132.229.172:7777")
Dim client As New TcpClient()
client.Connect("164.132.229.172", 7775)
Dim sendBytes As [Byte]() = System.Text.Encoding.ASCII.GetBytes(TextBox1.Text)
Dim stream As NetworkStream = client.GetStream()
stream.Write(sendBytes, 0, sendBytes.Length)
Timer1.Start()
End If
End If
Timer:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim pd() As Process
pd = Process.GetProcessesByName("Aimbot By The2Gamers")
If pd.Count > 0 Then
Dim InternetExplorer() As Process = Process.GetProcessesByName("Aimbot By The2Gamers")
For Each Process As Process In InternetExplorer
Process.Kill()
Next
End If
End Sub
Now this part down here is only server log from my vps:
[01:12:15] [LAUNCHER] Connection to Socket Server. | ClientID: [0] |
ClientIP: [92.241.153.29] [01:12:15] Remote client [0] has sent:
Joan_Mackey [01:12:16] [LAUNCHER] Player Socket disconnected|
ClientID: [0] | PlayerID: [0]
You should move the Dim client As New TcpClient() initialization to class level. Class level means that you put it outside any method (that is, outside any Sub or Function).
As it stands, your TcpClient is collected by the Garbage Collector after you've exited whatever method you put it in. After you've passed End Sub the TcpClient is technically no longer used, because you cannot access that specific instance anymore. The Garbage Collector checks for this when it runs, and as your variable is no longer used it will be collected.
When the Garbage Collector collects an object it starts releasing the object's unused resources. If the object (or any child object) implements the IDisposable interface, the Garbage Collector will first call that object's Dispose() method.
TcpClients are built on top of the System.Net.Sockets.Socket class. The Socket class implements IDisposable which means it has got a Dispose() method. The Garbage Collector will call this method for the underlying socket of your TcpClient. When it is called, the socket will automatically shut itself down and tell the endpoint that it's disconnecting - and this is what you are experiencing.
So to summarize:
The TcpClient is no longer used after you pass End Sub.
When the Garbage Collector runs it will start releasing the TcpClient's resources, and call Dispose() on the underlying socket.
The underlying socket will then tell the endpoint that it's disconnecting, and then it will terminate the connection.
Now your connection to the server isn't open anymore.

Constantly losing TCPClient connection from application

I have an application which connects to a Zebra QLn420 label printer through a TCPClient connection to the printer's static IP address and port number.
We have been having some issues with the software "stalling" and skipping over some of the labels, and after investigating (by adding some logging capabilities to the software to write out to a text file each time it checks the connection and actually reconnects) I have noticed that the connection does not seem to stay open for more than one second (not a solid number, it can vary from less than a second to 5 seconds or more from my tests).
While testing at my desk, this is almost a non-issue because the signal strengths are so strong that it reconnects instantly, but out in the warehouse where this is actually used, in some areas the signal isn't so strong. The function which handles the connection will try to reconnect for up to 5 seconds twice, then display an error message and ask if they want to retry connecting.
I'm curious if anyone has experienced anything like this, and what can be done to resolve it. I understand that the software will lose connection with the printer occasionally, especially in the weaker signal areas. But I would like to find a way to keep the connection open until either I close it or the signal is too weak to keep it going, as I feel this has a lot to do with the "missing" labels and definitely impacts the speed of the software.
Below is my connection code (a combination of my own code and some snippets found online):
Public Class LabelPrinter
Private strIP as String = "xxx.xxx.xxx.xxx"
Private intPort As Integer = "6101"
Private client As System.Net.Sockets.TcpClient
Private blnConnected As Boolean = False
Private blnValidIP As Boolean = False
Private intTimeoutLength As Integer = 5000
Private TimeoutTime As New Timers.Timer
Private clntSockParams As ClientSocketParameters
Private Structure ClientSocketParameters
Public addrs As String
Public prt As Integer
End Structure
Public Sub New(Picker As Picker, newIP As String, newPort As Integer, Optional PrinterTimeout As Integer = 5000)
If newIP <> "" Then strIP = newIP
If newPort <> 0 Then intPort = newPort
intTimeoutLength = PrinterTimeout
If newIP = "" Or newPort = 0 Then Exit Sub
Dim ipAddress As System.Net.IPAddress = Nothing
If Not System.Net.IPAddress.TryParse(strIP, ipAddress) Then Exit Sub
End Sub
Public Function Connect() As Boolean
Try
'connect to printer via TcpClient, need ip address and port number
'connects without thread, hangs program for 10-20 seconds if printer is not turned on, replaced with code below to thread the connection and set timeout
'If client Is Nothing OrElse Not client.Connected Then
' client = New System.Net.Sockets.TcpClient
' client.Connect(strIP, intPort)
'End If
'RRB 02/10/15 - added for loop to try to connect twice each attempt instead of only once
For i As Integer = 1 To 2
If client Is Nothing OrElse Not client.Connected Then
'uses ClientSocketParameters structure to pass to recursive function ConnectionReturned()
clntSockParams = New ClientSocketParameters
clntSockParams.addrs = strIP
clntSockParams.prt = intPort
'create client and call BeginConnect (attempts to connect on separate thread until TimeoutTime has elapsed)
client = New System.Net.Sockets.TcpClient
client.SendTimeout = intTimeoutLength
client.ReceiveTimeout = intTimeoutLength
'setup timer with timeout length and start, if timer goes past intTimeoutLength, the Timeout() function is called which closes everything and leaves client = Nothing
AddHandler TimeoutTime.Elapsed, AddressOf Timeout
TimeoutTime.Interval = intTimeoutLength
TimeoutTime.Start()
client.BeginConnect(strIP, intPort, New AsyncCallback(AddressOf ConnectionReturned), clntSockParams)
'keeps the program from doing anything else until BeginConnect either succeeds or fails (due to connect on separate thread)
Do While TimeoutTime.Enabled
System.Threading.Thread.Sleep(500)
Loop
End If
'if TimeoutTime is elapsed and client is Nothing, connection didn't happen, throw an error
If client Is Nothing Then
blnConnected = False
Else
blnConnected = True
Exit For
End If
Next
Catch ex As Exception
blnConnected = False
End Try
Return blnConnected
End Function
Private Sub ConnectionReturned(ByVal ar As System.IAsyncResult)
'this method is called from the client.BeginConnect line in Connect(), make sure timer is running
If TimeoutTime.Enabled Then
'ensure client is initialized
If client Is Nothing Then client = New System.Net.Sockets.TcpClient
'keep calling ConnectionReturned until client.Connected is true
If client.Connected Then
TimeoutTime.Stop()
Else
Dim actualParameters As ClientSocketParameters = DirectCast(ar.AsyncState, ClientSocketParameters)
client.BeginConnect(actualParameters.addrs, actualParameters.prt, New AsyncCallback(AddressOf ConnectionReturned), clntSockParams)
End If
End If
End Sub
Private Sub Timeout(ByVal sender As Object, ByVal e As EventArgs)
'this method is only called if TimeoutTime elapsed, which means no connection was made. close the client object if needed, set to Nothing, and stop TimeoutTime
If TimeoutTime.Enabled Then
Try
client.Close()
Catch ex As Exception
End Try
client = Nothing
TimeoutTime.Stop()
End If
End Sub
Public Sub Disconnect()
'need to make sure StreamWriter connection and TcpClient connection to printer are closed
Try
client.Close()
Catch ex As Exception
End Try
client = Nothing
blnConnected = False
End Sub
End Class
Please let me know if more information is needed. I'm also open to alternative connection types, so long as the static IP and port can be used (over wifi connection).
EDIT: I've modified the code in my program to use the System.Net.Socket class, and the connection seems to hold steady in my initial tests. What would cause this connection method to work where TCPClient doesn't seem to, in the same location?

UDP local broadcast

I'm working on a remote control tool. The client runs a program to locally send commands to servers in order to control them.
However, the client doesn't know the server's IP address and vice versa.
I decided to use UDP broadcasting (please tell me if there's a better way to do this, I tried using multicast but I didn't really understand it). When started, the client (which controls the servers) broadcasts a message to tell the servers that a new client connected. Then (or when the server is started), the servers broadcast their own IP addresses. When the client receives an IP address, it tries to connect via TCP.
Unfortunately, I ran into problems with that. I randomly got An existing connection was forcibly closed by the remote host exceptions and I wasn't able to find out why.
The exception occurred in my client program when listening for UDP broadcasts.
Now, I'm looking for a better way to find the clients.
Should I use broadcast or multicast?
How would I implement that?
EDIT: It wouldn't be a problem to use multiple ports. However, I need to be able to run a client AND a server on a single computer.
Here's the code I was using
Client (controls servers)
'Variables
Private UdpBroadcaster As UdpClient
Private UdpBroadcasterEndpoint As New IPEndPoint(IPAddress.Broadcast, 4334)
'Sub New()
Try
UdpBroadcaster = New UdpClient(4333)
UdpBroadcaster.EnableBroadcast = True
Catch
MsgBox("Error creating UDP client! Port already in use?", ...)
End Try
'Called when the application starts
Private Sub StartUdpListener()
Dim ListenerUdp As New Thread(AddressOf UdpListener)
ListenerUdp.IsBackground = True
ListenerUdp.Start()
End Sub
'Started as thread in StartUdpListener()
Private Sub UdpListener()
Try
Do
'The next line fails with the error I described (An existing connection was forcibly closed by the remote host)
Dim ReceivedBytes() As Byte = UdpBroadcaster.Receive(UdpBroadcasterEndpoint)
Dim ReceivedString As String = System.Text.Encoding.UTF32.GetString(ReceivedBytes)
'The following three lines will just connect to the received hostname
Dim ScanThread As New Thread(Sub() ScanSingle(ReceivedString))
ScanThread.IsBackground = True
ScanThread.Start()
Loop
Catch
If Not UdpBroadcaster Is Nothing Then
UdpBroadcaster.Close()
UdpBroadcaster = Nothing
End If
InvokeStatus("UDP connection lost, please try again later.")
End Try
End Sub
'Called when the application starts and when the user manually clicks the "UDP Scan" button
Private Sub StartBroadcastUdpThread()
Dim UdpBroadcastThread As New Thread(Sub() BroadcastUdp())
UdpBroadcastThread.IsBackground = True
UdpBroadcastThread.Start()
End Sub
'Started as thread in StartBroadcastUdpThread()
Private Sub BroadcastUdp()
If UdpBroadcaster Is Nothing Then
Try
UdpBroadcaster = New UdpClient(4333)
UdpBroadcaster.EnableBroadcast = True
Catch
MsgBox("Error creating UDP Client.", MsgBoxStyle.Critical, "Error")
Application.Exit()
Return
End Try
End If
Dim BroadcastBytes() As Byte = System.Text.Encoding.UTF32.GetBytes("Client-Identify")
UdpBroadcaster.Send(BroadcastBytes, BroadcastBytes.Length, UdpBroadcasterEndpoint)
InvokeStatus("UDP request sent successfully")
End Sub
Servers (controlled by client)
'Variables
Private UdpBroadcaster As UdpClient
Private UdpBroadcasterEndpoint As New IPEndPoint(IPAddress.Broadcast, 4333)
'Main method
Public Sub Main()
Try
UdpBroadcaster = New UdpClient(4334)
UdpBroadcaster.EnableBroadcast = True
StartUdpListener()
StartBroadcastUdpThread()
Catch
Console.WriteLine("Failed to create server. Port already in use?")
End Try
End Sub
'Called in Main()
Private Sub StartUdpListener()
Dim ListenerUdp As New Thread(AddressOf UdpListener)
ListenerUdp.IsBackground = True
ListenerUdp.Start()
End Sub
'Started as thread in StartUdpListener()
Private Sub UdpListener()
Try
Do
Dim ReceivedBytes() As Byte = UdpBroadcaster.Receive(UdpBroadcasterEndpoint)
Dim ReceivedString As String = System.Text.Encoding.UTF32.GetString(ReceivedBytes)
If ReceivedString.Equals("Client-Identify") Then
StartBroadcastUdpThread()
End If
Loop
Catch
If Not UdpBroadcaster Is Nothing Then
UdpBroadcaster.Close()
End If
End Try
End Sub
'Called when the application is started or a "Client-Identify" command is received
Private Sub StartBroadcastUdpThread()
Dim UdpBroadcastThread As New Thread(Sub() BroadcastUdp())
UdpBroadcastThread.IsBackground = True
UdpBroadcastThread.Start()
End Sub
'Started as thread in StartBroadcastUdpThread()
Private Sub BroadcastUdp()
Dim BroadcastBytes() As Byte = System.Text.Encoding.UTF32.GetBytes(Dns.GetHostName)
UdpBroadcaster.Send(BroadcastBytes, BroadcastBytes.Length, UdpBroadcasterEndpoint)
End Sub
Thanks in advance!
Thank you for your answers. I fixed it by removing the feature to manually call StartBroadcastUdpThread() in my client.
I still don't understand why this happens though. I use exactly the same code for both client and server, except the ports are swapped. The TCP server doesn't crash even if the StartBroadcastUdpThread() method is called multiple times, the client does. By the way, the problem occurs regardless of whether the client or server is started first.
Even if I don't really understand why broadcasting the second time stops the client from receiving broadcasts - it's fixed for now. Thanks for you help!
I would suggest using Zeroconf to find the server and clients, and then use a TCP socket to communicate between the two. You can see an example implementation on key-value pair zeroconf announcements here: https://github.com/Eyescale/Lunchbox/blob/master/lunchbox/servus.cpp
Minimal UDP server basis:
Imports System.Threading
Shared client As UdpClient
Shared receivePoint As IPEndPoint
client = New UdpClient(2828) 'Port
receivePoint = New IPEndPoint(New IPAddress(0), 0)
Dim readThread As Thread = New Thread(New ThreadStart(AddressOf WaitForPackets))
readThread.Start()
Public Shared Sub WaitForPackets()
While True
Dim data As Byte() = client.Receive(receivePoint)
Console.WriteLine("=" + System.Text.Encoding.ASCII.GetString(data))
End While
End Sub

Visual Basic UDPClient Server/Client model?

So I'm trying to make a very simple system to send messages from a client to a server (and later on from server to client as well, but baby steps first). I'm not sure exactly how to use UDPClient to send and receive messages (especially to receive them), mostly because I don't have anything triggering the ReceiveMessage() function and I'm not sure what would.
Source Code is at this link, go to File>Download. It is already built if you want to just run the exe.
So my question is basically: How can I easily use UDPClient, how can I get this system to work and what are some tips for executing this kind of connection? Anything I should watch out for (threading, issues with code,etc)?
Source.
You need first need to set up two UdpClients. One client for listening and the other for sending data. (You'll also need to pick a free/unused port number and know the IP address of your target - the machine you want to send data to.)
To set up the receiver,
Instantiate your UdpClient variable with the port number you chose earlier,
Create a new thread to avoid blocking while receiving data,
Loop over the client's receive method for as long as you want to receive data (the loop's execution should be within the new thread),
When you receive one lot of data (called a "packet") you may need to convert the byte array to something more meaningful,
Create a way to exit the loop when you want to finish receiving data.
To set up the sender,
Instantiate your UdpClient variable with the port number you chose earlier (you may want to enable the ability to send broadcast packets. This allows you to send data to all listeners on your LAN),
When you need to transmit data, convert the data to a byte array and then call Send().
I'd suggest that you have a quick skim read through this.
Here's some code to get you started off...
'''''''''''''''''''''''Set up variables''''''''''''''''''''
Private Const port As Integer = 9653 'Port number to send/recieve data on
Private Const broadcastAddress As String = "255.255.255.255" 'Sends data to all LOCAL listening clients, to send data over WAN you'll need to enter a public (external) IP address of the other client
Private receivingClient As UdpClient 'Client for handling incoming data
Private sendingClient As UdpClient 'Client for sending data
Private receivingThread As Thread 'Create a separate thread to listen for incoming data, helps to prevent the form from freezing up
Private closing As Boolean = False 'Used to close clients if form is closing
''''''''''''''''''''Initialize listening & sending subs'''''''''''''''''
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
InitializeSender() 'Initializes startup of sender client
InitializeReceiver() 'Starts listening for incoming data
End Sub
''''''''''''''''''''Setup sender client'''''''''''''''''
Private Sub InitializeSender()
sendingClient = New UdpClient(broadcastAddress, port)
sendingClient.EnableBroadcast = True
End Sub
'''''''''''''''''''''Setup receiving client'''''''''''''
Private Sub InitializeReceiver()
receivingClient = New UdpClient(port)
Dim start As ThreadStart = New ThreadStart(AddressOf Receiver)
receivingThread = New Thread(start)
receivingThread.IsBackground = True
receivingThread.Start()
End Sub
'''''''''''''''''''Send data if send button is clicked'''''''''''''''''''
Private Sub sendBut_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles sendBut.Click
Dim toSend As String = tbSend.Text 'tbSend is a textbox, replace it with whatever you want to send as a string
Dim data() As Byte = Encoding.ASCII.GetBytes(toSend)'Convert string to bytes
sendingClient.Send(data, data.Length) 'Send bytes
End Sub
'''''''''''''''''''''Start receiving loop'''''''''''''''''''''''
Private Sub Receiver()
Dim endPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, port) 'Listen for incoming data from any IP address on the specified port (I personally select 9653)
While (True) 'Setup an infinite loop
Dim data() As Byte 'Buffer for storing incoming bytes
data = receivingClient.Receive(endPoint) 'Receive incoming bytes
Dim message As String = Encoding.ASCII.GetString(data) 'Convert bytes back to string
If closing = True Then 'Exit sub if form is closing
Exit Sub
End If
End While
End Sub
'''''''''''''''''''Close clients if form closes''''''''''''''''''
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
closing = True 'Tells receiving loop to close
receivingClient.Close()
sendingClient.Close()
End Sub
Here are a few other exmples: Here, here, here and here.
Imports System.Threading
Shared client As UdpClient
Shared receivePoint As IPEndPoint
client = New UdpClient(2828) 'Port
receivePoint = New IPEndPoint(New IPAddress(0), 0)
Dim readThread As Thread = New Thread(New ThreadStart(AddressOf WaitForPackets))
readThread.Start()
Public Shared Sub WaitForPackets()
While True
Dim data As Byte() = client.Receive(receivePoint)
Console.WriteLine("=" + System.Text.Encoding.ASCII.GetString(data))
End While
End Sub

Issues Sending messages with TCPClient in vb.net

I'm realizing a .NET chat application but i still have that error:
I can send only a message per connection.
For example. With the code below, i can send only one message that can be received correctly by the other peer, but if i send another message message, on the same connection,it won't be received by the remote PC.
Here is the code:
Dim client_TCP As New TcpClient
Private Sub send_obj(ByVal obj As Object)
Dim bf As New BinaryFormatter
Dim tosend As Packet
tosend.data = obj
bf.Serialize(client_TCP.GetStream(), tosend)
client_TCP.GetStream.Flush()
End Sub
Private Sub connect_to_port()
Try
client_TCP = New TcpClient(client_data.getIP(), client_data.getPort())
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub disconnect_from_port()
client_TCP.Close()
End Sub
And here is the listener:
Private Sub Timer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timer.Tick
If client_TCP_listener.Pending = True Then
....
End If
End Sub
So, to send a message I always need to do this (example):
Dim b As Byte
b = 1
disconnect_from_port()
connect_to_port()
client_TCP.GetStream().WriteByte(b)
client_TCP.GetStream().Flush()
I tried to put\remove the flush from both the code. Nothing happened.
Have you got any ideas?!
How do you know that it is not received? Did you try emulating remote host with your own code?
TCP is a stream protocol that means that you can send two bytes doing two separate calls to client_TCP.GetStream().WriteByte(b) and the remote party can receive those 2 bytes using one Receive call. You should not make any assumptions on the I/O API call patterns (number of writes and number of receives) but analyze the data you're sending receiving via stream connection.
So to send messages using stream protocol you have to introduce the notion of the application protocol. For instance [2bytes-size][size-bytes of message] - which means that if we want to send "hello" message we at first will send 2 bytes containing the size of the "hello" string and then the string itself.
make sure that receiving end is also using .net BinaryFormatter for deserlizing the object.