In your while
loop, you are mixing calls to a TCP layer API with calls to TLS layer API that runs over it. This won't work properly.
The ssl.Socket
property is actually an instance of .NET socket (System.Net.Sockets.Socket
class), which represents the TCP socket that underlies the TlsServerSocket
instance. That underlying socket does not "know" anything about TLS/SSL or about the TlsServerSocket
, and in almost all scenarios involving TlsServerSocket
or TlsClientSocket
, it's best to leave it alone.
The ssl.Socket.Poll
call at the TCP layer implies that you would miss any data that has already been received by the TlsServerSocket
and is waiting in its internal buffer, and the ssl.Socket.Available
property returns the number of bytes available at the TCP level, which also includes the length of TLS packets that don't represent actual data, but are instead part of the TLS protocol itself.
For example, the value of 31 you get when the socket is closed at the client side represents the length of TLS Alert packet that informs the server that the TLS channel has been closed.
A typical server-side while
loop using asynchronous ReceiveAsync
might look like this:
byte[] data = new byte[4096]; // allocate a buffer for incoming data
while (true)
{
// receive data over the TLS socket
int receivedBytes = await ssl.ReceiveAsync(data);
if (receivedBytes == 0)
{
// when ReceiveAsync returns zero, it indicates
// that the connection has been closed and that
// it is time to close it from the server-side
// and exit the 'while' loop
await ssl.DisposeAsync();
break;
}
// otherwise, do something with the data
DoSomething(new ArraySegment<byte>(data, 0, receivedBytes));
}
There is actually no need to call ssl.Socket.Poll
or ssl.Socket.Available
at all.