So I have a client server model based off of using a TCPClient's stream and turning it into an SSLStream for security purposes, but each time the client wants to send something new to the server, it opens a new TCP connection to the server as the server ends the connection at the end. How would I go about listening for additional requests from the same stream? Not sure how and that's why I'm killing the stream at the end. Sorry if it's confusing, I can revise if not understandable. Thanks!
public void ServerListen()
{
TCPListener Server = new TCPListener(IPAddress.Any, 8001);
while (true)
{
Server.Start();
TCPClient TempClient = Server.AcceptTCPClient();
HandleRequest NewRequest = new HandleRequest(TempClient); // Send to a data handler class and open a separate thread to allow for additional clients to connect
}
}
public class HandleRequest
{
TCPClient WorkingClient;
public HandleRequest(TCPClient TempClient)
{
WorkingClient = TempClient;
(new Thread(new ThreadStart(DoWork))).Start();
}
public static void DoWork()
{
// Do Something Here With Data From Client
ProvideResponse(SomeData);
}
public static void ProvideResponse(object Data)
{
SSLStream SecureStream = new SSLStream(WorkingClient, false); // Kill inner stream after creating a secure connection
SecureStream.AuthenticateAsServer(MyCertificate, false, SslProtocols.Tls, true);
XmlSerializer XS = new XMLSerializer(typeof(someclass));
someclass TempObject = new someclass(){ InnerData = Data};
if (SecureStream.CanWrite)
{
XS.Serialize(SecureStream, TempObject);
}
SecureStream.Close();
}
}
SslStream
simply wraps around another Stream
. If you call AuthenticateAsServer()
the other side should AuthenticateAsClient()
and from that point on you can communicate over SSL. If either side fails to call this method, the SslStream
will throw an exception.
If you close an SslStream
constructed with the leaveInnerStreamOpen
parameter set to true
, you can then communicate directly over the underlying stream as if there never was an SslStream
(and you can even send and receive directly to/from the underlying stream while the SslStream
is still open).
In a typical scenario like HTTPS, client and server would enable SSL as soon as the connection is established, and continue using that for the duration of the connection. There's nothing stopping you though from closing the SslStream
on both sides after a request/response, and recreating one for the next message - you'd just have to keep the "ssl state" synchronized between client and server.
As for your comment:
Once a TCP connection is established, you can send and receive data for as long as both sides stay connected. For example:
TcpClient client = TcpListener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
while (true)
{
int bytes = stream.Read(...);
if (bytes == 0)
{
// other side has disconnected
stream.Close();
break;
}
// add incoming data to buffer, process messages
...
}
It's like talking to someone by writing text on a piece of paper you show to one another - you simply continue writing on the same piece of paper, and the other side can read while you write.
If you close the TcpClient
after a request/response and open a new one using TcpListener.AcceptXxx()
, you're throwing away each piece of paper after every message.
If I were you I'd play with these concepts (using the NetworkStream
class) without the SslStream
wrapper, until you feel you're doing the right thing. The SslStream
layer can be added without any significant changes to code that uses NetworkStream
.