Re: reconnect tcp



On 15 Apr, 20:08, "Peter Duniho" <NpOeStPe...@xxxxxxxxxxxxxxxx> wrote:
On Wed, 15 Apr 2009 05:58:56 -0700, RedLars <Liverpool1...@xxxxxxxxx>  
wrote:





After reviewing several posts on this forum it appears to be that the
best way to deal with tcp disconnect
is to send data and handle any exceptions.

Below is a small example that I have used for test purposes. If I
remove the network cable during
sending a list of packets to the server I get several different
SocketExceptions. It seems like if the
network cable is out for less than roughly 15 seconds I get
SocketExceptions with socketErrorCode 10060
and 10035 (10060 is received first and only once). In this case the
tcp connection is not lost and the
application can continue to re-use the connection. However, if the
cable is out for more than 15 seconds
I get all SocketExceptions with SocketErrorCode 10060, 10035 and after
15 seconds I get 100054 (10060 is received first and only once). In
this case the connection is lost and it appear that the application
needs to re-connect to the server.

How do I know when to re-connect to the server? It seems redundant to
reconnect if connection isnt lost.

It's not clear from your post why you are getting error # 10035.  You  
should only see that when using non-blocking sockets.  Are you using  
non-blocking sockets?  That is, have you set the Socket.Blocking property  
to "false"?

As for the more general question, if a send or receive method on a Socket  
instance throws a fatal exception, then that connection is done.  You need  
to close the socket and reconnect.  The only non-fatal exception you  
should see in .NET is error # 10035 (WSAEWOULDBLOCK), and then only if  
you're using the Socket directly and you've configured the Socket instance  
to be a non-blocking socket (which in .NET is mostly pointless, because  
.NET offers much better asynchronous i/o methods).

What little code you posted seems to imply that you're not even using the  
Socket instance directly, but instead are using it via a NetworkStream and  
TcpClient.  In this case, any exception is likely to be fatal.  Even if  
NetworkStream put the Socket into the non-blocking state (and I don't  
think it should), it shouldn't be letting the WSAEWOULDBLOCK exception to  
filter back to your application code.

Finally note that for some exceptions, it may _appear_ that you are able  
to continue using the Socket, but in fact doing so could result in data  
corruption.  My recollection was that .NET already prevents this access  
and that it's only an issue when using Winsock via the native API.  But if  
you're seeing a fatal exception from a Socket and yet are still able to  
use the Socket for i/o after the exception, I doubt this is a legal use of  
the Socket.

Of course, without a concise-but-complete code example, it's impossible to  
make any specific, concrete statements about what you should or should not  
do.  If you want a good answer, you need to post a concise-but-complete  
code example that reliably demonstrates the issue.

Pete– Skjul sitert tekst –

– Vis sitert tekst –

To illustrate the issue I have made a small client \ server
application. Code is attach at the end of post.

Here is the output from the client application (arguments are ip,
port, timeout). Shortly after starting the client application the
network cable is unplugged for a few seconds then reconnected again.
It appear that the client during that time gets a few exceptions but
then manages to continue sending and recving packets from server. It
appear like the exceptions are "non-fatal" and does not warrent a
reconnect.

Appreciate any input and please let me know if anything is unclear.

C:\Temp>client 157.237.193.87 6789 2000
Client send ID=421, len=5, data=10 20 11 22 33
Client recv ID=124, len=5, data=77 88 66 72 83
Client send ID=421, len=5, data=10 20 11 22 33
Client recv ID=124, len=5, data=77 88 66 72 83
Client send ID=421, len=5, data=10 20 11 22 33
IOExceptionUnable to read data from the transport connection
Stack
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32
offset, Int32 size)
at Client.Program.Main(String[] args) Client\Program.cs:line 40
SocketInnerException10060

Client send ID=421, len=5, data=10 20 11 22 33
IOExceptionUnable to read data from the transport connection:
Stack at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32
offset, Int32 size)
at Client.Program.Main(String[] args) in Client\Program.cs:line 40
SocketInnerException10035

Client send ID=421, len=5, data=10 20 11 22 33
IOExceptionUnable to read data from the transport connection
Stack at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32
offset, Int32 size)
at Client.Program.Main(String[] args) in Client\Program.cs:line 40
SocketInnerException10035

Client send ID=421, len=5, data=10 20 11 22 33
Client recv ID=124, len=5, data=77 88 66 72 83
Client send ID=421, len=5, data=10 20 11 22 33
IOExceptionUnable to read data from the transport connection
Stack at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32
offset, Int32 size)
at Client.Program.Main(String[] args) in Client\Program.cs:line 40
SocketInnerException10035

Client send ID=421, len=5, data=10 20 11 22 33
Client recv ID=124, len=5, data=77 88 66 72 83
Client send ID=421, len=5, data=10 20 11 22 33
Client recv ID=124, len=5, data=77 88 66 72 83
Client send ID=421, len=5, data=10 20 11 22 33
Client recv ID=124, len=5, data=77 88 66 72 83
Client send ID=421, len=5, data=10 20 11 22 33
Client recv ID=124, len=5, data=77 88 66 72 83
Client send ID=421, len=5, data=10 20 11 22 33
Client recv ID=124, len=5, data=77 88 66 72 83
Client send ID=421, len=5, data=10 20 11 22 33
Client recv ID=124, len=5, data=77 88 66 72 83

Here is the output from server app (arguments port, timeout)

C:\temp>server 6789 2000
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33
Server send ID=124, len=5, data=77 88 66 72 83
Server recv ID=421, len=5, data=10 20 11 22 33

namespace Server
{
class Program
{
static void Main(string[] args)
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any,
Int32.Parse(args[0]));
TcpListener listener = new TcpListener
(endpoint);
listener.Start();
while (true)
{
Socket s = listener.AcceptSocket();
ClientHandler ch = new ClientHandler(s, Int32.Parse
( args[1]) );
}
}
}

class ClientHandler
{
private Socket client;
private int timeout;

public ClientHandler(Socket client, int timeout)
{
this.timeout = timeout;
this.client = client;
Thread clientThread = new Thread(new ThreadStart
(ClientSession));
clientThread.Start();
}

public void ClientSession()
{
int id = 124;
byte[] buffer = { 0x77, 0x88, 0x66, 0x72, 0x83 };
int length = 5;
NetworkStream stream = null;
try
{
stream = new NetworkStream(client);

while (true)
{
int rxDataCounter = 0;
int receiveBytes = 8;
byte[] recvHeader = new byte[receiveBytes];
while (rxDataCounter < receiveBytes)
{
int localCounter = stream.Read(recvHeader,
rxDataCounter, receiveBytes - rxDataCounter);
if (localCounter == 0)
{
Console.WriteLine("Error Reading Header");
return;
}
rxDataCounter += localCounter;
}

int recv_id = IPAddress.NetworkToHostOrder
(BitConverter.ToInt32(recvHeader, 0));
int recv_len = IPAddress.NetworkToHostOrder
(BitConverter.ToInt32(recvHeader, 4));

rxDataCounter = 0;
byte[] recvData = new byte[recv_len];
while (rxDataCounter < recv_len)
{
int localCounter = stream.Read(recvData,
rxDataCounter, recv_len - rxDataCounter);
if (localCounter == 0)
{
Console.WriteLine("Error Reading data");
return;
}
rxDataCounter += localCounter;
}

Console.WriteLine(string.Format("Server recv ID=
{0}, len={1}, data={2}", recv_id, recv_len, DumpBytes(recvData)));

Thread.Sleep(timeout);

Console.WriteLine(string.Format("Server send ID=
{0}, len={1}, data={2}", id, length, DumpBytes(buffer)));
stream.Write(BitConverter.GetBytes
(IPAddress.HostToNetworkOrder(id)), 0, 4);
stream.Write(BitConverter.GetBytes
(IPAddress.HostToNetworkOrder(length)), 0, 4);
stream.Write(buffer, 0, 5);
}
}
catch (IOException io)
{
Console.WriteLine("IOException" + io.Message);
Console.WriteLine("Stack" + io.StackTrace);
SocketException se = io.InnerException as
SocketException;
if (se != null) Console.WriteLine
("SocketInnerException" + se.NativeErrorCode.ToString());
}
finally
{
if (stream != null) stream.Close();
}
}

public static string DumpBytes(byte [] buffer)
{
System.Text.StringBuilder builder = new StringBuilder();
for (int i = 0; i < buffer.Length; i++)
{
builder.AppendFormat("{0:X2} ", buffer[i]);
}
return builder.ToString();
}
}
}


namespace Client
{
class Program
{
static void Main(string[] args)
{
int timeout = Int32.Parse(args[2]);
TcpClient tcpClient = new TcpClient();
tcpClient.NoDelay = true;
tcpClient.ReceiveTimeout = 5000;
tcpClient.Connect(args[0], Int32.Parse(args[1]));
Stream stream = tcpClient.GetStream();

int id = 421;
byte[] buffer = { 0x10, 0x20, 0x11, 0x22, 0x33 };
int length = 5;

while(true)
{
try
{
Console.WriteLine(string.Format("Client send ID=
{0}, len={1}, data={2}", id, length, DumpBytes(buffer)));
stream.Write(BitConverter.GetBytes
(IPAddress.HostToNetworkOrder(id)), 0, 4);
stream.Write(BitConverter.GetBytes
(IPAddress.HostToNetworkOrder(length)), 0, 4);
stream.Write(buffer, 0, 5);

int rxDataCounter = 0;
int receiveBytes = 8;
byte[] recvHeader = new byte[receiveBytes];
while (rxDataCounter < receiveBytes)
{
int localCounter = stream.Read(recvHeader,
rxDataCounter, receiveBytes - rxDataCounter);
if (localCounter == 0)
{
Console.WriteLine("Error Reading Header");
return;
}
rxDataCounter += localCounter;
}

int recv_id = IPAddress.NetworkToHostOrder
(BitConverter.ToInt32(recvHeader, 0));
int recv_len = IPAddress.NetworkToHostOrder
(BitConverter.ToInt32(recvHeader, 4));

rxDataCounter = 0;
byte[] recvData = new byte[recv_len];
while (rxDataCounter < recv_len)
{
int localCounter = stream.Read(recvData,
rxDataCounter, recv_len - rxDataCounter);
if (localCounter == 0)
{
Console.WriteLine("Error Reading data");
return;
}
rxDataCounter += localCounter;
}

Console.WriteLine(string.Format(
"Client recv ID={0}, len={1}, data={2}",
recv_id, recv_len, DumpBytes(recvData)));

}
catch (IOException io)
{
Console.WriteLine("IOException" + io.Message);
Console.WriteLine("Stack" + io.StackTrace);
SocketException se = io.InnerException as
SocketException;
if (se != null) Console.WriteLine
("SocketInnerException" + se.NativeErrorCode.ToString());
}
Thread.Sleep(timeout);
}
}

public static string DumpBytes(byte[] buffer)
{
System.Text.StringBuilder builder = new StringBuilder();
for (int i = 0; i < buffer.Length; i++)
{
builder.AppendFormat("{0:X2} ", buffer[i]);
}
return builder.ToString();
}
}
}
.



Relevant Pages

  • Re: Linux 2.6.29.4
    ... static int is_efer_nx ... if (ret) ... struct ftdi_private { ... the specific security attributes of the socket ...
    (Linux-Kernel)
  • [PATCH] paccept, socket, socketpair w/flags
    ... there is a helper function to convert the new socket flags into ... socket() and socketpair. ... static int status; ... int fd1, fd2, err; ...
    (Linux-Kernel)
  • Re: An existing connection was forcibly closed by the remote host...
    ... EndReceivewill throw "Can't access disposed object" exception whenever the connection is terminated. ... In MS .NET Socket implementation there is no mechanism for the socket object to signal to the main thread that it is about to be disposed. ... public Socket ClientSocket ...
    (microsoft.public.dotnet.framework.compactframework)
  • Re: "invalid handle", sockets, threads and garbage collector
    ... your IntPtr value happens to coincide with a reference. ... The exception contains "invalid handle" message. ... Socket constructor problem ... finalization means closing the handle to resource. ...
    (microsoft.public.dotnet.framework.clr)
  • [PATCH] socket, socketpair w/flags, accept4
    ... helper function to convert socket flags into file flags. ... int status = 0; ... puts; ... int fd1, fd2, err; ...
    (Linux-Kernel)

Loading