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 endPrint 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