Edit: Yes I know that UDP doesn't technically connect, but you can still use it to set the default target for Send(), which is what I'm doing here.
Basically I have this problem that between calls to MySocket.Send(), MySocket is becoming disconnected i.e. the Connected variable becomes false (I know that Connected isn't necessarily up-to-date, but no data isn't being sent so I know that it's telling the truth).
The strange thing is that the RemoteEndPoint variable is still set correctly, but when I call Send(), no data is recieved by the other computer. However if I call Connect() again, the socket does connect, and I'm able to send data (at least until the next time the user does something that causes another call to Send() )
Can anyone tell me why a socket would spontaneously disconnect?
The line where I connect it is:
opep = new IPEndPoint(Opponent.Address, 1000);
Listener.Connect(opep);
I don't see anything here that could be garbage collected for example to cause this issue.
Thanks!
UDP doesn't set up a connection. You should check out the following link for more info
Difference between TCP and UDP?
Related
I'm developing a C# application, working with TCP sockets.
While debugging, I arrive in this piece of source code:
if ((_socket!= null) && (_socket.Connected))
{
Debug.WriteLine($"..."); <= my breakpoint is here.
return true;
}
In my watch-window, the value of _socket.RemoteEndPoint is:
_socket.RemoteEndPoint {10.1.0.160:50001} System.Net.EndPoint {...}
Still, in commandline, when I run netstat -aon | findstr /I "10.1.0.160", I just see this:
TCP 10.1.13.200:62720 10.1.0.160:3389 ESTABLISHED 78792
TCP 10.1.13.200:63264 10.1.0.160:445 ESTABLISHED 4
=> the remote endpoint "10.1.0.160:50001" is not visible in netstat result.
As netstat seems not reliable for testing TCP sockets, what tool can I use instead?
(For your information: even after having run further, there still is no "netstat" entry.)
Documentation of Socket.Connected, says:
The value of the Connected property reflects the state of the
connection as of the most recent operation. If you need to determine
the current state of the connection, make a nonblocking, zero-byte
Send call. If the call returns successfully or throws a WAEWOULDBLOCK
error code (10035), then the socket is still connected; otherwise, the
socket is no longer connected.
So if it returns true - socket has been "connected" some time in the past, but not necessary is still alive right now.
That's because it's not possible to detect if your TCP connection is still alive with certainly without contacting the other side in one way or another. The TCP connection is kind of "virtual", two sides just exchange packets but there is no hard link between them. When one side decides to finish communication - it sends a packet and waits for response from the other side. If all goes well two sides will both agree that connection is closed.
However, if side A does NOT send this close packet, for example because it crashed, or internet died and so on - the other side B has no way to figure out that connection is no longer active UNTIL it tries to send some data to A. Then this send will fail and now B knows connection is dead.
So if you really need to know if other side is still alive - then you have to send some data there. You can use keepalive which is available on TCP sockets (which basically does the same - sends some data from time to time). Or if you always write on this connection first (say other side is server and you do requests to it from time to time, but do not expect any data between those requests) - then just don't check if the other side is alive - you will know that when you will attempt to write next time.
What I have:
I have two socket client programs written in C#.
I have one socket server program (not written by me but it works) in Python.
The problem:
The first c# socket client I wrote works fine and can communicate with the python server client. I can send data over with no issue. However I wanted to rewrite the code to make it more object oriented, so I made the second program which is the same as the first in terms of what is done.
The issue is the second one won't connect, saying this:
System.Net.Sockets.SocketException: An attempt was made to access a socket in a forbidden way by its access permissions.
I googled this and I have come to the realization that the connection from the first connection hasn't been completely unbound.
When I did a netstat -a, I actually saw the connection and it said TIME_WAIT at the end.
The question is, how do I unbind it? Is it on the C#/client side?
FYI I have already tried closing/disconnecting/shutting down the socket and none of that worked. I also put in this command
connection.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
upon instantiation of the socket connection but that did not work either.
Would I have to do something on the server side to unbind the connection?
I know you said you already calling close or disconnect.
But are you reinitializing the socket variable.
eg: connection = new System.Net.Sockets.Socket(...
If you are using an older version of .Net you may also have to call Dispose() after call Close().
eg:
connection.Close();
connection.Dispose();
connection = new System.Net.Sockets.Socket(...
Be sure to always work with sockets within try statements as any calls to send and receive data or close the socket could result it an error at which stage, you should log the error and call Close() and then if applicable Dispose() on the socket instance to clear the resources. Once this has been done, you can then reinitialize a new instance of the socket to attempt a new connection to the server.
I'm using TcpListener to accept & read from TcpClient.
The problem is that when reading from a TcpClient, TcpClient.BeginRead / TcpClient.EndRead doesn't throw exception when the internet is disconnected. It throws exception only if client's process is ended or connection is closed by server or client.
The system generally has no chance to know that connection is broken. The only reliable way to know this is to attempt to send something. When you do this, the packet is sent, then lost or bounced and your system knows that connection is no longer available, and reports the problem back to you by error code or exception (depending on environment). Reading is usually not enough cause reading only checks the state of input buffer, and doesn't send the packet to the remote side.
As far as I know, low level sockets doesn't notify you in such cases. You should provide your own time out implementation or ping the server periodically.
If you want to know about when the network status changes you can subscribe to the System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged event. This is not specific to the internet, just the local network.
EDIT
Sorry, I misunderstood. The concept of "connected" really doesn't exist the more you think about it. This post does a great job of going into more details about that. There is a Connected property on the TcpClient but MSDN says (emphasis mine):
Because the Connected property only
reflects the state of the connection
as of the most recent operation, you
should attempt to send or receive a
message to determine the current
state. After the message send fails,
this property no longer returns true.
Note that this behavior is by design.
You cannot reliably test the state of
the connection because, in the time
between the test and a send/receive,
the connection could have been lost.
Your code should assume the socket is
connected, and gracefully handle
failed transmissions.
Basically the only way to check for a client connection it to try to send data. If it goes through, you're connected. If it fails, you're not.
I don't think you'd want BeginRead and EndRead throwing exceptions as these should be use in multi threaded scenarios.
You probably need to implement some other mechanism to respond to the dropping of a connection.
On the client side I need to know when/if my socket connection has been broken. However the Socket.Connected property always returns true, even after the server side has been disconnected and I've tried sending data through it. Can anyone help me figure out what's going on here. I need to know when a socket has been disconnected.
Socket serverSocket = null;
TcpListener listener = new TcpListener(1530);
listener.Start();
listener.BeginAcceptSocket(new AsyncCallback(delegate(IAsyncResult result)
{
Debug.WriteLine("ACCEPTING SOCKET CONNECTION");
TcpListener currentListener = (TcpListener)result.AsyncState;
serverSocket = currentListener.EndAcceptSocket(result);
}), listener);
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, and it is
clientSocket.Connect("localhost", 1530);
Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be TRUE, and it is
Thread.Sleep(1000);
serverSocket.Close();//closing the server socket here
Thread.Sleep(1000);
clientSocket.Send(new byte[0]);//sending data should cause the socket to update its Connected property.
Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, but its always TRUE
After doing some testing, it appears that the documentation for Socket.Connected is wrong, or at least misleading. clientSocket.Connected will only become false after clientSocket.close() is called. I think this is a throwback to the original C Berkeley sockets API and its terminology. A socket is bound when it has a local address associated with it, and a socket is connected when it has a remote address associated with it. Even though the remote side has closed the connection, the local socket still has the association and so it is still "connected".
However, here is a method that does work:
!(socket.Poll(0, SelectMode.SelectRead) && socket.Available == 0)
It relies on that fact that a closed connection will be marked as readable even though no data is available.
If you want to detect conditions such as broken network cables or computers abruptly being turned off, the situation is a bit more complex. Under those conditions, your computer never receives a packet indicating that the socket has closed. It needs to detect that the remote side has vanished by sending packets and noticing that no response comes back. You can do this at the application level as part of your protocol, or you can use the TCP KeepAlive option. Using TCP Keep Alive from .NET isn't particularly easy; you're probably better off building a keep-alive mechanism into your protocol (alternately, you could ask a separate question for "How do I enable TCP Keep Alive in .NET and set the keep alive interval?").
Just write to your socket as normal. You'll know when it's disconnected by the Exception that says your data couldn't be delivered.
If you don't have anything to write...then who cares if it's disconnected? It may be disconnected now, but come back before you need it - why bother tearing it down, and then looping a reconnect until the link is repaired...especially when you didn't have anything to say anyway?
If it bothers you, implement a keep alive in your protocol. Then you'll have something to say every 30 seconds or so.
Maybe solution is to send some dummy data through it and check if it times out?
I recommend stripping out the higher-level language stuff and explore what happens at the lower-level IO.
The lowest I've explored was while writing isectd (find on sourceforge). Using the select() system call, a descriptor for a closed socket becomes read-ready, and when isectd would attempt the recv() the socket's disconnected state can be confirmed.
As a solution, I recommend not writing your own socket IO and use someone else's middleware. There are lots of good candidates out there. Don't forget to consider simple queuing services as well.
PS. I would have provided URLs to all the above but my reputation (1) doesn't allow it.
does the clientSocket.Send() method wait for the packet to either be ack/nack'd?
If not your code is flying onto the next line while socket is still trying to figure out what is going on.
I'm using the following TCP Sockets Server/Client example: http://www.codeguru.com/Csharp/Csharp/cs_network/sockets/article.php/c8781/
I'm also using the following CryptoStream example:
http://www.obviex.com/samples/Encryption.aspx
Problem: Both Server and Clients communicate perfectly until I Stop the Server socket, wait a minute or so, then start the Server socket. Sometimes but not always I recieve a base64 error in the Encryption.aspx on line 'Convert.FromBase64String(cipherText);'...
I know there is incorrect / corrupted data in the buffer probably left-over from stopping the socket. Then the new data comes in and the error occurs.
Q. Will clearing the 'class SocketPacket; solve this issue?
Q. How do I clear the 'class SocketPacketsocketBuffer'?
Other suggestions are greatly appreciated..
One of the things you may find is happening is that one of the sockets is not being closed down properly. The thing with sockets is that you need to make sure they get correctly closed or you set the server socket to reuse the address.
Try tcpview from sysinternals to view the status of sockets. You can also use netstat to view the status of the sockets.