Cannot get port to close - vb.net

I am trying to fix an app that uses TCP to receive files. Unfortunately, I do not have the source code for the sending application. The problem that I am having is that after the first file is received, the second one is sent by the sending application, but it is not being picked up by the receiving application.
I believe the issue is that the socket is not being closed after receiving the file. I have a method that should close it, but _socket.Connected = false, so nothing is done. However, if I check the port, it is still bound, even after the socket is closed.
Private Sub CloseSocket(ByVal disconnect As Boolean)
If Not (_socket Is Nothing) Then
If (_socket.Connected = True) Then
_socket.Shutdown(SocketShutdown.Both)
If(disconnect) Then
_socket.Disconnect(True)
End If
End If
_socket.Close()
_socket = Nothing
End If
End Sub
I realize that I have not included much code, but the Listen method is quite large and convoluted. I can get additional code if it will provide insight. Any assistance would be greatly appreciated.
EDITED
The code that is used to check the port status is below:
Private Shared Function TcpIpGetPortStatus(ByVal port As Int32) As String
Dim properties As NetworkInformation.IPGlobalProperties
Dim listeners As Net.IPEndPoint()
Dim local As Net.IPEndPoint
Dim connections As NetworkInformation.TcpConnectionInformation()
Dim t As NetworkInformation.TcpConnectionInformation
Dim portStatus As String
portStatus = "Disconnected"
properties = NetworkInformation.IPGlobalProperties.GetIPGlobalProperties()
listeners = properties.GetActiveTcpListeners()
Try
' Cycle through all listening TCP connections and find the one that is associated with port.
For Each local In listeners
If (local.Port = port) Then
portStatus = "Connected"
Exit For
End If
Next local
' Port wasn't in the listening state so check if it is established.
If (portStatus = "Disconnected") Then
properties = NetworkInformation.IPGlobalProperties.GetIPGlobalProperties()
connections = properties.GetActiveTcpConnections()
' Cycle through all active TCP connections and find the one that is associated with port.
For Each t In connections
If (t.LocalEndPoint.Port = port) Then
Select Case t.State
Case NetworkInformation.TcpState.Established
portStatus = "Connected"
Exit For
End Select
End If
Next t
End If
Catch ex As Exception
' Handle Exception...
End Try
Return portStatus
End Function
This function will return "Connected" when called. I've traced it through, and found that the port I was using was still bound. Again, thank you for all help.
ADDITION
I just ran this between two separate systems, using WireShark to capture the data. There is a Sender and Receiver that I do not have sourcecode for, and am trying to integrate with, and the Sender and Receiver that I am updating the code to get it to communicate properly with the existing ones. The stream sent is identical in both cases (except for datetime in the ACK). If I send a second message from the existing sender to the Receiver being upgraded, the message is sent to the port, but the Receiver in development is never notified, which hangs both programs.

After pouring over the code that was provided to me, I finally realized that it was closing and disconnecting the wrong socket. Rather than calling Shutdown and Disconnect on the socket that was used to receive the message, it was called on the listening socket.
Once i realized this, I was able to close the correct socket, and the application began to work. Now I just need to go through and correct all of the issues that this caused with the underlying code, and things should be good.
Thank you to all of the people who responded. You got me thinking in the right direction.

Related

TCP Client to Server communication

All I'm looking for is a simple TCPClient/Listner example on Windows Form VB.Net. I'm a newbie and Microsoft TCPClient/Listner class examples are not what I am looking for. All I am looking is for the TCPClient to send a message and for a TCPListener to get the message and to send a message back "I got your message" ?
A little help would be great. I have some codes, but is only to send message to server and not back from server to client..
Any help will be very appreciated..
TCP communication is stream-based, which means it doesn't handle any packets. Due to this, messages that you receive might be either partial or lumped together.
You could for example send:
Hello!
How are you?
But you might receive:
Hello!How are you?
or:
Hello!How ar
e you?
(or something similar)
To fix this you must apply something called "length-prefixing". Length-prefixing (or length prefixing) means that before you send a message, you put its length (amount of characters/bytes) in the beginning of it. By doing so, the endpoint will know exactly how many bytes to read for each message. Thus there will be no problems with messages being partial or lumped together.
This is not the most straightforward thing to do as a beginner, as to get it to work properly on both sides you have to structure your code just right. So I've created two classes that will take care of this for you. See the examples below on how to use them for simple text message-based communication.
Link to source: http://www.mydoomsite.com/sourcecodes/ExtendedTcpClient.zip
Link to C# source : http://www.mydoomsite.com/sourcecodes/ExtendedTcpClient%20CSharp.zip
EDIT (2019-11-08)
Some time ago I made an upgraded version of this with a bit better code structure and error handling. For those of you interested, the new code can be downloaded here (VB.NET only):
https://www.mydoomsite.com/sourcecodes/ExtendedTcpClient%202.0.zip
Example usage
Note that in those examples Client does not refer to the client side, but to the TcpClient.
Server side
First declare a new variable for ExtendedTcpClient, and be sure to
include WithEvents in the declaration.
Dim WithEvents Client As ExtendedTcpClient
Then you will need a TcpListener and a Timer to check for incoming connections.
Dim Listener As New TcpListener("0.0.0.0", 5555) 'Listen for any connection on port 5555.
Dim WithEvents Tmr As New System.Windows.Forms.Timer
Then you need to subscribe to the timer's Tick event.
Private Sub Tmr_Tick(sender As System.Object, e As System.EventArgs) Handles Tmr.Tick
End Sub
In there you check for incoming connections via the Listener.Pending() method. When you are to accept a connection you first declare a new
instance of the ExtendedTcpClient. The class requires to have a
form as its owner, in this application Me is the current form.
Then you use the ExtendedTcpClient.SetNewClient() method with
Listener.AcceptTcpClient() as its argument to apply the
TcpClient from the listener. Put this code in the Tmr_Tick sub:
If Listener.Pending() = True Then
Client = New ExtendedTcpClient(Me)
Client.SetNewClient(Listener.AcceptTcpClient())
End If
Now the client and server are connected to each other.
Now you need to subscribe to the PacketReceived event of the
client. Create a sub like so:
Private Sub Client_PacketReceived(sender As Object, e As ExtendedTcpClient.PacketReceivedEventArgs) Handles Client.PacketReceived
End Sub
All received data are presented in an array of bytes.
In the PacketReceived sub you can output the received packet as text into a TextBox. Just check if the packet header is PlainText and then
you can convert the received packets contents (which is an array of
bytes, accessed via e.Packet.Contents) to a string and put it in
the TextBox.
If e.Packet.Header = TcpMessagePacket.PacketHeader.PlainText Then
TextBox1.AppendText("Message recieved: " & System.Text.Encoding.Default.GetString(e.Packet.Contents) & Environment.NewLine)
End If
System.Text.Encoding.Default.GetString() will convert a byte array to normal text.
In the PacketReceived sub you can also make it send "Message received" to the client.
Dim ResponsePacket As New TcpMessagePacket(System.Text.Encoding.Default.GetBytes("Message received."), TcpMessagePacket.PacketHeader.PlainText)
ResponsePacket.Send(Client.Client) 'Get the ExtendedTcpClient's underlying TcpClient.
Lastly, when closing the form you just need to disconnect the client.
Private Sub ServerWindow_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
If Client IsNot Nothing Then Client.Disconnect()
End Sub
And that's it for the server side.
Client side
For the client side you will do pretty much the same as the server side, though you won't be needing a TcpListener nor a Timer.
Dim WithEvents Client As New ExtendedTcpClient(Me) 'The current form as its owner.
Connect to the server via the IP and port you've given the listener.
Client.Connect("127.0.0.1", 5555) 'Connects to localhost (your computer) at port 5555.
Now if you want to send text to the server you'd do something like this (in for example a button):
Dim MessagePacket As New TcpMessagePacket(System.Text.Encoding.Default.GetBytes(TextBox2.Text), TcpMessagePacket.PacketHeader.PlainText)
MessagePacket.Send(Client.Client)
TextBox2 includes the text you want to send.
Lastly, you will need to subscribe to the PacketReceived event here too to check for responses from the server. In there you receive text just like the server does.
Private Sub Client_PacketReceived(sender As Object, e As ExtendedTcpClient.PacketReceivedEventArgs) Handles Client.PacketReceived
If e.Packet.Header = TcpMessagePacket.PacketHeader.PlainText Then
TextBox1.AppendText(System.Text.Encoding.Default.GetString(e.Packet.Contents) & Environment.NewLine) 'Prints for example "Message received." from the server.
End If
End Sub
And now everything should be working!
Link to a complete example project (only client-to-server): http://www.mydoomsite.com/sourcecodes/TCP%20Messaging%20System.zip
Link to C# example: http://www.mydoomsite.com/sourcecodes/CSharp%20TCP%20Messaging%20System.zip
If you want to add more headers to the class (the headers indicate to you what kind of data each packet contains), open TcpMessagePacket.vb and add more values in the PacketHeader enum (located in the region called Constants).
Hope this helps!
Screenshot from the example project
(Click the image for larger resolution)

Setting a manual timeout in VB.NET

I have a vb.net application that interfaces with some external hardware - an array of motor controllers. To do this, I'm using a CANOpen library provided by the hardware supplier. However, the timeouts built into the library are frankly excessive, and cause the application to hang painfully under specific conditions. I'd prefer not to need to edit the library if possible.
What's the most sensible way to design in another, shorter timeout within vb.net? The function in question is a blocking function, so presumably in-thread timers won't help. Is there an elegant solution here?
Give this a try, it's is the best I could come up with so far. I've used background workers just because they are easy to use.
Basically it's a thread within a thread which will at least keep your UI responsive, judging by what you've said you should probably use threading for all the drive comms functions anyway in case a drive loses comms for any reason while the app is running.
This ain't pretty, but it will at least allow you to exit out early before the CAN function itself times out.
Private connected As Boolean
Private Sub bwTryConnect_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwTryConnect.DoWork
Dim timeout As Boolean
Dim timeoutCount As Integer
Dim timeoutValue As Integer = 5 ' timeout value
bwConnect.RunWorkerAsync() ' start worker to try connection
While bwConnect.IsBusy And Not timeout
Thread.Sleep(1000) ' wait a second
timeoutCount += 1 ' increment timeout value
If timeoutCount = timeoutValue Then timeout = True ' connection timed out
End While
' connected will be true if the try connection worker completed (connection to drive ok) before the timeout flag was set, otherwise false
connected = Not timeout
End Sub
Private Sub bwConnect_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwConnect.DoWork
' use your CAN library function here - either a simple connect command or just try reading an arbitary value from the drive
' if you want to test this, uncomment one of the following lines:
'Thread.Sleep(20000) ' simulate timeout
'Thread.Sleep(2000) ' simulate connect
End Sub
Obviously you then call with bwTryConnect.RunWorkerAsync().

use callback to allow multiple connections to socket?

I am trying to create a VB.Net server program that has an external link to process data. The server will wait on port 7878 for a request to be made from a client. When the server receives a request it will send a string containing the state of all variables and send a string every second containing values for only changed variables. The server does not need to receive any information from the client for processing. I have successfully implemented everything with the exception of allowing for multiple requests at once. The basic program looks like this:
Class Server
Public Sub Main()
'thread start for ListenForRequests
End Sub
Public Sub ListenForRequests()
'code to set up socket
'bind socket
'listen
Using newConnection as socket.accept()
'do stuff
newConnection.send'stuff
End Using
End Sub
End Class
Can anyone tell me a SIMPLE way to implement a callback for async code? I think I need to move my 'do stuff and send stuff code into a new sub and fire a new thread upon socket.accept, but I can't figure out how to pass the newConnection through to a new thread.

Application crashes while reading Serial Ports in loop using .Net 2.0

I take a part on a project and after many tests, me and my colleagues feel little disappointed by our coding skills and methodology. The issue is the following:
The application must read data from some type of RS-485 devices connected on a single bus via one or multiple serial ports. However, these devices come from different manufactures so as a result, they have different connection settings, different command sets and return different data. Moreover, each serial port can handle none, one or multiple devices simultaneously.
Each of our custom COMPort objects contains a device list and each device contains the type and the device settings that are recommended. So, after loading all settings and building all objects, the application starts polling each device in each COMPort object list. Every time, before writing each command, the serial port buffers are emptied and its settings change (Baud-rate, Parity, Handshake) without closing and reopening the port. After every command, a Threading.Thread.Sleep(delay) is executed with variable delay, depending on the response time of each device (delay varies from 150ms to 800ms). After Sleep() ends, application Reads the serial port and gets expected data. After that, either if BytestoRead > 0 or BytestoRead = 0 or an Exception occurs(wrong data returned, error in checksums, etc.), this function returns and application continues to read the next device in the list.
So, application executes in an endless loop, reading all devices from start to end, until it finally ends when user stops it from UI (when the project is a Windows Forms) or when the service Stops (when the project is a Windows service). The application does not use DataReceived event because we faced a lots of trouble, so the Read procedure is done manually.
Finally, application has a global log file which is accessible from all objects and holds all usual and unusual events and each COMPort object has its own log file in which all valid read data are written. Moreover, each COMPort has a timer object which checks for daytime changes per second and everyday at midnight all log files close and new files are opened.
The main problem is that all this seems to work great but unfortunately the application stops writing to logs after 1-2 hours (most of the times after 1:58 minutes exactly on one client machine), then after some minutes it crashes, sometimes with Send or Don't send window and sometimes silently. The CPU load never exceeds 1% and private & virtual memory does not seem to have a leak because it doesn't grow.
I have to mention that this application is tested on 3 machines (Windows XP, Windows 2003), on the following situations: mixed types of devices, one type of device, no devices connected (using null modem cable on one development machine.) Even on the last situation, the application crashes silently. This leads me to the thought that the issue has nothing to do with the Read procedure because in the “no devices attached” scenario, there is no data to be read. Also, the project is built with VB.Net 2008 using .Net Framework 2.0.
EDIT : Below is a small summary of the Read, Write and Polling procedures. I wrote it on Notepad++ as an example because I don't have access to the real code right now, so excuse any syntax errors. The aim of this is to give a better explanation of the situation I describe above and nothing more.
Private deviceIndex as Integer = -1
Private deviceList as List(Of Devices)
Private serialPort as SerialPort()
Private Sub PollSensor()
Try
If (deviceIndex <> -1) And deviceIndex > deviceList.Count then
deviceIndex = 0
End If
With serialPort
If .IsOpen then
.DiscardInBuffer()
.DiscardOutBuffer()
' SerialPort attributes must change during runtime to suit device requirements.
' Some devices require for example 4800 BaudRate and some other 9600.
.BaudRate = deviceList(deviceIndex).BaudRate
.Parity = deviceList(deviceIndex).Parity
.Handshake = deviceList(deviceIndex).HandShake
' Write command to device, passing device specific response time.
' Some devices have for example 150ms response time and some other 800ms.
WritetoDevice(new Byte[] {01, 01}, deviceList(deviceIndex).ResponseTime)
End If
End With
Catch ex As Exception
' Log
End Try
End Sub
Private Sub WritetoDevice(ByVal command As Byte[], ByVal responseTime As Integer)
Try
serialPort.Write(command, 0, command.Length)
' Cause application to pause for time equal with the device response time.
Threading.Thread.Sleep(responseTime)
' If device response is regular, data may have been available in serial port.
If ReadDevice() = 0 then
' Poll next device
deviceIndex += 1
PollSensor()
End If
Catch ex As Exception
' Log
End Try
End Sub
Private Function ReadDevice() As Integer
Dim data as String = ""
Try
With serialPort
If .IsOpen then
If .BytesToRead() > 0 Then
Do
data += .ReadExisting()
Until .BytesToRead() = 0
' Do something with data
End If
End If
End With
Catch ex As Exception
' Log
Finally
' Continue with the next device in deviceList, ignoring the current device Read() result
' This happens because devices return faulty data too often and the polling must continue
Return 0
End Try
End Function
We have tried to use the Debug Diagnostics Tool 1.2 x86 but the results returned, do not help us to understand the source of the issue. Some of the exported reports contain the following, although all exceptions are handled in Try..Catch blocks:
- The following threads in ... are waiting in a WaitOne
- 6,25% of threads blocked
- System.ExecutionEngineException
- System.StackOverflowException
- System.OutOfMemoryException
- System.FormatException
- System.Threading.ThreadAbortException
Does anyone have a better idea on how the above scenario could work?
Feel free to criticize any of the above methods, because that will help us to become better.

Check if port is blocked by windows firewall

How do i check if specific port is blocked by Windows firewall , both in incoming and outgoing connections.
I've seen code samples such as this one:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim host As String = "localhost"
Dim port As Integer = 6900
Dim addr As IPAddress = CType(Dns.GetHostAddresses(host)(0), IPAddress)
Try
Dim tcpList As New TcpListener(addr, port)
tcpList.Start()
Catch sx As SocketException
' Catch exception here if port is blocked
End Try
End Sub
But how can i know if the exception is thrown specifically because of firewall blocking, and not because of other socket errors?
I'd say that the proper way to check if Windows Firewall is blocking a port isn't to test it, but to use the Windows Firewall API to check conclusively.
I've never used it but I'd assume that INetFwOpenPorts would be the place to start.
Here's a VB.Net code sample that seems to contain code that does this. Specifically I'd suggest looking at the IsxPLportOpen method in that sample which uses the GloballyOpenPorts method to get a reference to INetFwOpenPorts.