Writing a windows service with a socket interface.

  • Thread starter Thread starter Peter Strøiman
  • Start date Start date
P

Peter Strøiman

Hi.

I'm writing a windows service that is accessible via sockets. I have tried
to find literature on the subject but I couldn't.

Basically my service, when asked to start, starts up a new thread that just
waits for connection. See bottom of this mail.

The StreamParser class is the facade that parses data sent to my service,
and sends a response back to the client.

I'm left with a couple of questions.

A: Are there any good resources on writing windows services with socket
interfaces anywhere?

B: Is my main code robust. E.g. if some idiot accidentally pulled the
network cable out of the server, would _listener.AcceptTcpClient() throw an
exception. Or perhaps if the IP address of the server was modified while the
service was running.

C: When a client connects and sends a request and thereafter gets a
response, should I close the socket, or keep the socket open. I'm writing
the class that handles the client's communication with the server as well,
so I can control these things. If the best option is to leave the connection
open, I would implement a sort of connection pool of course.

D: How should I detect if clients are disconnected? My StreamParser
implementation simply calls the blocking Stream.Read() method, waiting for
data to arrive. Can I count on that the stream throws an IOException if the
client is disconnected? E.g. if the network cable is unplugged (either from
the server or client), someone changes the IP address of the server/client,
or the client process suddenly terminates. Of course I would implement a
"close" command in my communication protocal that would manually close a
connection.

Thanks in advance,
Peter Strøiman

// service main thread
try
{
_listener = new TcpListener( _ipEndPoint );
_listener.Start();
_state = TcpInterfaceState.Running;
while( true )
{
TcpClient client = _listener.AcceptTcpClient();
if ( client != null )
{
Stream stream = client.GetStream();
StreamParser parser = new StreamParser( stream );
Thread thread = new Thread( new ThreadStart( parser.Run ) );
thread.ApartmentState = ApartmentState.STA;
thread.Start();
}
}
}
catch( Exception e )
{
// error handling code
}
 
Peter Strøiman said:
Hi.

I'm writing a windows service that is accessible via sockets. I have tried
to find literature on the subject but I couldn't.

Why not use Remoting instead? It's FAR easier than direct socket
manipulation and can easily be switched to use other channels. Some example
channels "in the wild" are: SMTP, MSMQ, NamedPipes, TCP/IP, and
SharedMemory. It also allows for easily configurable control of manipulation
on the sent data via channel sinks. Some sinks I've seen include encryption,
compression, thread priority serialization, and user token serialization. It
will get you completely away from the nitty-gritty of parsing and
serializing data streams.
Basically my service, when asked to start, starts up a new thread that
just waits for connection. See bottom of this mail.

The StreamParser class is the facade that parses data sent to my service,
and sends a response back to the client.

I'm left with a couple of questions.

A: Are there any good resources on writing windows services with socket
interfaces anywhere?

B: Is my main code robust. E.g. if some idiot accidentally pulled the
network cable out of the server, would _listener.AcceptTcpClient() throw
an exception. Or perhaps if the IP address of the server was modified
while the service was running.

Both these situations could indeed lead to an exception. Since deep down,
TcpListener.AcceptTcpClient calls the accept function from WINSOCK2, any of
the errors described by that function could lead to an exception.
C: When a client connects and sends a request and thereafter gets a
response, should I close the socket, or keep the socket open. I'm writing
the class that handles the client's communication with the server as well,
so I can control these things. If the best option is to leave the
connection open, I would implement a sort of connection pool of course.

Tricky. It depends on the type of application. If you're dealing with a
scenario where the client and server have continuing communications, I'd say
it'd be worthwhile to keep the connection open, but time it out after a
certain time of no activity. I don't think a connection pool would help you
unless you're envisaging many client applications on one client machine
using the same connection to communicate to the server. However, if you're
looking for the highest scalability, then each connection should be used for
one call and response, and then shut down. Of course, if you're going to do
this make sure the call and response carry enough data that you don't
require too many of them.

A compromise would be to have a "conversation" where the server and client
connect, partake in some sequence of calls and response and then close the
connection when that sequence is complete. This should ideally be a
predefined sequence of messages enforced by the server or you open yourself
to a DOS attack.

So you might have the Authenticate/Authorize conversation, consisting of
maybe 2-4 call-responses. You'd also have the FetchData conversation,
consisting of, say, 8 call-responses and so forth.
D: How should I detect if clients are disconnected? My StreamParser
implementation simply calls the blocking Stream.Read() method, waiting for
data to arrive. Can I count on that the stream throws an IOException if
the client is disconnected? E.g. if the network cable is unplugged (either
from the server or client), someone changes the IP address of the
server/client, or the client process suddenly terminates. Of course I
would implement a "close" command in my communication protocal that would
manually close a connection.

The stream should throw an IOException if the socket or stream is closed.
However, the client just suddenly dropping off the network wouldn't result
in such an exception. This is why the TcpClient has a ReceiveTimeout
property.

One way to check if the clients alive is to ping the client every once and
again (the approach that DCOM uses). This unfortunately eats up unneccessary
network bandwidth. .NET Remoting uses the concept of leases where a client
is given a certain amount of time to make a call (say a minute) before the
object is destroyed. Each call from the client renews the lease.
 
Back
Top