Socket 编程经验谈—如何处理socket连接后服务器端或客户端的断开

  • Post author:
  • Post category:其他


现象:服务器端等待客户断连接,当socket连接建立后,如果客户端异常断开,服务器会抛出异常,从而导致程序运行中断

目标:希望服务器一直等待连接,客户端中断后程序不退出,而客户端重新恢复后可以继续保持连接

代码:

public class Receive

{


public static byte[] buffer= new byte[1024];

public static ManualResetEvent socketEvent = new ManualResetEvent(false);

public static Socket sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

public static Socket handler = null;

public static string ClientBroken = “An connection was forcibly closed by the remote host”;

public static void receive()

{


try

{


Console.WriteLine(“Main ThreadID:” + AppDomain.GetCurrentThreadId());

byte[] bytes = new byte[1024];

IPAddress ipAddr = IPAddress.Parse(“127.0.0.1”);

int Port = 10001;

IPEndPoint EPServer = new IPEndPoint(ipAddr, Port);

//Binding a socket

sListener.Bind(EPServer);

//Start listening

sListener.Listen(10);

while(true)

{


if (handler==null)

{


//first must make a connect

Console.WriteLine(“waiting for a connection…”);

//asychronous function for accepting connections

sListener.BeginAccept(new AsyncCallback(AcceptCallback), sListener);

socketEvent.WaitOne();

handler.BeginReceive(buffer,0,buffer.Length,0,new AsyncCallback(ReceiveCallback),handler);

socketEvent.WaitOne();

}

else

{


Console.WriteLine(“waiting next message…”);

socketEvent.Reset();

handler.BeginReceive(buffer,0,buffer.Length,0,new AsyncCallback(ReceiveCallback),handler);

socketEvent.WaitOne();

}

}

Console.ReadLine();

}

catch (Exception e)

{


Console.WriteLine(e.ToString());

}

Console.ReadLine();

}


public static void AcceptCallback(IAsyncResult ar)

{


try

{


Console.WriteLine(“AcceptCallback Thread ID:” + AppDomain.GetCurrentThreadId());

Socket listener = (Socket)ar.AsyncState;

//new socket

handler = listener.EndAccept(ar);

handler.BeginReceive(buffer,0,buffer.Length,0,new AsyncCallback(ReceiveCallback),handler);

}

catch (Exception e)

{


Console.WriteLine(e.ToString());

}

}


public static void ReceiveCallback(IAsyncResult ar)

{


string err_message=null;

try

{


Console.WriteLine(“ReceiveCallback Thread ID:” + AppDomain.GetCurrentThreadId());

string content = String.Empty;

handler = (Socket)ar.AsyncState;

int bytesRead = handler.EndReceive(ar);

//if there is some data…

if (bytesRead>0)

{


//append it to the main string

content += Encoding.ASCII.GetString(buffer,0,bytesRead);

//if we encounter the end of message character

if (content.IndexOf((char)3)> -1 || content.IndexOf((char)16)>-1)

{


Console.WriteLine(“Read “+content.Length+” bytes from socket. /n Data:”+content);

socketEvent.Set();

}

else

{


//otherwise receive the remaining data

handler.BeginReceive(buffer,0,buffer.Length,0,new AsyncCallback(ReceiveCallback),handler);

}

}

}

catch(Exception e)

{


err_message = e.Message;

if (err_message.IndexOf(“An existing connection was forcibly closed by the remote host”)> -1)

{


Console.WriteLine(“An existing connection was forcibly closed by the remote host”);

//handler.Shutdown(SocketShutdown.Both);

//handler.Close();

Console.WriteLine(“waiting for a connection…”);

//asychronous function for accepting connections

sListener.BeginAccept( new AsyncCallback(AcceptCallback), sListener);

}

else

{


Console.WriteLine(e.ToString());

}

}

}

}

说明:关键在于最后这段的异常处理,接收中断后,服务器端重新等待接收。

现象:客户端与服务器连接,当socket连接建立后,如果服务器端异常断开,客户端会抛出异常,从而导致程序运行中断

目标:希望客户端出现提示,服务器端中断后程序不退出,而服务器端重新恢复后可以继续保持连接

代码:

public class AsyncComm

{


public static string theResponse = “”;

public static byte[] buffer = new byte[1024];

public static ManualResetEvent socketEvent = new ManualResetEvent(false);

public static Socket sClient= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

public static IPEndPoint EPServer = new IPEndPoint(IPAddress.Parse(“127.0.0.1”), 10001);

public static void send(string data)

{


byte[] byteData=null;

byteData = Encoding.ASCII.GetBytes(data);

try

{


if (!sClient.Connected)

{


Console.WriteLine(System.DateTime.Now.ToString(“yyyy-MM-dd HH:mm:ss:ffff”)+” “+”Connect begining……”);

sClient.BeginConnect(EPServer, new AsyncCallback(ConnectCallback),sClient);

socketEvent.WaitOne();

}

sClient.BeginSend(byteData,0,byteData.Length,0,new AsyncCallback(SendCallback),sClient);

socketEvent.WaitOne();

}

catch (Exception e)

{


Console.WriteLine(“Server side is broken…”);

socketEvent.Reset();

return;

}

}

public static void ConnectCallback(IAsyncResult ar)

{


try

{


Thread thr = Thread.CurrentThread;

Console.WriteLine(“ConnectCallback Thread State:” + AppDomain.GetCurrentThreadId());

Socket sClient = (Socket)ar.AsyncState;

sClient.EndConnect(ar);

Console.WriteLine(“Socket connected to ” + sClient.RemoteEndPoint.ToString());

socketEvent.Set();

}

catch (Exception ex)

{


Console.WriteLine(System.DateTime.Now.ToString(“yyyy-MM-dd HH:mm:ss:ffff”)+”||”+AppDomain.GetCurrentThreadId()+”||3–Level 3 Server connection is broken, waiting for Level 3 Server connection……”);

sClient= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

socketEvent.Set();

}

}

receive函数相同,可以参照写出

说明:

在每次发送或接收时检测当前socket是否连接,如果没有连接,就启动连接,并阻塞线程等待ConnectCallback的返回


http://community.csdn.net/Expert/topic/3638/3638505.xml?temp=.2154199


wangsaokui (无间道III(终极无间))