I needed a small single purpose TCP socket server for work, and I thought it might be an opportune time to try a new programming language. My choices were Scala, F# or Erlang. The target platform was a win2k box and I wanted to be able to register it as a service so F# was the obvious choice. In the code below I modified the echo server example from the MIT F# site to run as a service.
// This sample code is provided "as is" without warranty of any kind.
// We disclaim all warranties, either express or implied, including the
// warranties of merchantability and fitness for a particular purpose.
#light
#r "System.ServiceProcess.dll";;
#r "System.Configuration.Install.dll";;
// Echo Server: opens a service on the localhost which bounces data straight back
open System.Net
open System.Net.Sockets
open System.Threading
open System.ServiceProcess
open System.ComponentModel
open System.Configuration.Install
open Microsoft.FSharp.Compatibility.CompatArray
let spawn f = (new Thread(new ThreadStart(f))).Start()
type EchoServer = class
inherit ServiceBase as base
new() as this = {} then base.ServiceName <- "SimpleEchoService"
override this.OnStart(args:string[]) =
spawn(this.listen)
member this.listen() =
let sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP)
sock.Bind(new IPEndPoint(IPAddress.Any, 5120))
let backlog = 2 // number of incoming connections that can be queued for acceptance
sock.Listen(backlog)
let port = (sock.LocalEndPoint :?> IPEndPoint).Port
Printf.printf "server accepting on port %d...\n" port
while (true) do
let csock = sock.Accept()
Printf.printf "the server has accepted a client on port %d...\n" port;
spawn(fun () ->
let total = ref 0
try
let buf = Bytearray.create 64
let stream = new NetworkStream(csock)
while true do
Printf.printf "server reading...\n";
let nread = stream.Read(buf,0,64)
Printf.printf "server read %d...\n" nread;
stream.Write(buf,0,nread);
total := !total + nread;
done;
with
| :? Sockets.SocketException
| :? System.IO.IOException ->
Printf.printf "client gone: server read %d bytes from that client\n" !total;
flush stdout
)
done
end
Print this post
2 comments:
Matthew... I'm trying to write a Win32 service in F# also, but I'm not sure how to programmatically add the installer. Can you help tell me how you did this?
Thanks,
Scott
It's been a while since I've done anything in F# or .Net so this might not be 100% correct. From what I remember you just need to compile the F# code to an executable and then use the command line utility 'installutil' to register the service. You could also use an installer project or install the service programmatically. I've never personally installed a service programmatically. I've always create an MSI using WIX, but judging from this StackOverflow post it doesn't look to bad. I hope this helps, good luck.
http://stackoverflow.com/questions/255056/install-a-net-windows-service-without-installutil-exe
Post a Comment