Skip to content

Instantly share code, notes, and snippets.

@Aimeast
Created July 29, 2015 13:39
Show Gist options
  • Save Aimeast/24ca4d55943e80af1a84 to your computer and use it in GitHub Desktop.
Save Aimeast/24ca4d55943e80af1a84 to your computer and use it in GitHub Desktop.
#region Socket operations
protected IAsyncResult BeginSocketRead(int length, ApmCallback callback)
{
return BeginSocketIO(new byte[length], callback, _socket.BeginReceive, _socket.EndReceive);
}
protected IAsyncResult BeginSocketWrite(byte[] data, ApmCallback callback)
{
return BeginSocketIO(data, callback, _socket.BeginSend, _socket.EndSend);
}
private IAsyncResult BeginSocketIO(byte[] data, ApmCallback callback, BeginSocket begin, EndSocket end)
{
var apm = new ApmStruct { Data = data, Callback = callback, Begin = begin, End = end };
return begin(data, 0, data.Length, SocketFlags.None, ar => EndSocketIO(ar, end), apm);
}
private void EndSocketIO(IAsyncResult ar, EndSocket end)
{
SocketError errorCode;
var length = end(ar, out errorCode);
var apm = (ApmStruct)ar.AsyncState;
apm.Callback?.Invoke(apm.Data, errorCode);
}
protected delegate IAsyncResult BeginSocket(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state);
protected delegate int EndSocket(IAsyncResult ar, out SocketError err);
protected delegate void ApmCallback(byte[] data, SocketError err);
protected class ApmStruct
{
public byte[] Data;
public ApmCallback Callback;
public BeginSocket Begin;
public EndSocket End;
}
#endregion
#region Socket operations
public byte[] SocketRead(int length)
{
return SocketIO(new byte[length], _socket.Receive);
}
public void SocketWrite(byte[] data)
{
SocketIO(data, _socket.Send);
}
private byte[] SocketIO(byte[] data, Func<byte[], int, int, SocketFlags, int> func)
{
var pos = 0;
var length = data.Length;
while (pos < length)
{
try
{
pos += func(data, pos, length - pos, SocketFlags.None);
}
catch (SocketException ex)
{
if (ex.SocketErrorCode == SocketError.WouldBlock
|| ex.SocketErrorCode == SocketError.IOPending
|| ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
{
Thread.Sleep(30);
}
else
throw;
}
}
return data;
}
#endregion
#region Socket operations
public async Task<byte[]> SocketRead(int length)
{
var data = new byte[length];
var len = await Task.Factory.FromAsync(
_socket.BeginReceive(data, 0, data.Length, SocketFlags.None, null, null),
ar => _socket.EndReceive(ar));
return data;
}
public async Task SocketWrite(byte[] data)
{
var len = await Task.Factory.FromAsync(
_socket.BeginSend(data, 0, data.Length, SocketFlags.None, null, null),
ar => _socket.EndSend(ar));
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment