I’ve been contemplating about using TPL dataflow blocks for my socket server, I’ve been running some isolated performance tests using blocks, which doesn’t point to anything special, the only positive thing I can see is the ease of chaining blocks and the asynchronicity. So before I get into implementing it in my code. I would like to know if anyone has used it for any such fast socket servers. Especially I want to know if the following design is viable or not(keeping performance and scalability in mind).
//Please note that class is not the exact code, it is a rough idea. Class Client(Socket socket) { private BufferBlock<byte[]> mDataSendBufferBlock; private ActionBlock<byte[]> mDataSendActionBlock; private TransformBlock<byte[], Packet mIncomingDataStreamBlock; private ActionBlock<Packet> mRawByteArrayConvertorBlock; private SSlSteam socketStream; private async void RcvBytesFromSocket() { var bytesRcvd = socketStream.ReadAsync(SocketEventArgs.Buffer, SocketEventArgs.Offset, SocketEventArgs.Count, mIOCancellationToken); mIncomingDataStreamBlock.SendAsync(buffer, mIOCancellationToken); } private async Task StartSendASync(byte[] data) { if (!mIOCancellationToken.IsCancellationRequested) { task = socketStream.WriteAsync(data, 0, data.Length, mIOCancellationToken); } } private void CreatePipeLineForIncomingDataStream() { mIncomingDataStreamBlock = new TransformBlock<byte[], Packet>(data => ParseBytesToPackets(data), new ExecutionDataflowBlockOptions() { CancellationToken = mIOCancellationToken, BoundedCapacity = 50, MaxDegreeOfParallelism = 1 }); mRawByteArrayConvertorBlock = new ActionBlock<Packet>(packet => doSomething(Packet), new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded, BoundedCapacity = 50 }); mByteStreamToASCOLink = mIncomingDataStreamBlock.LinkTo(mRawByteArrayConvertorBlock); } private void CreatePipeLineForOutgoingDataStream() { mDataSendBufferBlock = new BufferBlock<byte[]>(new DataflowBlockOptions() { BoundedCapacity = 50 }); mDataSendActionBlock = new ActionBlock<byte[]>(bytes => StartSendASync(bytes), new ExecutionDataflowBlockOptions() { CancellationToken = mIOCancellationToken, BoundedCapacity = 50 }); mSendDataLink = mDataSendBufferBlock.LinkTo(mDataSendActionBlock); } }
So this class would we instantiated for each and every new client connected to the server. So All incoming data and data to be sent, for each client will be parsed in its own class. Would this kind of design be scalable and perform well for around 10000 clients?