111,129
社区成员
发帖
与我相关
我的任务
分享 public byte[] SSend(byte[] tosend, out SocketError err, int timeout = 1000)
{
err = SocketError.Success;
if (!_connected || _socket == null || !_socket.Connected)
{
err = SocketError.NotConnected;
IsConnected = false;
return null;
}
lock (this)
{
if (_socket == null) return null;
try
{
_socket.Send(tosend);
_recvBuffer = new byte[BUFF_SIZE];
if (_DEBUG) log.DebugFormat("> {0,3}: {1}", tosend.Length, ValueHelper.BytesToHexStr(tosend));
_sendTimeoutEvent.Reset();
_recvLen = 0;
IAsyncResult iar = _socket.BeginReceive(_recvBuffer, 0, BUFF_SIZE, SocketFlags.None, out err,
new AsyncCallback(receiveCallback), _socket);
if (!_sendTimeoutEvent.WaitOne(timeout, false))
{
_socket.EndReceive(iar);
//Error = string.Format("超时: {0}", timeout);
//log.ErrorFormat("< 超时: {0}", timeout);
}
if (_recvLen > 0)
{
if (_DEBUG)
log.DebugFormat("< {0,3}: {1}", _recvLen, ValueHelper.BytesToHexStr(_recvBuffer, _recvLen));
}
byte[] outBuff = new byte[_recvLen];
Array.Copy(_recvBuffer, outBuff, _recvLen);
return outBuff;
}
catch (Exception e)
{
Error = string.Format("异常: {0}", e.Message);
log.ErrorFormat("SSend erro: {0}", e.Message);
return null;
}
finally
{
}
}
}
private void receiveCallback(IAsyncResult ar)
{
try
{
_recvLen = _socket.EndReceive(ar);
}
catch (Exception e)
{
Error = string.Format("异常: {0}", e.Message);
//log.ErrorFormat("< 错误: {0}", e.Message);
}
finally
{
_sendTimeoutEvent.Set();
}
}void SendMessage<M,T>(Socket client, M message, Action<T> callback, Action tmeout);的方法来发送消息,它发送消息之后(瞬间)就结束了当前线程了,然后当相同的 client 收到消息时会内存中事先注册、保存的数据中找到对应的callback 而再次触发回调事件。并且主线程可能每隔一段时间(例如1分钟)去清理一下超时未回复的注册数据,回调其 timeout 委托方法。如果你在通讯协议上有“顺序编号”字段,那么就算是发送方以顺序“1、2、3、4、5”连续发了5条指令,而接收方以“1、4、3、5、2”顺序返回的结果,这个 SendMessage 方法流程也能够正确地回调 callback或者是 timeout委托,而不会搞错乱了。
这里最为关键地是,它的流程不搞什么 _sendTimeoutEvent 这种东西!它不使用一个拖死、阻塞线程的策略去设计程序,它是真正异步的流程,而不是用异步操作编程语句去偷运同步顺序编程思路。实际上当发送消息时并不去“阻塞”线程,因此这是真异步,不是伪异步。