-
Notifications
You must be signed in to change notification settings - Fork 85
F# Echo Server
vtortola edited this page Nov 25, 2014
·
2 revisions
This is an implementation of the Echo Server example in F# as a demonstration of how to use WebSocketListener in this language.
The source code can be found HERE
First, I created some helpers to simplify the work with the library.
A extension method to accept websockets asynchronusly using Async<WebSocket>
rather than Task<WebSocket
:
type WebSocketListener with
member x.AsyncAcceptWebSocket = async {
let! client = Async.AwaitTask <| x.AcceptWebSocketAsync cancellation.Token
if(not(isNull client)) then
return Some client
else
return None
}
Also, two extension methods on the WebSocket
class to receive/send string messages:
type WebSocket with
member x.AsyncReadString = async {
let! message = Async.AwaitTask <| x.ReadMessageAsync cancellation.Token
if(not(isNull message)) then
use reader = new StreamReader(message)
return Some (reader.ReadToEnd())
else
return None
}
member x.AsyncSendString (input:string) = async {
use writer = new StreamWriter(x.CreateMessageWriter(WebSocketMessageType.Text), Encoding.UTF8)
writer.Write input
do! writer.FlushAsync() |> Async.AwaitIAsyncResult |> Async.Ignore
}
[<EntryPoint>]
let main argv =
let options =
let opt = new WebSocketListenerOptions()
opt.PingTimeout <- TimeSpan.FromSeconds(20.)
opt.SubProtocols <- [|"text"|]
opt
let endpoint = new IPEndPoint(IPAddress.Any,9005)
use listener = new WebSocketListener(endpoint, options)
listener.Standards.RegisterStandard(new Rfc6455.WebSocketFactoryRfc6455(listener))
Async.Start <| AsyncAcceptClients listener
listener.Start()
Log [|"Echo Server started at "; endpoint.ToString()|];
Console.ReadKey true |> ignore
listener.Stop()
cancellation.Cancel()
Log "Server stopped";
Console.ReadKey true |> ignore
0 // return an integer exit code
let AsyncAcceptClients(listener : WebSocketListener) =
async {
while not cancellation.IsCancellationRequested && listener.IsStarted do
let! result = Async.Catch listener.AsyncAcceptWebSocket
match result with
| Choice1Of2 result ->
match result with
| None -> ignore()
| Some client -> Async.Start <| AsyncAcceptMessages client
| Choice2Of2 error ->
Log [|"Error Accepting clients: "; error.Message|]
Log "Server Stop accepting clients"
}
let AsyncAcceptMessages(client : WebSocket) =
async {
while client.IsConnected do
let! result = Async.Catch client.AsyncReadString
match result with
| Choice1Of2 result ->
match result with
| None -> ignore()
| Some content -> do! client.AsyncSendString content
| Choice2Of2 error ->
Log [|"Error Handling connection: "; error.Message|]
Log [|"WebSocket "; (client.RemoteEndpoint.ToString()); " disconnected"|]
}