diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4856c0f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+SocketIO/obj/*
+*.suo
+*j.user
+SocketIO/bin/*
+SocketIO.userprefs
diff --git a/SocketIO.sln b/SocketIO.sln
index a66be6a..d28d4a9 100644
--- a/SocketIO.sln
+++ b/SocketIO.sln
@@ -1,6 +1,6 @@
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocketIO", "SocketIO\SocketIO.csproj", "{2F18D000-F801-40FC-8B29-CA112E33536D}"
EndProject
Global
@@ -14,6 +14,9 @@ Global
{2F18D000-F801-40FC-8B29-CA112E33536D}.Release|x86.ActiveCfg = Release|x86
{2F18D000-F801-40FC-8B29-CA112E33536D}.Release|x86.Build.0 = Release|x86
EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = SocketIO\SocketIO.csproj
EndGlobalSection
diff --git a/SocketIO.userprefs b/SocketIO.userprefs
deleted file mode 100644
index 880e1d0..0000000
--- a/SocketIO.userprefs
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/SocketIO/SocketIO.csproj b/SocketIO/SocketIO.csproj
index 2f50ed6..48fa76c 100644
--- a/SocketIO/SocketIO.csproj
+++ b/SocketIO/SocketIO.csproj
@@ -1,5 +1,5 @@
-
-
+
+
Debug
x86
@@ -10,6 +10,26 @@
SocketIO
SocketIO
v3.5
+
+
+
+
+ 3.5
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
true
@@ -19,7 +39,7 @@
DEBUG;
prompt
4
- x86
+ AnyCPU
false
@@ -79,4 +99,16 @@
bin\Debug\SocketIO.dll
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 3.5 SP1
+ true
+
+
\ No newline at end of file
diff --git a/SocketIO/bin/Debug/SocketIO.dll b/SocketIO/bin/Debug/SocketIO.dll
deleted file mode 100644
index 99e7487..0000000
Binary files a/SocketIO/bin/Debug/SocketIO.dll and /dev/null differ
diff --git a/SocketIO/bin/Debug/SocketIO.pdb b/SocketIO/bin/Debug/SocketIO.pdb
deleted file mode 100644
index 6c12f63..0000000
Binary files a/SocketIO/bin/Debug/SocketIO.pdb and /dev/null differ
diff --git a/SocketIO/socketio/Client.cs b/SocketIO/socketio/Client.cs
index 7055c76..e77d286 100644
--- a/SocketIO/socketio/Client.cs
+++ b/SocketIO/socketio/Client.cs
@@ -59,11 +59,6 @@ public class Client : IDisposable, SocketIOClient.IClient
public event EventHandler SocketConnectionClosed;
public event EventHandler Error;
- ///
- /// ResetEvent for Outbound MessageQueue Empty Event - all pending messages have been sent
- ///
- public ManualResetEvent MessageQueueEmptyEvent = new ManualResetEvent(true);
-
///
/// Connection Open Event
///
@@ -128,15 +123,22 @@ public Client(string url, WebSocketVersion socketVersion)
this.registrationManager = new RegistrationManager();
this.outboundQueue = (new ConcurrentQueue());
- this.dequeuOutBoundMsgTask = new Thread(new ThreadStart(dequeuOutboundMessages));
- //this.dequeuOutBoundMsgTask = Task.Factory.StartNew(() => dequeuOutboundMessages(), TaskCreationOptions.LongRunning);
- this.dequeuOutBoundMsgTask.Start();
}
///
/// Initiate the connection with Socket.IO service
///
public void Connect()
+ {
+ Connect(null, null);
+ }
+
+ ///
+ /// Initiate the connection with Socket.IO service using provided handshake query string and headers
+ ///
+ ///
+ ///
+ public void Connect(string query, string[] headers)
{
lock (padLock)
{
@@ -145,7 +147,7 @@ public void Connect()
try
{
this.ConnectionOpenEvent.Reset();
- this.HandShake = this.requestHandshake(uri);// perform an initial HTTP request as a new, non-handshaken connection
+ this.HandShake = this.requestHandshake(uri, query, headers);// perform an initial HTTP request as a new, non-handshaken connection
if (this.HandShake == null || string.IsNullOrEmpty(this.HandShake.SID) || this.HandShake.HadError)
{
@@ -159,7 +161,8 @@ public void Connect()
string.Format("{0}://{1}:{2}/socket.io/1/websocket/{3}", wsScheme, uri.Host, uri.Port, this.HandShake.SID),
string.Empty,
this.socketVersion);
- this.wsClient.EnableAutoSendPing = true; // #4 tkiley: Websocket4net client library initiates a websocket heartbeat, causes delivery problems
+ //this.wsClient.EnableAutoSendPing = true; // #4 tkiley: Websocket4net client library initiates a websocket heartbeat, causes delivery problems
+ this.wsClient.EnableAutoSendPing = false; // ANF: socket.io has it's own heartbeat, this should be unnecessary
this.wsClient.Opened += this.wsClient_OpenEvent;
this.wsClient.MessageReceived += this.wsClient_MessageReceived;
this.wsClient.Error += this.wsClient_Error;
@@ -303,9 +306,11 @@ public void Emit(string eventName, Object payload)
///
public void Send(IMessage msg)
{
- this.MessageQueueEmptyEvent.Reset();
if (this.outboundQueue != null)
+ {
this.outboundQueue.Enqueue(msg.Encoded);
+ ThreadPool.QueueUserWorkItem(new WaitCallback(dequeueOutboundMessages));
+ }
}
public void Send(string msg) {
@@ -315,9 +320,11 @@ public void Send(string msg) {
private void Send_backup(string rawEncodedMessageText)
{
- this.MessageQueueEmptyEvent.Reset();
if (this.outboundQueue != null)
+ {
this.outboundQueue.Enqueue(rawEncodedMessageText);
+ ThreadPool.QueueUserWorkItem(new WaitCallback(dequeueOutboundMessages));
+ }
}
///
@@ -404,7 +411,10 @@ protected void closeWebSocketClient()
// websocket client events - open, messages, errors, closing
private void wsClient_OpenEvent(object sender, EventArgs e)
{
- this.socketHeartBeatTimer = new Timer(OnHeartBeatTimerCallback, new object(), HandShake.HeartbeatInterval, HandShake.HeartbeatInterval);
+ // ANF: only enable the heartbeat timer if the interval is non-zero
+ if(HandShake.HeartbeatInterval.TotalMilliseconds!=(double)0.0)
+ this.socketHeartBeatTimer = new Timer(OnHeartBeatTimerCallback, new object(), HandShake.HeartbeatInterval, HandShake.HeartbeatInterval);
+
this.ConnectionOpenEvent.Set();
this.OnMessageEvent(new EventMessage() { Event = "open" });
@@ -413,6 +423,9 @@ private void wsClient_OpenEvent(object sender, EventArgs e)
try { this.Opened(this, EventArgs.Empty); }
catch (Exception ex) { Trace.WriteLine(ex); }
}
+
+ // send any messages we might have queued while opening the connection
+ ThreadPool.QueueUserWorkItem(new WaitCallback(dequeueOutboundMessages));
}
@@ -547,34 +560,16 @@ private void EndAsyncEvent(IAsyncResult result)
}
}
///
- /// While connection is open, dequeue and send messages to the socket server
+ /// dequeue and send messages to the socket server
///
- protected void dequeuOutboundMessages()
+ protected void dequeueOutboundMessages(Object stateinfo)
{
- while (this.outboundQueue != null)
+ if (this.ReadyState == WebSocketState.Open && this.outboundQueue != null)
{
- if (this.ReadyState == WebSocketState.Open)
- {
- string msgString;
- try
- {
- if (this.outboundQueue.TryDequeue(out msgString))
- {
- this.wsClient.Send(msgString);
- }
- else
- this.MessageQueueEmptyEvent.Set();
- }
- catch(Exception ex)
- {
- Trace.WriteLine("The outboundQueue is no longer open...");
- }
- }
- else
- {
- this.ConnectionOpenEvent.WaitOne(2000); // wait for connection event
- }
- }
+ string msgString;
+ while(this.outboundQueue.TryDequeue(out msgString))
+ this.wsClient.Send(msgString);
+ }
}
///
@@ -583,19 +578,24 @@ protected void dequeuOutboundMessages()
/// The tansport and sid are required as part of the ws: transport connection
///
/// http://localhost:3000
+ /// nullable, optional query string
+ /// nullable, Optional headers(ex: "name:value")
/// Handshake object with sid value
/// DownloadString: 13052140081337757257:15:25:websocket,htmlfile,xhr-polling,jsonp-polling
- protected SocketIOHandshake requestHandshake(Uri uri)
+ protected SocketIOHandshake requestHandshake(Uri uri, string query, string[] headers)
{
string value = string.Empty;
string errorText = string.Empty;
SocketIOHandshake handshake = null;
using (WebClient client = new WebClient())
- {
+ {
+ if (headers != null && headers.Length > 0)
+ foreach (string s in headers)
+ client.Headers.Add(s);
try
{
- value = client.DownloadString(string.Format("{0}://{1}:{2}/socket.io/1/{3}", uri.Scheme, uri.Host, uri.Port, uri.Query)); // #5 tkiley: The uri.Query is available in socket.io's handshakeData object during authorization
+ value = client.DownloadString(string.Format("{0}://{1}:{2}/socket.io/1/{3}", uri.Scheme, uri.Host, uri.Port, string.IsNullOrEmpty(query) ? uri.Query: query)); // #5 tkiley: The uri.Query is available in socket.io's handshakeData object during authorization
// 13052140081337757257:15:25:websocket,htmlfile,xhr-polling,jsonp-polling
if (string.IsNullOrEmpty(value))
errorText = "Did not receive handshake string from server";
@@ -630,7 +630,6 @@ protected virtual void Dispose(bool disposing)
{
// free managed resources
this.Close();
- this.MessageQueueEmptyEvent.Close();
this.ConnectionOpenEvent.Close();
}