Method of using keep-alive to handle the abnormal disconnection of socket network in C #

Source: Internet
Author: User
Tags array error code socket time interval
Disconnect | The network recently I am responsible for the development of an IM project, the server and the client adopt TCP protocol connection. The service side uses the C # development, the client uses Delphi development. In the service side development I encountered a variety of network abnormal disconnect phenomenon. In dealing with these anomalies have some experience, now write to share with you.

What is the main reason for the network abnormal disconnection? Summed up there are mainly the following two kinds:

1, client program exception.

In this case, we can handle this very well because the client-side exception exit will cause a Connectionreset socket exception (that is, the 10054 exception in WinSock2) on the server. Just handle this exception on the server side.

2, network link anomaly.

such as: Cable pull out, switch off power, client machine off. When these conditions occur, the server does not receive any exceptions. That way, the code above would not be able to handle the situation. This is done in MSDN, where I post the original MSDN:

If you need to determine the current state of the connection, make a non-blocking, 0-byte Send call. If the call successfully returns or throws a Waewouldblock error code (10035), the socket is still connected, otherwise, the socket is no longer in a connected state.

  However, I found in practical applications that MSDN's approach to this kind of processing in many cases is not valid, can not detect the network has been abnormally disconnected. So what do we do?

We know that TCP has a connection detection mechanism, that is, if the specified time (typically 2 hours) without data transfer, will send a keep-alive datagram to the end, the use of the serial number is the last message sent the last byte of the serial number, on the end if you receive this data, Loopback a TCP Ack, confirming that the byte has been received, so that the connection is not disconnected. If you do not receive a response for a period of time, you will try again, after several retries, send a reset to the end, and then disconnect the connection.

In Windows, the first probe is two hours after the last data is sent, and then every 1 seconds, the probe is detected 5 times, and if no response is received 5 times, the connection is disconnected. But two hours is obviously too long for our project. We must shorten this time. So how do we do that? I'm going to take advantage of the IOControl () function of the socket class. Let's see what this function can do:

Use the IoControlCode enumeration to specify the control code and set the low-level operation mode for the Socket.

Namespaces: System.Net.Sockets
Assembly: System (in System.dll)

Grammar

C#
public int IOControl (
IoControlCode IoControlCode,
Byte[] Optioninvalue,
Byte[] Optionoutvalue
)


Parameters
IoControlCode
A IoControlCode value that specifies the control code for the operation to be performed.

Optioninvalue
An array of type Byte containing the input data required by the operation.

Optionoutvalue
An array of type Byte containing the output data returned by the operation.

return value
The number of bytes in the Optionoutvalue parameter.

Such as:

Socket. IOControl (iocontrolcode.keepalivevalues, inoptionvalues, NULL);

What we need to figure out is the definition of inoptionvalues, which is a struct in C + +. Let's take a look at this structure:

struct tcp_keepalive
... {
U_long OnOff; Whether to enable Keep-alive
U_long KeepAliveTime; How long to start the first probe (in milliseconds)
U_long KeepAliveInterval; Probe time interval (in milliseconds)
};

In C #, we pass directly to the function with a byte array:

UINT dummy = 0;
byte[] inoptionvalues = new byte[marshal.sizeof (dummy) * 3];
Bitconverter.getbytes ((UINT) 1). CopyTo (inoptionvalues, 0);//is enabled keep-alive
Bitconverter.getbytes ((UINT) 5000). CopyTo (Inoptionvalues, marshal.sizeof (dummy)); How long does it begin to detect the first time?
Bitconverter.getbytes ((UINT) 5000). CopyTo (Inoptionvalues, marshal.sizeof (dummy) * 2)//Probe time interval

Specific implementation code:

public static void Acceptthread ()
... {
Thread.CurrentThread.IsBackground = true;
while (true)
... {
UINT dummy = 0;
byte[] inoptionvalues = new byte[marshal.sizeof (dummy) * 3];
Bitconverter.getbytes ((UINT) 1). CopyTo (inoptionvalues, 0);
Bitconverter.getbytes ((UINT) 5000). CopyTo (Inoptionvalues, marshal.sizeof (dummy));
Bitconverter.getbytes ((UINT) 5000). CopyTo (Inoptionvalues, marshal.sizeof (dummy) * 2);
Try
... {
Accept (inoptionvalues);
}
Catch... { }
}
}

private static void Accept (byte[] inoptionvalues)
... {
Socket socket = Public.s_socketHandler.Accept ();
Socket. IOControl (iocontrolcode.keepalivevalues, inoptionvalues, NULL);
UserInfo info = new UserInfo ();
Info.socket = socket;
int id = GetUserID ();
Info. Index = ID;
PUBLIC.S_USERLIST.ADD (ID, info);
Socket. BeginReceive (info. Buffer, 0, info. Buffer.length, Socketflags.none, New AsyncCallback (ReceiveCallback), info);
}

Well, that's a success.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.