在无阻塞环境,Socket的SendAsync和ReceiveAsync显得特别另类。他们返回的不是Task而是bool 值。为了与开发环境兼容【其实就是为了使用ContinueWith】,需要将他们封装,返回为Task<int>.
以下为转换函数:
public class SocketTokenInfo
{
public static int SocketMaxWaitTime = 1000 * 60;//Socket一次发送,接收最大的等待时间。单位:毫秒
ByteBuffer Buffer;
System.Net.Sockets.Socket Socket;
System.Net.Sockets.SocketAsyncEventArgs Event;
System.Threading.CancellationTokenSource Cancel;
Exception Error;
Task<int> returnTask;
int returnValue = -1;//GetData时,是接收到的数据长度. GetHttpHead时,是httpheader的结束位置.
int ReceivedBytes()
{
if (Error != null)
throw Error;
return returnValue;
}
void CheckCall()
{
if (Buffer != null)
throw new Exception("ReCall Socket Function when Task not end.");
}
void EndTaskCall()
{
try
{
//Cancel.Dispose();
Event.Dispose();
}
catch { }
Task tmp = returnTask;
Event.UserToken = null;
Event = null;
//Cancel = null;
returnTask = null;
HelperExtend.socketToken.Ended(this);
tmp.Start();
}
Task<int> CreatTask()
{
if (Cancel == null)
{
Cancel = new System.Threading.CancellationTokenSource();
}
returnValue = 0;
Error = null;
Cancel.CancelAfter(SocketMaxWaitTime);
returnTask = new Task<int>(ReceivedBytes, Cancel.Token);
return returnTask;
}
#region 发送数据
public Task<int> SendData(System.Net.Sockets.Socket s, ByteBuffer buf, System.Net.Sockets.SocketAsyncEventArgs e = null)
{
CheckCall();
if (e == null)
e = new System.Net.Sockets.SocketAsyncEventArgs();
Event = e;
e.UserToken = this;
this.Buffer = buf;
Buffer.SocketSendEvent(Event);
this.Socket = s;
Event.Completed += CheckSend;
if (!s.SendAsync(Event))
{
CheckSend(s, Event);
}
return CreatTask();
}
void CheckSend(object sender, System.Net.Sockets.SocketAsyncEventArgs Event)
{
Event.Completed -= CheckSend;
returnValue = Event.BytesTransferred;
this.Buffer.Readed(returnValue);
EndTaskCall();
}
#endregion
#region HttpHead
public Task<int> GetHttpHead(System.Net.Sockets.Socket s, ByteBuffer buf, System.Net.Sockets.SocketAsyncEventArgs e=null)
{
CheckCall();
if (e == null)
e = new System.Net.Sockets.SocketAsyncEventArgs();
Event = e;
Event.UserToken = this;
this.Buffer = buf;
this.Buffer.SocketReceiveEvent(Event);
Socket = s;
Event.Completed += CheckHttp;
if (!s.ReceiveAsync(Event))
{
CheckHttp(s, Event);
}
return CreatTask();
}
void CheckHttp(object sender, System.Net.Sockets.SocketAsyncEventArgs e)
{
if (e.BytesTransferred <= 0)
{//连接已断开.
Event.Completed -= CheckHttp;
this.Error = new Exception("Socket is disconnted before headers are received");
this.EndTaskCall();
return;
}
int oldLen = this.Buffer.Count;//上次检查结束位置.
this.Buffer.Writed(e.BytesTransferred);
int rtVlue = this.Buffer.LineDoubleCheckASC2(oldLen);//检查\r\n\r\n
if (rtVlue < 0)
{//未完成,继续接收数据.
if (!this.Socket.ReceiveAsync(Event))
{
CheckHttp(this.Socket, Event);
}
}
else
{//完成httpHeader的接收
returnValue = rtVlue;
EndTaskCall();
}
}
#endregion
#region GetOnce
//执行一次socket取数据操作.无论是否成功.
public Task<int> GetOnce(System.Net.Sockets.Socket s,ByteBuffer buf, System.Net.Sockets.SocketAsyncEventArgs e=null)
{
CheckCall();
if (e == null)
e = new System.Net.Sockets.SocketAsyncEventArgs();
Event = e;
e.UserToken = this;
this.Buffer = buf;
this.Buffer.SocketReceiveEvent(Event);
Socket = s;
Event.Completed += CheckReceiveRst;
if (!s.ReceiveAsync(Event))
{
CheckReceiveRst(s, Event);
}
return CreatTask();
}
void CheckReceiveRst(object sender, System.Net.Sockets.SocketAsyncEventArgs e)
{
Event.Completed -= CheckReceiveRst;
returnValue = Event.BytesTransferred;
this.Buffer.Writed(Event.BytesTransferred);
EndTaskCall();
}
#endregion
#region GetFixLen
//执行一次socket取数据操作.无论是否成功.
public Task<int> GetFixLength(System.Net.Sockets.Socket s,int ask,ByteBuffer buf, System.Net.Sockets.SocketAsyncEventArgs e = null)
{
CheckCall();
if (e == null)
e = new System.Net.Sockets.SocketAsyncEventArgs();
Event = e;
e.UserToken = this;
this.Buffer = buf;
this.Buffer.SocketReceiveEvent(Event);
Socket = s;
returnValue = ask;
Event.Completed += CheckAskLen;
if (!s.ReceiveAsync(Event))
{
CheckAskLen(s, Event);
}
return CreatTask();
}
void CheckAskLen(object sender, System.Net.Sockets.SocketAsyncEventArgs Event)
{
if(Event.BytesTransferred <= 0)
{
Event.Completed -= CheckAskLen;
this.Error = new Exception("Socket Closed Before Data All");
EndTaskCall();
return;
}
this.Buffer.Writed(Event.BytesTransferred);
if(this.Buffer.Count >= returnValue)
{
Event.Completed -= CheckAskLen;
EndTaskCall();
return;
}
if (!this.Socket.ReceiveAsync(Event))
{
CheckAskLen(this.Socket, Event);
}
}
#endregion
#region All
//接收数据,等待对方断开连接后返回.
public Task<int> GetAllAndClose(System.Net.Sockets.Socket s, System.Net.Sockets.SocketAsyncEventArgs e, ByteBuffer buf)
{
CheckCall();
if (e == null)
e = new System.Net.Sockets.SocketAsyncEventArgs();
Event = e;
Event.UserToken = this;
this.Buffer = buf;
this.Buffer.SocketReceiveEvent(Event);
Socket = s;
Event.Completed += CheckAll;
if (!s.ReceiveAsync(Event))
{
CheckAll(s, Event);
}
return CreatTask();
}
void CheckAll(object sender, System.Net.Sockets.SocketAsyncEventArgs e)
{
if (Event.BytesTransferred <= 0)
{
Event.Completed -= CheckAll;
this.Socket.Shutdown(System.Net.Sockets.SocketShutdown.Both);
this.Socket.Dispose();
return;
}
else
{
this.Buffer.Writed(Event.BytesTransferred);
if (!this.Socket.ReceiveAsync(Event))
{
CheckAll(Socket, Event);
}
}
}
#endregion
public void DoCancel()
{
Cancel.Cancel();
}
}
ByteBuffer 是一个缓冲区管理函数.