小弟最近在写TCP异步编程的程序,发送和接受都是用的回调函数的形式,遇到一个头疼的问题就是在考虑网络连接突然中断的情况时,程序往往需要在客户端发送一条消息之后15秒左右的时间,才会检测到连接中止,捕获connectionAborted异常。那么大家平常都是怎么做的呢
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace _10_TCP模块化编程
{
class ObjectState
{
public Socket client;
public MyTcp obj;
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
class MyTcp
{
public delegate void dReceiver(object sender, string b);
public event dReceiver receive;
public Socket WebHabor;
//private bool connected;
public MyTcp(IPEndPoint iep, dReceiver dEventCall)
{
//接收消息的委托;
receive += dEventCall;
//创建socket连接;
WebHabor = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ObjectState obs = new ObjectState();
obs.obj = this;
obs.client = WebHabor;
WebHabor.BeginConnect(iep, new AsyncCallback(ConnectCallback), obs);
//connected = WebHabor.Connected ? true : false;
Thread.Sleep(10);
if (WebHabor.Connected == true)
{
Receive();
}
else
{
Program.postLog("连接失败,请检查ip和port");
}
}
public static void ExceptionSolver(SocketException sep)
{
switch (sep.SocketErrorCode)
{
case SocketError.NotConnected:
//捕获ip地址输入错误的情况;
Program.postLog("不存在网络连接");
break;
case SocketError.ConnectionAborted:
//在这里处理频繁出现的错误,
//比如IP不对,网线没插
Program.postLog("连接中止");
break;
case SocketError.ConnectionRefused:
//远程主机正在主动拒绝连接;可能是连接的时候ip或port写错了;
Program.postLog("对方不接受连接,更可能是port的原因");
break;
case SocketError.HostUnreachable:
Program.postLog("连接目标不可达");
break;
case SocketError.TimedOut:
//尝试连接ip超时;
Program.postLog("尝试连接ip超时,更可能是ip的原因");
break;
default:
Program.postLog("捕获到" + sep.SocketErrorCode);
//这里直接报错,如果调试的时候出现这里的错误比较多,就移到上面解决,一般问题都是从来不出的
break;
}
}
public void Send(byte[] dataToSend,int byteCount)
{
try
{
WebHabor.BeginSend(dataToSend, 0, byteCount, 0, new AsyncCallback(SendCallback), WebHabor);
//System.Threading.Thread.Sleep(10);//为了让其它线程跑起来;
}
catch (SocketException sep)
{
Program.postLog("在Send这里");
ExceptionSolver(sep);
}
}
public void Receive()
{
byte[] buffer = new byte[256];
ObjectState obs = new ObjectState();
obs.obj = this;//这个传的是MyTcp;
obs.client = WebHabor;
try
{
WebHabor.BeginReceive(obs.buffer, 0, ObjectState.BufferSize, 0, new AsyncCallback(ReceiveCallback), obs);
}
catch (SocketException sep)
{
Program.postLog("在reveive这里");
ExceptionSolver(sep);
}
//receive.Invoke(this, buffer);
}
//beginConnect的回调函数;
private static void ConnectCallback(IAsyncResult ar)
{
ObjectState obs = (ObjectState)ar.AsyncState;
try
{
// Retrieve the socket from the state object.
Socket client = obs.client;
// Complete the connection.
client.EndConnect(ar);
//Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
//连上就连上吧就不发数据了
//MessageBox.Show("Socket connected to " + client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
//connectDone.Set();
}
catch (SocketException sep)
{
//Console.WriteLine(e.ToString());
//MessageBox.Show("connect回调函数出错了" + e.ToString());
/*********************************************************************
*
* 此处需要考察一下连接失败的异常情况。
*
*********************************************************************/
//obs.obj.connected = false;
Program.postLog("在ConnectCallback这里");
ExceptionSolver(sep);
}
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
//System.Threading.Thread.Sleep(10);//为了让其它线程跑起来;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Program.postLog("本次发送" + bytesSent + "个字节");
//Console.WriteLine("Sent {0} bytes to server.", bytesSent);
//MessageBox.Show("Sent " + bytesSent + " bytes to server.");
// Signal that all bytes have been sent.
//sendDone.Set();
}
catch (SocketException sep)
{
//MessageBox.Show("Send回调函数出错了" + e.ToString());
/*********************************************************************
*
* 此处需要考察一下发送失败的异常情况。
*
*********************************************************************/
Program.postLog("在SendCallback这里");
ExceptionSolver(sep);
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
//byte[] buffer = new byte[256];
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
//StateObject state = (StateObject)ar.AsyncState;
//Socket client = state.workSocket;
// Read data from the remote device.
ObjectState objs = (ObjectState)ar.AsyncState;
Socket client = objs.client;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
string getMsg = Encoding.ASCII.GetString(objs.buffer, 0, bytesRead);
//Console.WriteLine("新得到的数据是" + getMsg + "呵呵");
//MessageBox.Show("新得到的数据是" + getMsg);
string msg=Encoding.Default.GetString(objs.buffer, 0, bytesRead);
Program.postLog(msg);
//objs.obj.receive.Invoke(objs.obj, msg);//因为这是静态函数,这个objs.obj实际是MyTcp实例。
//MessageBox.Show(bytesRead.ToString() + "更新数据后:" + state.sb.ToString());
// Get the rest of the data.
client.BeginReceive(objs.buffer, 0, objs.buffer.Length, 0, new AsyncCallback(ReceiveCallback), objs);
}
else
{
//接到0字节说明对方主动断开了连接;
Program.postLog("对方主动断开连接");
}
}
catch (SocketException sep)
{
//MessageBox.Show("Receive回调函数出错了" + e.ToString());
/*********************************************************************
*
* 此处需要考察一下接收失败的异常情况。
*
*********************************************************************/
Program.postLog("在ReceiveCallback这里");
ExceptionSolver(sep);
}
}
}
}
如果要求比较严格的话,你试试加入心跳包的机制呢?