IO Completion Ports (IOCP) - c#

When I call BeginExecuteReader (SQL) does it use IO Completion Ports? What makes it to be asynchronous? Should I call it from Begin[Operation]() or from the wrapper for IAsyncResult constructor?

does it use IO Completion Ports
Maybe, but that's an implementation detail deep in the native SQL Client's implementation.
Remember the SQL Server ADO.NET calls into the (local) native SQL Server client which will perform communication with the server.
What makes it to be async?
Its implementation. There is more than one way to do this, from approaches which fake it (perform blocking operations with a dedicated worker thread) through to IO Completion Ports and other "true" asynchronous APIs.
Where from should I call it ?
Wherever is right for your design.
for IAsyncResult constructor?
How you use the asynchronous APIs (callback passed to BeginExecuteReader, poll the returned IAsyncResult's IsComplete, wait on IAsyncResult, convert to a Task with TaskFactory.FromAsync, using the Reactive Extensions with Observable.FromAsyncPattern, or something else) is again part of the design of your code.
There are too many possibilities to give any form of guidance.

Whether or not the method uses IO Completion Ports is up to the implementation.
The call is asynchronous if it returns before the work is completed. Obviously that's also up to the implementation.
The standard way to use it would be
{
...
var fs = new FileStream(...); // using FileStream as an example
var data = new byte[100];
var ar = fs.BeginRead(data, 0, 100, MyCallback, new object[] { fs, data });
...
// you can check the IAsyncResult ar for completion,
// or do some work that doesn't depend on the data
}
private void MyCallback(IAsyncResult ar)
{
// AsyncState gets the last parameter from the call to BeginRead
var fs = (FileStream)(((object[])ar.AsyncState)[0]);
var data = (FileStream)(((object[])ar.AsyncState)[1]);
int numberOfBytesRead = fs.EndRead(ar);
// do something with data
}
You could also use a lambda expression as for a callback of course. With lambdas the state doesn't have to be captured manually so you could use it like
var ar = fs.BeginRead(data, 0, 100, result =>
{
int numberOfBytesRead = fs.EndRead(result);
// do something with data
}, null);

Related

Socket.ConnectAsync for windows store application does not like Async

Windows store applications are frustrating to say the least; just close enough to regular .net to get into trouble.
My issue with working in Tasks, await, and Socket.ConnectAsync.
I've got the following code:
public async Task<string> Connect(string hostName, int portNumber)
{
string result = string.Empty;
// Create DnsEndPoint. The hostName and port are passed in to this method.
DnsEndPoint hostEntry = new DnsEndPoint(hostName, portNumber);
// Create a stream-based, TCP socket using the InterNetwork Address Family.
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Create a SocketAsyncEventArgs object to be used in the connection request
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = hostEntry;
// Inline event handler for the Completed event.
// Note: This event handler was implemented inline in order to make this method self-contained.
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate (object s, SocketAsyncEventArgs e)
{
// Retrieve the result of this request
result = e.SocketError.ToString();
// Signal that the request is complete, unblocking the UI thread
_clientDone.Set();
});
// Sets the state of the event to nonsignaled, causing threads to block
_clientDone.Reset();
// Make an asynchronous Connect request over the socket
await _socket.ConnectAsync(socketEventArg);
// Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
// If no response comes back within this time then proceed
_clientDone.WaitOne(TIMEOUT_MILLISECONDS);
return result;
}
And I started added in Async / await to the app to prevent UI issues. But when I went into this function and added the Await to
await _socket.ConnectAsync(socketEventArg);
I get the error:
Error CS1929 'bool' does not contain a definition for 'GetAwaiter' and the best extension method overload 'WindowsRuntimeSystemExtensions.GetAwaiter(IAsyncAction)' requires a receiver of type 'IAsyncAction'
In looking at the docs for ConnectAsync it looks like ConnectAsync is supposed to support await...
Does it not support await?
No, ConnectAsync is not a TAP method, and thus cannot be used with await.
My #1 recommendation for anyone using raw sockets is "don't". If you can, use a REST API (with HttpClient) or a SignalR API. Raw sockets have tons of pitfalls.
If you must use raw sockets (i.e., the other side is using a custom TCP/IP protocol and you don't have the power to fix the situation), then the first thing to note is that the Socket class has three complete APIs all in one class.
The first is the deceptively simple-looking synchronous API (Connect), which I do not recommend for any production code. The second is the standard APM pattern (BeginConnect/EndConnect). The third is a specialized asynchronous pattern that is specific to the Socket class (ConnectAsync); this specialized API is much more complex to use than the standard asynchronous API, and is only necessary when you have chatty socket communication in a constrained environment, and need to reduce the object churn through the garbage collector.
Note that there is no await-compatible API. I haven't spoken to anyone at Microsoft about this, but my strong suspicion is that they simply thought the Socket class had too many members already (3 complete APIs; adding an await-compatible one would add a fourth complete API), and that's why it was skipped over when they added TAP-pattern (await-compatible) members to other types in the BCL.
The correct API to use - easily 99.999% of the time - is the APM one. You can create your own TAP wrappers (which work with await) by using TaskFactory.FromAsync. I like to do this with extension methods, like this:
public static Task ConnectTaskAsync(this Socket socket, EndPoint remoteEP)
{
return Task.Factory.FromAsync(socket.BeginConnect, socket.EndConnect, remoteEP, null);
}
You can then invoke it anywhere on a Socket, as such:
await _socket.ConnectTaskAsync(hostEntry);

async / await or Begin / End with TcpListener?

I've started to build a tcp server which will be able to accept many clients, and receive simultaneously from all of the clients new data.
Until now, I used IOCP for tcp servers which was pretty easy and comfortable,
but this time I want to use the Async / Await tech. that was released in C# 5.0.
The problem is that when I started to write the server using async / await, I figured out that in tcp multiple users server use case, async / await tech. and the regular synchrony methods will work the same.
Here's a simple example to be more specific:
class Server
{
private TcpListener _tcpListener;
private List<TcpClient> _clients;
private bool IsStarted;
public Server(int port)
{
_tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, port));
_clients = new List<TcpClient>();
IsStarted = false;
}
public void Start()
{
IsStarted = true;
_tcpListener.Start();
Task.Run(() => StartAcceptClientsAsync());
}
public void Stop()
{
IsStarted = false;
_tcpListener.Stop();
}
private async Task StartAcceptClientsAsync()
{
while (IsStarted)
{
// ******** Note 1 ********
var acceptedClient = await _tcpListener.AcceptTcpClientAsync();
_clients.Add(acceptedClient);
IPEndPoint ipEndPoint = (IPEndPoint) acceptedClient.Client.RemoteEndPoint;
Console.WriteLine("Accepted new client! IP: {0} Port: {1}", ipEndPoint.Address, ipEndPoint.Port);
Task.Run(() => StartReadingDataFromClient(acceptedClient));
}
}
private async void StartReadingDataFromClient(TcpClient acceptedClient)
{
try
{
IPEndPoint ipEndPoint = (IPEndPoint) acceptedClient.Client.RemoteEndPoint;
while (true)
{
MemoryStream bufferStream = new MemoryStream();
// ******** Note 2 ********
byte[] buffer = new byte[1024];
int packetSize = await acceptedClient.GetStream().ReadAsync(buffer, 0, buffer.Length);
if (packetSize == 0)
{
break;
}
Console.WriteLine("Accepted new message from: IP: {0} Port: {1}\nMessage: {2}",
ipEndPoint.Address, ipEndPoint.Port, Encoding.Default.GetString(buffer));
}
}
catch (Exception)
{
}
finally
{
acceptedClient.Close();
_clients.Remove(acceptedClient);
}
}
}
Now if you see the lines under 'Note 1' and 'Note 2',
It can easily be changed to:
Note 1 from
var acceptedClient = await _tcpListener.AcceptTcpClientAsync();
to
var acceptedClient = _tcpListener.AcceptTcpClient();
And Note 2 from
int packetSize = await acceptedClient.GetStream().ReadAsync(buffer, 0, 1024);
to
int packetSize = acceptedClient.GetStream().Read(buffer, 0, 1024);
And the server will work exactly the same.
So, why using async / await in tcp listener for multiple users if it's the same like using regular synchrony methods?
Should I keep using IOCP in that case? because for me it's pretty easy and comfortable but I am afraid that it will be obsoleted or even no more available in newer .NET versions.
Untill now, i used IOCP for tcp servers which was pretty easy and comfortable, but this time i want to use the Async / Await tech. that was released in C# 5.0.
I think you need to get your terminology right.
Having BeginOperation and EndOperation methods is called Asynchronous Programming Model (APM). Having a single Task (or Task<T>) returning method is called Task-based Asynchronous Pattern (TAP). I/O Completion Ports (IOCP) are a way to handle asynchronous operations on Windows and asynchronous I/O methods using both APM and TAP use them.
What this means is that the performance of APM and TAP is going to be very similar. The big difference between the two is that code using TAP and async-await is much more readable than code using APM and callbacks.
So, if you want to (or have to) write your code asynchronously, use TAP and async-await, if you can. But if you don't have a good reason to do that, just write your code synchronously.
On the server, a good reason to use asynchrony is scalability: asynchronous code can handle many more requests at the same time, because it tends to use fewer threads. If you don't care about scalability (for example because you're not going to have many users at the same time), then asynchrony doesn't make much sense.
Also, your code contains some practices that you should avoid:
Don't use async void methods, there is no good way to tell when they complete and they have bad exception handling. The exception is event handlers, but that applies mostly to GUI applications.
Don't use Task.Run() if you don't have to. Task.Run() can be useful if you want to leave the current thread (usually the UI thread) or if you want to execute synchronous code in parallel. But it doesn't make much sense to use it to start asynchronous operations in server applications.
Don't ignore Tasks returned from methods, unless you're sure they're not going to throw an exception. Exceptions from ignored Tasks won't do anything, which could very easily mask a bug.
After couple of search i found this
Q: It is a list of TCPServer practices but which one is the best practice for managing 5000+ clients each seconds ?
A: my assumption is "Writing async methods" more over if you are working with database same time "Async methods and iterators" will do more
here is the sample code using async/await.
async await tcp server
I think it is easier to build a tcp server using async/await than iocp.

Async/Await and Tasks

Ok, I think I have understood the whole async/await thing. Whenever you await something, the function you're running returns, allowing the current thread to do something else while the async function completes. The advantage is that you don't start a new thread.
This is not that hard to understand as it's somewhat how Node.JS works, except Node uses alot of callbacks to make this happen. This is where I fail to understand the advantage however.
The socket class doesn't currently have any Async methods (that work with async/await). I can of course pass a socket to the stream class, and use the async methods there, however this leaves a problem with the accepting of new sockets.
There are two ways of doing this, as far as I know. In both cases I accept new sockets in an infinite loop on the main thread. In the first case I can start a new task for every socket that I accept, and run the stream.ReceiveAsync within that task. However, won't an await actually block that task, since the task will have nothing else to do? Which again will result in more threads spawned on the threadpool, which again is no better than using synchronous methods inside a task?
My second option is to put all accepted sockets in one of several lists (one list per thread), and inside those threads run a loop, running await stream.ReceiveAsync for every socket. This way, whenever i run into await, stream.ReceiveAsync and start receiving from all other sockets.
I guess my real question is if this is in any way more effective than a threadpool, and in the first case, if it really will be worse than just using the APM methods.
I also know you can wrap APM methods into functions using await/async, but the way I see it, you still get the "disadvantage" of APM methods, with the extra overhead of state machines in async/await.
The async socket API is not based around Task[<T>], so it isn't directly usable from async/await - but you can bridge that fairly easily - for example (completely untested):
public class AsyncSocketWrapper : IDisposable
{
public void Dispose()
{
var tmp = socket;
socket = null;
if(tmp != null) tmp.Dispose();
}
public AsyncSocketWrapper(Socket socket)
{
this.socket = socket;
args = new SocketAsyncEventArgs();
args.Completed += args_Completed;
}
void args_Completed(object sender, SocketAsyncEventArgs e)
{
// might want to switch on e.LastOperation
var source = (TaskCompletionSource<int>)e.UserToken;
if (ShouldSetResult(source, args)) source.TrySetResult(args.BytesTransferred);
}
private Socket socket;
private readonly SocketAsyncEventArgs args;
public Task<int> ReceiveAsync(byte[] buffer, int offset, int count)
{
TaskCompletionSource<int> source = new TaskCompletionSource<int>();
try
{
args.SetBuffer(buffer, offset, count);
args.UserToken = source;
if (!socket.ReceiveAsync(args))
{
if (ShouldSetResult(source, args))
{
return Task.FromResult(args.BytesTransferred);
}
}
}
catch (Exception ex)
{
source.TrySetException(ex);
}
return source.Task;
}
static bool ShouldSetResult<T>(TaskCompletionSource<T> source, SocketAsyncEventArgs args)
{
if (args.SocketError == SocketError.Success) return true;
var ex = new InvalidOperationException(args.SocketError.ToString());
source.TrySetException(ex);
return false;
}
}
Note: you should probably avoid running the receives in a loop - I would advise making each socket responsible for pumping itself as it receives data. The only thing you need a loop for is to periodically sweep for zombies, since not all socket deaths are detectable.
Note also that the raw async socket API is perfectly usable without Task[<T>] - I use that extensively. While await may have uses here, it is not essential.
This is not that hard to understand as it's somewhat how Node.JS works, except Node uses alot of callbacks to make this happen. This is where I fail to understand the advantage however.
Node.js does use callbacks, but it has one other significant facet that really simplifies those callbacks: they are all serialized to the same thread. So when you're looking at asynchronous callbacks in .NET, you're usually dealing with multithreading as well as asynchronous programming (except for EAP-style callbacks).
Asynchronous programming using callbacks is called "continuation-passing style" (CPS). It's the only real option for Node.js but is one of many options on .NET. In particular, CPS code can get extremely complex and difficult to maintain, so the async/await compiler transform was introduced so you could write "normal-looking" code and the compiler would translate it to CPS for you.
In both cases I accept new sockets in an infinite loop on the main thread.
If you're writing a server, then yes, somewhere you will be repeatedly accepting new client connections. Also, you should be continuously reading from each connected socket, so each socket also has a loop.
In the first case I can start a new task for every socket that I accept, and run the stream.ReceiveAsync within that task.
You wouldn't need a new task. That's the whole point of asynchronous programming.
My second option is to put all accepted sockets in one of several lists (one list per thread), and inside those threads run a loop, running await stream.ReceiveAsync for every socket.
I'm not sure why you'd need multiple threads, or any dedicated threads at all.
You seem a bit confused on how async and await work. I recommend reading my own introduction, the MSDN overview, the Task-Based Asynchronous Pattern guidance, and the async FAQ, in that order.
I also know you can wrap APM methods into functions using await/async, but the way I see it, you still get the "disadvantage" of APM methods, with the extra overhead of state machines in async/await.
I'm not sure what disadvantage you're referring to. The overhead of state machines, while non-zero, is negligible in the face of socket I/O.
If you're looking to do socket I/O, you have several options. For reads, you can either do them in an "infinite" loop using APM or Task wrappers around the APM or Async methods. Alternatively, you could convert them into a stream-like abstraction using Rx or TPL Dataflow.
Another option is a library I wrote a few years ago called Nito.Async. It provides EAP-style (event-based) sockets that handle all the thread marshaling for you, so you end up with something simpler like Node.js. Of course, like Node.js, this simplicity means it won't scale as well as a more complex solution.

Calling BeginRead from a NetworkStream

Ok I want to connect to a Socket and read a network stream using the System.Net.Sockets.NetworkStream class. This is what I have so far:
NetworkStream myNetworkStream;
Socket socket;
socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw,
ProtocolType.IPv4);
socket.Connect(IPAddress.Parse("8.8.8.8"), 8888);
myNetworkStream = new NetworkStream(socket);
byte[] buffer = new byte[1024];
int offset = 0;
int count = 1024;
myNetworkStream.BeginRead(buffer, offset, count, ??, ??);
Now I need an AsyncCallback and an Object state to complete my BeginRead method but I'm not even sure if this is going to work. I'm a bit lost at this point! Where do I need to go from here?
Basically, when you call the Begin* method on an asynchronous operation, there needs to be a call to a corresponding End* statement (for more detailed information, see the Asynchronous Programming Overview on MSDN, specifically the section titled "Ending an Asynchronous Operation").
That said, you generally want to pass a method/anonymous method/lambda expression which will do one or two things:
1) Call the corresponding End* method, in this case, Stream.EndRead. This call will not block when called because the callback will not be called until the operation is complete (note that if an exception occurred during the async call then this exception will be thrown when the End* method is called).
2) Possibly start a new asynchronous call. In this case, it's assumed you'll want to read more data, so you should start a new call to Stream.BeginRead
Assuming you want to do #2, you can do the following:
// Declare the callback. Need to do that so that
// the closure captures it.
AsyncCallback callback = null;
// Assign the callback.
callback = ar => {
// Call EndRead.
int bytesRead = myNetworkStream.EndRead(ar);
// Process the bytes here.
// Determine if you want to read again. If not, return.
if (!notMoreToRead) return;
// Read again. This callback will be called again.
myNetworkStream.BeginRead(buffer, offset, count, callback, null);
};
// Trigger the initial read.
myNetworkStream.BeginRead(buffer, offset, count, callback, null);
However, if you are using .NET 4.0, this becomes much easier using the FromAsync method on the TaskFactory class.

How to create C# Compact Framework non-blocking sockets

I am trying to create a non-blocking socket in WM6 C# but I keep getting the following compiler error:
"Synchronous calls are not supported on non-blocking sockets. Set Blocking=true or use the asynchronous methods."
However when I use the BeginReceive() asynchronous methods, the EndReceive() is blocked. Same for BeginSend() and EndSend(). How do you do a non-blocking socket within the compact framework?
Here's my code. I am not using an AsyncCallback method because I want to return the bytesRecv and bytesSent variables.
private void asyncReceive(byte[] recvBytes, int offset, int size, SocketFlags sf)
{
IAsyncResult asyncResult = null;
int recvBytes = 0;
try
{
asyncResult = _socket.BeginSend(sendBytes, offset, size, sf, null, null);
recvBytes = _socket.EndSend(asyncResult); // <-- This blocks even with _socket.Blocking = false;
}
catch (SocketException)
{
//Check SocketException.ErrorCode...
}
return recvBytes;
}
Looks like you're missing the point- the behavior you're seeing is by design. I'd suggest reading up on async programming in .NET (lots of resources- maybe start here). Non-blocking socket reads/writes with BeginXXX will allow you to start the send/receive, then go do something else and be notified by the kernel when it's done (via the AsyncCallback), at which point you'd call the corresponding EndXXX method to get the result. If you call EndXXX right after the BeginXXX call before the operation is complete, it's designed to block until completion.
To get non-blocking behavior, you'll need to break up your code a bit to handle the callback correctly (eg, marshal the result back to your UI, whatever). You won't have the answer as to how many bytes were sent/received until that's actually been done by the underlying kernel bits.

Categories

Resources