I don't know C# but I can describe briefly how to do it in Ruby if that helps. Of course, for a robust solution you will probably end up porting the whole Faye/cometD client codebase to C#.
Here's the simplest thing you can do, with no error handling, transport negotation etc. The handshake must be done over normal HTTP, not sockets:
require 'uri'
require 'net/http'
require 'json'
require 'faye/websocket'
message = JSON.dump('channel' => '/meta/handshake',
'version' => '1.0',
'supportedConnectionTypes' => ['long-polling','websocket'])
response = Net::HTTP.post_form(uri, :message => message)
handshake = JSON.parse(response.body).first
client_id = handshake['clientId']
Once you've got a client ID, you can open a socket to the server, register subscriptions and receive messages. The protocol requires that you poll the /meta/connect channel even when using WebSocket; message delivery is not tied to this but it serves as a keep-alive mechanism to keep the session active.
EM.run {
ws = Faye::WebSocket::Client.new('ws://localhost:8000/bayeux')
ws.onmessage = lambda do |event|
message = JSON.parse(event.data).first
case message['channel']
when '/meta/connect'
# poll /meta/connect again
ws.send(JSON.dump('channel' => '/meta/connect',
'clientId' => client_id,
'connectionType' => 'websocket'))
when '/meta/subscribe'
# check message['successful'] and message['error']
else
# handle any other pushed message
end
end
ws.onopen = lambda do |event|
# send initial /meta/connect message
ws.send(JSON.dump('channel' => '/meta/connect',
'clientId' => client_id,
'connectionType' => 'websocket'))
# register a subscription for channel /foo
ws.send(JSON.dump('channel' => '/meta/subscribe',
'clientId' => client_id,
'subscription' => '/foo'))
end
}