I have implemented a wcf P2P setup in a simple application.
My question is the result of testing this with multiple clients. Nine times out of ten, all the clients will synch up in the mesh and connect without issue.
However, depending on which client I close and then re-open, it will not reconnect to the mesh. The other clients do not see it.
My question is how can I perhaps close and re-open the p2p on this client so it can attempt to connect again? I'd set a timer perhaps that every minute or so if it isn't connected, it might assume there is an issue so it would close it's p2p endpoint or whatever and then re-open it to refresh the whole thing.
I ask this since if I close this client, then re-open it, it will reconnect to the mesh.
I want fool-proof connections. Such as, you open a client and the client will figure out if it has to restart or it isn't getting connection after a certain amount of time so it attempts to "flush" the connection and rebuild it.
Does this make sense?
It's going to be difficult to determine that you're not connected to the mesh because of some unknown fault condition rather than simply being alone.
The IOnlineStatus property on the peer channel can tell you if you're alone in the mesh (false), or if you have connected peers (true). You can get this property by registering for the status change event like so:
IOnlineStatus status = myPeerChannel.GetProperty<IOnlineStatus>();
status.Online += new EventHandler(MyOnlineEventHandler);
status.Offline += new EventHandler(MyOfflineEventHandler);
So I suppose one way to do this would be to have a timer that checks your online status and if you go more than X amount of time being offline, dispose of your channel and create a new one.
Related
I'd like to provide my TCP/IP client class with a CheckConnection function so that I can check if something wrong has happened (my own client disconnected, server disconnected, server stuck up,...).
I have something like that:
bool isConnectionActive = false;
if (Client.Poll(100000, SelectMode.SelectWrite) == true)
isConnectionActive = true;
based on what MSDN says:
SelectWrite: true, if processing a Connect(EndPoint), and the connection has succeeded; -or- true if data can be sent; otherwise, returns false.
The point is that, testing this with simple server application, I am getting always true from CheckConnection, even if server-listener has been closed and even if server-application has been shutdown; that's weird, because I expect in those cases that both no connection is being processed (already connected minutes ago) and no data can be sent.
I have already implemented a similar connection check on server side using a combination of Poll with SelectRead and Available and it seems working properly; so now, should I write something similar also on client side? is the SelectWrite approach correct (but I'm using it improperly)?
There are lots of things you can check but none of them are assured to give you the result you are looking for. Even the implementation you have on the server will not work 100% of the time. I guarantee it will fail one day.
There are FIN packets, which should be sent from the client to the server, and vice versa when a connection is closed, but there is no guarantee that these will be delivered, or even processed.
This is generally known as the TCP Half Open problem.
Closing a TCP Socket is a mutually agreed process, you generally have a messaging protocol which tells the other end that it's closing, or you have some predefined set of instructions and you close after that.
The only reliable way to 100% detect if a remote socket is closed is to send some data to it. Only if you get an error back will you know if the socket has closed.
Some applications which don't send a lot of data implement a keep-alive protocol, they simply send/receive a few bytes every minute, so they know that the remote endpoint is present.
You can technically have two servers that are in a connected state and haven't sent data to each other for 10 years. Each end continues to believe that the other end is there until one try's to send some data and finds out it isn't.
I'm trying to make a stunnel clone in C# just for fun. The main loop goes something like this (ignore the catch-everything-and-do-nothing try-catches just for now)
ServicePointManager.ServerCertificateValidationCallback = Validator;
TcpListener a = new TcpListener (9999);
a.Start ();
while (true) {
Console.Error.WriteLine ("Spinning...");
try {
TcpClient remote = new TcpClient ("XXX.XX.XXX.XXX", 2376);
SslStream ssl = new SslStream(remote.GetStream(), false, new RemoteCertificateValidationCallback(Validator));
ssl.AuthenticateAsClient("mirai.ca");
TcpClient user = a.AcceptTcpClient ();
new Thread (new ThreadStart(() => {
Thread.CurrentThread.IsBackground = true;
try{
forward(user.GetStream(), ssl); //forward is a blocking function I wrote
}catch{}
})).Start ();
} catch {
Thread.Sleep (1000);
}
}
I found that if I do the remote SSL connection, as I did, before waiting for the user, then when the user connects the SSL is already set up (this is for tunneling HTTP so latency is pretty important). On the other hand, my server closes long-inactive connections, so if no new connection happens in, say, 5 minutes, everything locks up.
What is the best way?
Also, I observe my program generating as much as 200 threads, which of course means that context-switching overhead is pretty big and sometimes results in the whole thing just blocking for seconds, even with just one user tunneling through the program. My forward function goes, in a gist, like
new Thread(new ThreadStart(()=>in.CopyTo(out))).Start();
out.CopyTo(in);
of course with lots of error handling to prevent broken connections from holding up forever. This seems to stall a lot though. I can't figure how to use asynchronous methods like BeginRead which should help according to google.
For any kind of proxy server (including an stunnel clone), opening the backend connection after you accept the frontend connection is clearly much simpler to implement.
If you pre-open backend connections in anticipation of receiving frontend connections, you can certainly save an RTT (which is good for latency), but you have to deal with the issue you hinted at: the backend will close idle connections. At any time that you receive a frontend connections, you run the risk that the backend connection that you are about to associate with this frontend connection and which has been opened some time ago is too old to use and may be closed by the backend. You will have to manage a pool of currently open backend connections and periodically close and refresh them when they become idle for too long. There is even a race condition where if the backend decided the connection has been idle too long and decides to close it but the proxy server receives a new frontend connection at the same time, the frontend may decide to forward a request through the backend connection while the backend is closing this connection. That means that you must be able to know a priori how long backend connections can be idle for before the backend will close them (you must know what the timeout values that are configured on the backend are set to) so you can give them up just before the backend will decide they are too old.
So in summary: pre-opening backend connections will save an RTT versus opening them only on demand, but it is a lot of work, including subtle connection pool management that it quite tough to implement bug-free. Up to you to judge if the extra complexity is worth it.
By the way, concerning your comment about handling several hundred simultaneous connections, I recommend implementing such an I/O-bound program as a proxy server based around an event loop instead of based around threads. Basically, you use non-blocking sockets and process events in a single thread (e.g. "this socket has new data waiting to be forwarded to the other side") instead of spawning a thread for each connection (which can get expensive both in thread creation and context switches). In order to scale such an event-based model to multiple CPU cores, you can start a small number of parallel threads of processes (more or less one per CPU core) which each handle many hundreds (or thousands) of simultaneous connections.
I have been using this API ( http://managedwifi.codeplex.com/ )successfully and without any major problems. Until today at least...
I have implemented a program in C# which among others retrieves the BSSID of the connected A.P. and the number of the available wireless networks in proximity and does a number of checks. When I am connected to a certain A.P. I get a message and when I am not connected to this specific A.P. (but to another one or I am not connected at all) I get another message. Simple as that.
I did this, connection to the A.P, check once and only - when the application starts.
But...I wanted to add a timer so that this check happens every 30 or 60 seconds (and not only at the beginning). The problem is that it runs for a few times (maximum 10) and then the program freezes and I get the following message:
Win32Exception was unhandled:
An attempt was made to establish a session to a network server, but there are already too many sessions established to that server
and the message box points to WlanClient client = new WlanClient();
I don't know what is incorrect and although the code compiles correctly I get this error.
Maybe is something with the dispose of the objects?
Any help will be much appreciated.
"Maybe is something with the dispose of the objects?"
You are right, that is whats probably missing from your code.
Make
WlanClient client = new WlanClient();
a class variable and use it as often as you like.
... class Yourclass
{
private static WlanClient client = new WlanClient();
...
Okay I know there is lots of info out there on this and I promise you I have read it all and tried umpteen different methods to get this working!!
I have a socket server program which runs on a laptop. I then have up to 50 laptops connected wirelessly via the same LAN to the server. The client laptops all connect to the server (using Socket.ConnectAsync) and the server uses async methods as well to send and receive data. The server shows a list of connected client laptops to the user and this list seems to be accurate and picks up whenever a client disconnects and connects. However, the client laptops never seem to detect when connection to the server has been lost under certain circumstances (ie if server program crashes, if server laptop goes in to standby mode etc.) I have got a timer on the client laptops which polls the connection every 5 seconds as follows:
bool SocketConnected(Socket s)
{
bool part1 = s.Poll(0, SelectMode.SelectWrite);
bool part2 = (s.Available == 0);
if (!part1 && part2)
{
return false;
}
else
{
return true;
}
}
I have tried using all selectmodes (SelectWrite,SelectRead,SelectError) and have tried using different time out values. I have tried checking s.Connected value after these operations and have tried all manners of other methods to determine the connection state and nothing seems to produce reliable results!! I think I can achieve the result I desire by sending dummy information every 5 seconds and checking s.Connected after doing so, however I don't really want to do this as each laptop is already sending lots of data to the server as it is. Any help at all is massively appreciated! Thanks
The only reliable way to check if a connection is alive is to send something to the other end and see if it arrives. You can do this either manually by sending and receiving a "ping" value from time to time, or automatically by enabling the KeepAlive socket option.
The MSDN documentation for Socket.Poll is very explicit about the exact situations (server crashes, standby) you mentioned:
This method cannot detect certain kinds of connection problems, such
as a broken network cable, or that the remote host was shut down
ungracefully. You must attempt to send or receive data to detect these
kinds of errors.
I run my application on a network and in some cases the client lost connection to the server. After this time, when I wanted to send a message to the server I receive the following error: Operation not allowed on non-connected sockets (something like this).
I thought to create an event for object type TcpClient and when tcp_obj.Connected = false to call a function to discontinue execution of the current code. How could I do this?
Or giving me other suggestios.
Thanks.
I know at least from socket programming in Java that when a client loses connection to the server, the server does not and can not know about it. You need a heartbeat of some sort to detect the early disconnection.
We often use a heartbeat in our client/server applications to detect early disconnections and log them on the server. This way the server can close the associated socket and release the connection back to the pool.
Simply send a command to the client periodically and wait for a response. If no response is garnered within a timeout assume disconnect and close streams.
I would simply first check your connection object to ensure you are connected, prior to attempting to send the message. Also make sure that you are putting your send-logic inside of a try-catch, so that if you do happen to get disconnected mid transmission, you'll be able to resume without blowing your application apart.
Psuedo-Code:
private void SendMessage(string message, Socket socket)
{
if(socket.connectionState = States.Connected)
{
try{
// Attempt to Send
}
catch(SocketException Ex)
{
// Disconenct, Additional Cleanup Etc.
}
}
}
If you are in C#, prior to your connection state changing, you will have a socket disconnected event fire, prior to your connection state changing. Make sure you tie this event up as soon as your socket connects.
Can we know why you use TCP sockets? Is for calling a tcp device o server code?
I recommend you if is for calling a .net server app use Windows Communication Foudation. It is simple to expose services by net.tcp, http, etc.
Regards,
Actually this is a very old problem,
If I understand your question correctly you need a way to know whether you're application is still connected to the server or vice versa.
If so then a workaround is to have a UDP connection just to check the connectivity (overhead I know, but its much better then polling on Connected state), you could check just before you send you're data.
Since UDP is not Connection oriented you don't need to be connected when you send the data