TCP/IP detect clients who willingly disconnects themselves from my server - vb.net

I am using Vb.Net and VS 2013, based on my research it isn't possible to detect whether the client is still connected or not unless the client sends a KEEP ALIVE command to my server or sends a string indicating that that client will be disconnected before it disconnects itself, due to this I wanted to know if it is possible to detect if a client disconnects itself from my server? I mean if the client willingly disconnects it self from the server?
This is a follow up question to this wherein I am asking if it is possible to detect currently connected clients to my server
Edit: I've added that it is also possible by telling the client to send a string of command indicating that it will disconnect itself before the client actually disconnects itself.

I think you should do a few tutorials on the subject :
https://msdn.microsoft.com/en-us/library/vstudio/ms172757(v=vs.100).aspx
and have a look at the documentation :
https://msdn.microsoft.com/en-us/library/vstudio/system.net.sockets.socket(v=vs.100).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
https://msdn.microsoft.com/en-us/library/vstudio/1011kecd(v=vs.100).aspx
You can check the current state of the socket via Poll although i would recommend switching to an OOP approach
'Creates the Socket for sending data over TCP.
Dim s As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
' Connects to host using IPEndPoint.
s.Connect(EPhost)
If Not s.Connected Then
strRetPage = "Unable to connect to host"
End If
' Use the SelectWrite enumeration to obtain Socket status.
If s.Poll(- 1, SelectMode.SelectWrite) Then
Console.WriteLine("This Socket is writable.")
Else
If s.Poll(- 1, SelectMode.SelectRead) Then
Console.WriteLine(("This Socket is readable. "))
Else
If s.Poll(- 1, SelectMode.SelectError) Then
Console.WriteLine("This Socket has an error.")
End If
End If
End If
If SelectMode.SelectError is True your client/server has either disconnected or timed out.

Related

Rebroadcasting data from Vb.Net socket listener to another socket

I've got a VB.Net project working that connects to a remote IP/port and receives a continuous string of data from it. It does this by receiving a byte at a time and assembling it into a string until the EOL character is received, then it currently writes the completed line out to a file. This is run using a background worker so that it doesn't block the UI of my application.
I'd like to extend it so that the line of data received is pushed to a remote machine via another socket as soon as the EOL character is received. I've implemented the same basic code as my listening socket to do this and it works but hangs after a random amount of time.
I suspect that there's a problem with the data send completing before the next line of data is sent so I think I may need to use an asynchronous socket.
Is this likely to be the best approach ? If so, should this go on a separate background thread of its own or stay on the current background thread ?
Here's the code that I use to set up the connection to the remote server that I want to send data to:
' Create socket to server process
Dim serverSocket As New System.Net.Sockets.TcpClient()
Dim serverStream As NetworkStream = Nothing
' Declare buffer for messages sent to server
Dim serverBuffer As Byte()
' Connect to remote server
serverSocket.Connect(serverIp, serverPort)
' Tie server stream to socket
serverStream = serverSocket.GetStream()
And this is how I'm actually sending the line of data:
' Send line to remote server
serverBuffer = System.Text.Encoding.ASCII.GetBytes(line)
serverStream.Write(serverBuffer, 0, serverBuffer.Length)
It all seems to make sense but Googling around suggests that I should use the .BeginWrite method but that then requires callbacks to be defined and I can't see what purpose they would serve.

Close The Socket?

I have an application that needs to stream data up to a server over a particular port. When the application starts it performs a number of checks, for network connectivity, a reachable host, among others. I'd like it to also check the port to ensure it's able to receive data.
I have this code:
Private Function CheckPort(ByVal Host As String) As Boolean
Dim IPs() As IPAddress = Dns.GetHostAddresses(Host)
Dim s As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
s.Connect(IPs(0), <port # removed>)
If s.Poll(-1, SelectMode.SelectWrite) Then
Return True
End If
Return False
End Function
The code works well, but I'm concerned that by performing the check I might be inadvertently preventing subsequent messages from the application from reaching the port. Will performing this check interfere with the actual data I want to send to the host? Should I close the socket with s.close() before returning the function?
I mainly agree with CodeCaster's response.
If you say the server is buggy, it is also probable that a few minutes after you check the port connection, the connection is broken or even closed by the server.
If you still want to do it as a means to reduce risk of making the user write some message that later cannot be sent, this would be a good approach to follow. An alternative is that you can save the data as draft locally or somewhere else for sending it later when the server is available.
Now, going to your code:
You are opening a connection inside function CheckPort so when the function finishes you will lose any reference to s, the open socket. In C, you would have a leak of resources; in Java, a garbage collector will take care of the Socket and close it. I don't know how it is in VB but I'd close that socket before leaving the function. In any case it's a healthy practice.
Additionally, when you have data ready to send you won't be able to do it on the same connection if you lose the reference (s) to the open socket or you close the socket (unless VB has any trick that I don't know). You will have to open a new connection to send data. Don't worry, you will be able to do it even if you made the check before. The server will see it as just a different connection, maybe from a different source port (or could be the same if you closed the connection before, that depends on the OS).
Checking a port before connecting to it is as useful as verifying file existence before opening it: not at all.
The file can be deleted in between checking and opening, and your socket can be closed for a variety of reasons.
Just connect and write to it, it'll throw an appropriate exception when it won't work.

Recover Callback channel after CommunicationObjectAbortedException thrown

We have (Multiple)Clients-(One)Server architecture for poker desktop game. We are using callback Notifications using callback Channels.
But sometimes because of internet connection drops, that particualr client gets disconected from server and that particular's client's WCF channel is also gone to faluted state and his callback Channel which lies in server is also faluted.
Scenario :
That client is playing game, while internet connection drops, that game is stopped, still his game window remains open and when his/her internet connection gets back that client is dropped out from Server, but that player's game window still opens and that player can't do anything as his/her WCF channel is dropped out.
We want to close that particular client's window while he/she is dropped out from server and throwing 'CommunicationObjectAbortedException ' exception.
We can't use previous WCF channel's callback channel as it's in faluted state.
So we have tried to create new callbackChannel in server while dropping using below code :
OperationContext.Current.GetCallbackChannel();
but here Current is showing "NULL" as that player's WCF channel is aborted, so it's throwing an error that "Object reference not set to an instance of object".
So is there any solution to use aborted WCF channel's callback Channel or recover that WCF channel without reinitializing them or to call that client using new channel?
I'd try following:
On server side, when trying to communicate using faulted / aborted chanel - you'll failed.
Catch this failure, and remove its callback from the list (I suppose you manage some callback list).
On client side - when chanel Faulted / ... handled - try to re-open new chanel to server. When this new chenel will be open, on server side place this new callback back to the "valid callbacks" list.

Internet connection in MC65

In MC65, SIM card is already inserted. Any web site can be browsed.
In my application, there is sending email feature using Rebex. Sometimes, it cannot send email. So I tried to browse IE and I'm beware if 3G connection signal appears, sending works properly.
Around connection signal on Screen, there is "H" symbol. What is it?
For my case, it's not good to switch 3G connection by browsing IE. how to handle it.
Does the Rebex Mail throw any exception when it's unable to send email? Error message might help to diagnose the problem.
Is it possible to create a SMTP communication log file and include part of it with error message? Following code shows how to do it:
Dim mailMessage As New MailMessage()
'todo: set mail message properties
Dim smtp As New Smtp
smtp.LogWriter = new Rebex.FileLogWriter("\temp\log.txt", Rebex.LogLevel.Debug)
smtp.Connect("smtp.example.org")
smtp.Send(mailMessage)
Edit:
The 'H' symbol could mean HSDPA - high speed data transfer over 3G network.
Is it possible, that connection is dropped and IExplorer re-establishes connection automatically. In such case you may try to 'dial' connection manually. The How to establish a GPRS connection for FTP use on .NET CF post shows how.

Manage frequently called WCF connection

Maybe I'm missing something basic here, so please correct me if I am. I have a local service and a WinForms app that communicate via WCF, but I seem to end up with a lot of copies of this code in my application:
Public Shared Sub MyLocalMethod1()
Dim tcpBinding As New NetTcpBinding
tcpBinding.SendTimeout = New TimeSpan(0, 0, 5)
Dim tcpFactory As ChannelFactory(Of MyWCFClass.MyWCFInterface) = New _
ChannelFactory(Of MyWCFClass.MyWCFInterface)(tcpBinding, "net.tcp://localhost:4079")
Dim ServiceWCFConnection As MyWCFClass.MyWCFInterface = tcpFactory.CreateChannel
ServiceWCFConnection.MyWCFMethod1()
tcpFactory.Close()
End Sub
I should probably be doing this in some kind of a helper class that creates the connection, lets my service use it, and then closes the connection, so I don't have multiple copies of this connection code. However, should I be leaving this connection open, or does it make sense to close it every time? The WinForm generally calls the service every few seconds, so it may make more sense to try and have a common copy that all these different calls can each access, instead of opening a closing a new connection each time.
It depends on your needs because both approaches are correct. You can wrap your channel creation code into some helper. You will have same functionality as you use at the moment with single place to edit your channel creation code (DRY principle). Usage of the service is slower because each call will create new TCP connection. Use some disposable helper class to represent your created connection.
If you decide to use single channel (proxy) for whole application you have to think about some new complexity. You are using Net.Tcp binding which creates transport session - TCP connection will live for long time. Moreover WCF service instance will live for the same time as the connection because default instancing mode is PerSession. So single service instance will handle all requests from your client = your service will became stateful. Also when you use opened channel for several calls you have to test state of the channel - network problem, server problem, timeout or unhandled exception will switch channel to Faulted state - such channel and related service instance cannot be used any more. You have to abort such channel and open new one.