Can I rely on DataAvailable for an SSL-wrapped networkstream? - c#

I'm dealing with an application that does a lot of asynchronous reading. To improve performance, I'd like to directly do a synchronous call to Read from an SslStream provided that the call does not block.
The SslStream itself does not provide a DataAvailable property like the underlying NetworkStream does.
So, given that I know that it's a wrapped network stream being read, will the true in DataAvailable guarantee that the call to the SslStream won't cause a block?
Like this:
public void Read(NetworkStream netStream, SslStream sslStream)
{
// given that netStream is the inner stream of sslStream
if (netStream.DataAvailable)
{
// Will not block
sslStream.Read(...);
}
else
{
// Would block
sslStream.Read(...);
}
}
The SslStream is already authenticated and ready to go. I'm not sure if there are any additional overhead apart from the encrypting/decrypting. I assume the answer is reliant on if the SslStream requires a read of more than one byte from the underlying stream in order to read one encrypted byte.

No it doesn't guarantee that, because there are SSL Records at the next layer down, and you may not have received an entire one yet, and cryptologically speaking you can't do anything until you have it all, as you first have to check the MAc for integrity purposes.
But more to the point, I question the whole strategy. Just issue the reads as you need them in normal code: don't try to guess which mode will work best in each situation. The SSL overhead will probably swamp the sync/async difference, and the network bandwidth limitation will swamp them both.

It depends on the cipher in use- endpoints using RC4 or another stream cipher are more likely to be decryptable one byte at a time, but no guarantees. An endpoint configured for DES or other block ciphers will wait until a full block is available.
You could do some screwy stuff with a peekable intermediate buffering stream and try to make sure you've got a reasonable block size before making a blocking read, but that's nasty.
If you absolutely can't block, I'd stick to BeginRead and a completion delegate.

Related

C# Socket.Send( ): does it send all data or not?

I was reading about sockets from a book called "C# Network Programming" by Richard Blum. The following excerpt states that the Send() method is not guaranteed to send all the data passed to it.
byte[] data = new byte[1024];
int sent = socket.Send(data);
On the basis of this code, you might be tempted to presume that the
entire 1024-byte data buffer was sent to the remote device... but this
might be a bad assumption. Depending on the size of the internal TCP
buffer and how much data is being transferred, it is possible that not
all the data supplied to the Send() mehtod was actually sent.
However, when I went and looked at the Microsoft documentation https://msdn.microsoft.com/en-us/library/w93yy28a(v=vs.110).aspx it says:
If you are using a connection-oriented protocol, Send will block until
all of the bytes in the buffer are sent, unless a time-out was set
So which is it? The book was published in 2004, so has it changed since then?
I'm planning to use asynchronous sockets, so my next question is, would BeginSend() send all data?
All you had to do was read the rest of the exact same paragraph you quoted. There's even an exception to your quote given in the very same sentence.
If you are using a connection-oriented protocol, Send will block until all of the bytes in the buffer are sent, unless a time-out was set by using Socket.SendTimeout. If the time-out value was exceeded, the Send call will throw a SocketException. In nonblocking mode, Send may complete successfully even if it sends less than the number of bytes in the buffer. It is your application's responsibility to keep track of the number of bytes sent and to retry the operation until the application sends the bytes in the buffer.
For BeginSend, the behavior is also described:
Your callback method should invoke the EndSend method. When your application calls BeginSend, the system will use a separate thread to execute the specified callback method, and will block on EndSend until the Socket sends the number of bytes requested or throws an exception.
That's not a very nice design and defeats the whole point of a callback! Consider using SendAsync instead (and then you still need to check the BytesTransferred property).
Both of the resources you quoted are correct. I think the wording could have been better though.
Inthe docs, MSDN it is also written that
There is also no guarantee that the data you send will appear on the
network immediately. To increase network efficiency, the underlying
system may delay transmission until a significant amount of outgoing
data is collected.
So Send method is blocking until underlying system has had room to buffer your data for a network send.
A successful completion of the Send method means that the underlying
system has had room to buffer your data for a network send.

Thread-lock by ParameterInstance.lockObject, does it work?

I've googled far and wide and found no answer to this. I am programming my own little Tcp library to make it easy for myself. On the server I have a 'ConnectedClient' object that has a socket and a network stream. On the server static class I have a Send function that sends a length-prefixed stream. I want the stream to be thread safe, but for each client. Would this work for that?
Send(ConnectedClient client, ...(rest of parameters nor relevant))
{
lock (client.lockObject)
{
// Writing to stream thread-safely I hope...
}
}
I hope I made myself clear enough, if not, just ask for more details.
It looks like you are writing some kind of multiplexer. Indeed, that should work fine as long as you write an entire payload (and length-prefix) within a single lock, and as long as the lockObject is representative of the mutual-exclusive resource (i.e. must be a common lockObject for all clients that we don't want to collide).
Perhaps the trickier question is: are you going to read the reply within that method (success/return-value/critical-fail), or are you going to read the reply asynchronously, and let the next writer write to the stream while the first message is flying...
For comparison, when writing BookSleeve (a redis multiplexer, full source available if you want some reference code), I chose a different strategy: one dedicated thread to do all the writing to the thread, with all the callers simply appending to a thread-safe queue; that way, even if there is a backlog of work, the callers aren't delayed.

Ignoring incoming data in TcpClient / NetworkStream

For communication with some third-party software, I need to establish an unidirectional connection over TCP. My software only needs to send data to the other side and never will read any data.
Currently I'm using the TcpClient. What would happen if there are incoming packets nonetheless and I never read them? Would they pile up somewhere and lead to some errors or the like? How would I configure the TcpClient to ignore or discard all incoming data?
The whole design is not exactly what I would do, but I can't change the other software and need to bear with this.
Some nice hints on the bits inside a TcpClient would be very helpful!
I think some of the data will be buffered, waiting for you to read it. Not sure how large the buffer size is, however. I don't think it will lead to errors immediately, but if the sender is expecting to be able to write, at some point the write may time out and the other party may choose to close the connection.
Nothing will happen from your point of view. Data will be discarded.

C#: SSL with SocketAsyncEventArgs?

I'm developing a socket server using C# .NET. I'm using the async model provided by the SocketAsyncEventArgs class, because it must be a high performance server to support many connections in short periods of time. Next, I want to secure the communication between
clients and server, and I think I could use SSL.
Is there any way of using SSL with the SocketAsyncEventArgs model? I know .NET has the SslStream class for SSL securing, but I need to use SocketAsyncEventArgs for high performance.
Is it possible to use SSL in an upper level, without implementing it in the server code?
Thanks in advance.
Not sure if anyone cares anymore since this is so old but I needed to do just that this week and could not find anything on the internet that met my needs. Maybe there is something new in the framework that does this that I was unable find... Regardless, I would post source code but since I wrote it for my company and they tend to frown on that, I'll just outline the approach I took:
Since SslStream takes a stream in the constructor, I implemented my own Stream subtype with an underlying MemoryStream for reads and another for writes. I also pass in the TcpClient to this object as well.
I used the TcpClient to do the handshake for setting up the SSL connection. After authenticating the server or client depending on how I am using it, I then use my two MemoryStreams for the SslStream read/writes.
So for Async writes, I first write my payload to the SslStream which populates my MemoryStream for writing with encrypted data. With the encrypted data from the MemoryStream, I populate the SocketAsyncEventArgs buffer and call the TcpClient SendAsync method. For reads, it's pretty much the opposite.
I can't say it particular excites me to move the data like that but as long as you don't let your MemoryBuffer objects get reallocated constantly, it's not a performance issue. At least this way, I can use just the framework and my own code without relying on third party software.
You can take third-party implementation of SSL/TLS protocol, such as our SecureBlackbox, and use it with any transport, including .NET Sockets in asynchronous mode. SSL server component of SecureBlackbox doesn't have it's own socket, instead it fires events, in whose handlers you write your socket-related code. This way you an plug any transport, even non-socket one.
I think I may have found a project that provides this.
https://sourceforge.net/projects/socketservers/
I'm still playing with it and am bumping into an issue loading the server certificate, however, looking through the source code it looks promising.
One aspect I'm unsure about is that it p/invokes to secur32.dll rather than being a pure c# implementation, so I'm not sure what the memory/performance impact of that is.
The details on the sourceforge project page are sparse as to what the goal of the project is.

TcpClient.GetStream().Read() vs. TcpClient.Client.Receive()

.NET allows two very similar ways to "read" from the network (assuming TCP connection):
1. TcpClient.GetStream().Read()
2. TcpClient.Client.Receive()
By looking at NetworkStream source code - it seems that it's an extra wrapper over the underlying socket, which eventually calls Socket methods.
Question: what's the benefit of using "indirect" NetworkStream variation (#1), instead of using direct wrapper provided by Socket implementation?
Thank you,
Boris.
There is, in fact, a pretty clear benefit of using the first option (TcpStream and not Socket). The benefit is that stream API is more flexible when different underlying implementations are needed at for the same program.
For example, a code which sometimes may use SSL and sometimes may not use it, can switch between SslStream and TcpStream with no changes to the calling code. This is something which is much harder to accomplish using only plain Socket API.
Nothing, really. It's just that sometimes it's more convenient to use a Stream.
To me, a successful Socket.Receive operation with zero bytes received tells you that connection is closed.

Categories