在写 C# socket 的时候发现 socket 连接无法设置超时时间,需要15s才能超时返回。百度一下发现也没有实现的比较好的代码。
因此,才有了下面这段 socket 连接超时的代码,这段代码已经应用到实际的项目中,并且运行稳定。
如果你有更好的实现方案可以给我留言。
class Socket2 : IComunication
{
static IPEndPoint ipe;
static byte[] sendBytes = new byte[1400];
static byte[] recBytes = new byte[1400];
volatile static Socket socket = null;
static System.Threading.Timer readTimer = null;
static int readOverTime;
static bool ReadOK;
static System.Threading.Timer connectTimer = null;
static int connectOverTime;
public Socket2()
{
readTimer = new System.Threading.Timer(OnReadTimeUp, null, Timeout.Infinite, Timeout.Infinite);
object obj = Global.Config.Read("ReadOverTime");
if (obj == null || !int.TryParse(obj.ToString(), out readOverTime))
{
readOverTime = 3000;
}
obj = Global.Config.Read("ConnectOverTime");
if (obj == null || !int.TryParse(obj.ToString(), out connectOverTime))
{
connectOverTime = 3000;
}
}
private static void OnConnectTimeUp(object obj)
{
StateObject stateObject = (StateObject)obj;
lock (connectTimer)
{
if (stateObject.socket != null)
{
stateObject.socket.Close();
stateObject.socket = null;
socket = null;
}
}
}
private static void OnReadTimeUp(object obj)
{
ReadOK = false;
socket.Close();
}
public bool Start()
{
try
{
if (socket == null)
{
string host = Global.Config.Read("DriverIP").ToString();
int port = Convert.ToInt32(Global.Config.Read("DriverPort"));
IPAddress ip = IPAddress.Parse(host);
ipe = new IPEndPoint(ip, port);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.DontFragment = false;
socket.ExclusiveAddressUse = true;
socket.UseOnlyOverlappedIO = false;
socket.SendBufferSize = 1500;
socket.ReceiveBufferSize = 1500;
socket.ReceiveTimeout = readOverTime;
socket.SendTimeout = readOverTime;
// 设置连接超时计时器
StateObject so = new StateObject();
so.socket = socket;
//socket.Connect(ipe);
connectTimer = new System.Threading.Timer(OnConnectTimeUp, so, Timeout.Infinite, Timeout.Infinite);
connectTimer.Change(connectOverTime, Timeout.Infinite);
socket.BeginConnect(ipe, new AsyncCallback(ConnectCallback), so);
autoEventConnect.WaitOne();
}
return true;
}
catch (SocketException e)
{
Global.log.Debug(e);
socket.Close();
socket = null;
return false;
}
catch (Exception e)
{
if (socket != null)
{
socket.Close();
}
socket = null;
return false;
}
}
AutoResetEvent autoEventConnect = new AutoResetEvent(false);
private void ConnectCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
StateObject stateObject = (StateObject)ar.AsyncState;
lock (connectTimer)
{
try
{
if (stateObject.socket != null)
{
// Complete the connection.
stateObject.socket.EndConnect(ar);
connectTimer.Change(Timeout.Infinite, Timeout.Infinite);
connectTimer.Dispose();
}
}
catch (Exception e)
{
if (stateObject.socket != null)
{
stateObject.socket.Close();
}
stateObject.socket = null;
stateObject.reciveBuffer = null;
stateObject.sendBuffer = null;
stateObject = null;
}
}
autoEventConnect.Set();
}
public bool Stop()
{
if (socket != null)
{
socket.Close();
}
socket = null;
return true;
}
public bool Write()
{
try
{
if (socket != null)
{
buildSendBytes();
socket.NoDelay = true;
int n = socket.Send(sendBytes, sendBytes.Length , SocketFlags.None);
if (n != sendBytes.Length)
{
Global.log.Debug("send error 需要发送的字节数 " + "实际发送的字节数" + sendBytes.Length + ":" +n);
}
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
Global.log.Debug("Error Send");
Global.log.Debug(e);
if (socket != null)
{
socket.Close();
socket = null;
}
return false;
}
}
public bool Read()
{
try
{
if (socket != null)
{
StateObject so = new StateObject();
so.socket = socket;
so.reciveBuffer = recBytes;
// 设置读超时计时器
readTimer.Change(readOverTime, Timeout.Infinite);
socket.BeginReceive(recBytes, 0, recBytes.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), so);
// 接受完成
autoEvent.WaitOne();
readTimer.Change(Timeout.Infinite, Timeout.Infinite);
buildRecBytes();
// 需要添加读超时返回 false
if (ReadOK == true)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
catch (Exception e)
{
Global.log.Debug(e);
return false;
}
}
AutoResetEvent autoEvent = new AutoResetEvent(false);
public class StateObject
{
public Socket socket = null;
public byte[] reciveBuffer = null;
public byte[] sendBuffer = null;
}
volatile int bytesRecieved = 0;
public void ReceiveCallback(IAsyncResult ar)
{
StateObject state = null;
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
state = (StateObject)ar.AsyncState;
// Read data from the remote device.
int bytesRead = state.socket.EndReceive(ar);
if (bytesRead > 1400)
{
Global.log.Debug("bytesRead > 1400 :" + bytesRead);
}
if (bytesRead > 0)
{
bytesRecieved += bytesRead;
if (bytesRecieved < recBytes.Length)
{
state.socket.BeginReceive(state.reciveBuffer, bytesRecieved, state.reciveBuffer.Length - bytesRecieved, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
}
if (bytesRecieved == recBytes.Length)
{
bytesRecieved = 0;
ReadOK = true;
autoEvent.Set();
}
}
else
{
state.socket.Close();
state.socket = null;
socket = null;
state.reciveBuffer = null;
state.sendBuffer = null;
state = null;
ReadOK = false;
autoEvent.Set();
}
}
catch (Exception e)
{
Global.log.Debug("Error Recieve");
Global.log.Debug(e);
if (state.socket != null)
{
state.socket.Close();
state.socket = null;
socket = null;
}
state.reciveBuffer = null;
state.sendBuffer = null;
state = null;
ReadOK = false;
autoEvent.Set();
}
}
public bool ReadArray()
{
throw new NotImplementedException();
}
public bool WriteArray()
{
throw new NotImplementedException();
}
}
浙公网安备 33010602011771号