This project is read-only.

Websocket client on MonoTouch

Jan 10, 2012 at 4:47 AM

Hi there, I'm trying to use the WebSocketClient within a MonoTouch application and am getting tripped up within the SuperSocket layer.  Based on the conversation here, I'm rebuilding all the source myself and have been able to establish a connection to existing server (verified by log statements in the connect/disconnect on server).  However, when I actually attempt to send a message, I'm getting a null reference.

I traced this down to the TcpClientSession.DequeueSend method.  Within the try...catch is the line: 'async = Client.SendAsync(args);' and this is where the var Client is null.  It seems that this var is set from within ProcessAccept(), which should be called by the  m_SocketEventArgs.Completed event which would be triggered after the ConnectAsync is called from the ClientSession.Connect()?  Wow, I hope that makes sense; but in the end, it never gets triggered and Client is always null.  I can break in Connect() without issue, but I will never hit a break set in m_SocketEventArgs_Completed or ProcessAccept.

Also, I wasn't sure where I should post this, on SuperWebSocket, SuperSocket, or here.  Feel free to move the discussion or just let me know and I can repost.

Thanks for all the support

Jan 10, 2012 at 6:17 AM

While attempting to generate logs to clarify what's going on, I've learned that the ProcessAccept method is indeed being called, but only after I attempt to send a message, not during the opening of the connection.  Please take a look at the logs below:

TcpClientSession.Init - Initialized socketEventArgs.Completed
Controller - Before socket.Open()
TcpClientSession.Connect()
TcpClientSession.Connect() - socket.ConnectAsync result - True
Controller - After socket.Open()
Controller - Before socket.Send()
TcpClientSession.DequeueSend()
Controller - After socket.Send()
m_SocketEventArgs_Completed - Socket.Completed event fired
TcpClientSession.ProcessAccept()

Items beginning "Controller - " are from my calling code.  Hope this helps, I'm not sure I know all I need to in order to resolve that one :)

Jan 10, 2012 at 8:55 AM

TcpClientSession.ProcessAccept()?

Jan 10, 2012 at 8:59 AM

Did you ensure your sending is after the socket is opened?

There is an event named webscoekt.Opened you can use.

Jan 10, 2012 at 9:01 AM

The method 'OnGetHostAddresses' is in the execution routine?

Jan 10, 2012 at 5:05 PM

You were correct that I was not waiting for the Opened event to fire before sending messages.  So I have reworked this so that within that event handler is the first time I attempt to send a message.  But, here's the key now - this event is never fired.  Don't know why, I'll be looking there next and will update once I discover anything relevant.

And I'm not sure about 'OnGetHostAddresses', I could not find that name anywhere within my solution.

Jan 11, 2012 at 11:15 AM
Edited Jan 11, 2012 at 11:21 AM

I have updated the client, and added an event named "Error", you can use it to monitoring the error of the websocket client.

websocket.Error += new EventHandler<ErrorEventArgs>(websocket_Error);

Jan 11, 2012 at 5:47 PM

Awesome news, thanks for the update.  Sorry I hadn't gotten more details in yesterday but I got sidelined with another problem.  In addition, I was thinking there might be a discrepancy between the socket server and client code?  I know the client has been reworked extensively lately, but our socket server has been deployed for a few months now (already serving web clients).  Could it be I need to update the server code as well?

Jan 11, 2012 at 9:18 PM

I had to rebuild both SuperSocket.ClientEngine as well as WebSocket4Net under new MonoTouch projects, and I got that to compile just fine as before.  After that I added simple test app that had references to these 2 projects and on startup attempts to connect to the socket server and send a message.  I have the same behavior as before, where the connection is opened but the socket.Opened or socket.Error events never fires.  I'll continue digging, but wanted to provide an update.

Oh, and I'm not sure how I missed the OnGetHostAddresses method, but it does indeed get called.

Jan 11, 2012 at 9:35 PM

A bit of additional information, it looks like everything is running without exception up through sending the handshake.  I see it build the handshake data within the DraftHybi10Processor class, then tries to send it - which goes through and Sending_Completed is called, which goes back to DequeueSend and exits because there are no more segments available.

After this, I'm not sure exactly where the process should pick up again.  I think my next step will be to update the server side code as well; just seems like a good idea :)

Jan 12, 2012 at 1:27 AM
Edited Jan 12, 2012 at 1:28 AM

Which websocket server are you using?

You can run the server on your local and then debug it when the client starts connection.

Jan 12, 2012 at 3:11 AM

I'm using the SuperWebSocket server, and I'm not sure specific version but it appears the last time it was built was around end of October, at least updated in source control.

Jan 12, 2012 at 3:13 AM

Could you try WebSocket4Net .NET 4 or Silverlight version first?

Jan 12, 2012 at 4:33 AM

I'm not sure I understand exactly, I am using the source for WebSocket4Net project, but I had to simply import it into a newly created MonoTouch project in order to satisfy the references.  If I try to open the WebSocket4Net.sln in MonoDevelop, the main project has invalid references that then state "Assembly not available for .NETFramework 4.0 Client Profile (In Mono 2.10.8)"

There are similar invalid references under the Silverlight project that then state "Assembly not available for Moonlight / Silverlight 4.0 (In mono 2.10.8)".

I could easily be missing something by now, but I thought based on previous talk under SuperWebSocket forums that I would need to recompile the projects for use under MonoTouch?

Jan 12, 2012 at 4:36 AM

You'd better debug into the SuperWebSocket(the server side).

Jan 12, 2012 at 5:24 AM

Oh boy, I was afraid you might say something like that :)  I'll work on getting environment setup to test everything and report back any discoveries.  Thanks for sticking with me through all this, I'm working in isolation on this feature and it's nice to at least have some sort of validation I'm not simply missing something stupid.  

Jan 12, 2012 at 6:56 AM

Add this configuration node to output socket log:
<system.diagnostics>
        <trace autoflush="true" />
        <sources>
            <source name="System.Net.Sockets" maxdatasize="1024">
                <listeners>
                    <add name="SocketTrace"/>
                </listeners>
            </source>
        </sources>
        <sharedListeners>
            <add name="SocketTrace"
                 type="System.Diagnostics.TextWriterTraceListener"
                 initializeData="System.Net.Trace.log" />
        </sharedListeners>
        <switches>
            <add name="System.Net.Sockets" value="Verbose" />
        </switches>
    </system.diagnostics>

Jan 12, 2012 at 7:00 AM

You'd better debug into the line below in the class WebSocketReaderBase.cs:

protected void Handshake(IProtocolProcessor protocolProcessor, IWebSocketSession session)
Jan 12, 2012 at 7:52 PM

Thanks for the example configuration, I set it up and with the hopes it means more to you than me, here's the output from the server as I attempt a connection/handshake and fail to receive the opened event on the client.  I still need to dig into the method you provided as well - thanks for the pointers.

System.Net.Sockets Verbose: 0 : [11708] Socket#40644060::Socket(InterNetwork#2)
System.Net.Sockets Verbose: 0 : [11708] Exiting Socket#40644060::Socket()
System.Net.Sockets Verbose: 0 : [11708] Socket#40644060::Bind(0:8001#8001)
System.Net.Sockets Verbose: 0 : [11708] Exiting Socket#40644060::Bind()
System.Net.Sockets Verbose: 0 : [11708] Socket#40644060::Listen(100#100)
System.Net.Sockets Verbose: 0 : [11708] Exiting Socket#40644060::Listen()
System.Net.Sockets Verbose: 0 : [11708] Socket#40644060::Accept()
System.Net.Sockets Verbose: 0 : [11708] Socket#47980820::Socket()
System.Net.Sockets Verbose: 0 : [11708] Exiting Socket#47980820::Socket()
System.Net.Sockets Information: 0 : [11708] Socket#47980820 - Accepted connection from 192.168.7.226:53330 to 192.168.7.53:8001.
System.Net.Sockets Verbose: 0 : [11708] Exiting Socket#40644060::Accept() -> Socket#47980820
System.Net.Sockets Verbose: 0 : [11708] Socket#40644060::Accept()
System.Net.Sockets Verbose: 0 : [5512] Socket#47980820::Receive()
System.Net.Sockets Verbose: 0 : [5512] Data from Socket#47980820::Receive
System.Net.Sockets Verbose: 0 : [5512] 00000000 : 47 45 54 20 2F 77 65 62-73 6F 63 6B 65 74 20 48 : GET /websocket H
System.Net.Sockets Verbose: 0 : [5512] 00000010 : 54 54 50 2F 31 2E 31 0D-0A 55 70 67 72 61 64 65 : TTP/1.1..Upgrade
System.Net.Sockets Verbose: 0 : [5512] 00000020 : 3A 20 57 65 62 53 6F 63-6B 65 74 0D 0A 43 6F 6E : : WebSocket..Con
System.Net.Sockets Verbose: 0 : [5512] 00000030 : 6E 65 63 74 69 6F 6E 3A-20 55 70 67 72 61 64 65 : nection: Upgrade
System.Net.Sockets Verbose: 0 : [5512] 00000040 : 0D 0A 53 65 63 2D 57 65-62 53 6F 63 6B 65 74 2D : ..Sec-WebSocket-
System.Net.Sockets Verbose: 0 : [5512] 00000050 : 56 65 72 73 69 6F 6E 3A-20 38 0D 0A 53 65 63 2D : Version: 8..Sec-
System.Net.Sockets Verbose: 0 : [5512] 00000060 : 57 65 62 53 6F 63 6B 65-74 2D 4B 65 79 3A 20 36 : WebSocket-Key: 6
System.Net.Sockets Verbose: 0 : [5512] 00000070 : 36 35 32 36 0D 0A 48 6F-73 74 3A 20 31 39 32 2E : 6526..Host: 192.
System.Net.Sockets Verbose: 0 : [5512] 00000080 : 31 36 38 2E 37 2E 35 33-0D 0A 4F 72 69 67 69 6E : 168.7.53..Origin
System.Net.Sockets Verbose: 0 : [5512] 00000090 : 3A 20 31 39 32 2E 31 36-38 2E 37 2E 35 33 0D 0A : : 192.168.7.53..
System.Net.Sockets Verbose: 0 : [5512] 000000A0 : 0D 0A : ..
System.Net.Sockets Verbose: 0 : [5512] Exiting Socket#47980820::Receive() -> 162#162
System.Net.Sockets Verbose: 0 : [5512] Socket#47980820::Send()
System.Net.Sockets Verbose: 0 : [5512] Data from Socket#47980820::Send
System.Net.Sockets Verbose: 0 : [5512] 00000000 : 48 54 54 50 2F 31 2E 31-20 31 30 31 20 53 77 69 : HTTP/1.1 101 Swi
System.Net.Sockets Verbose: 0 : [5512] 00000010 : 74 63 68 69 6E 67 20 50-72 6F 74 6F 63 6F 6C 73 : tching Protocols
System.Net.Sockets Verbose: 0 : [5512] 00000020 : 0D 0A 55 70 67 72 61 64-65 3A 20 57 65 62 53 6F : ..Upgrade: WebSo
System.Net.Sockets Verbose: 0 : [5512] 00000030 : 63 6B 65 74 0D 0A 43 6F-6E 6E 65 63 74 69 6F 6E : cket..Connection
System.Net.Sockets Verbose: 0 : [5512] 00000040 : 3A 20 55 70 67 72 61 64-65 0D 0A 53 65 63 2D 57 : : Upgrade..Sec-W
System.Net.Sockets Verbose: 0 : [5512] 00000050 : 65 62 53 6F 63 6B 65 74-2D 41 63 63 65 70 74 3A : ebSocket-Accept:
System.Net.Sockets Verbose: 0 : [5512] 00000060 : 20 39 54 63 46 73 4F 63-2B 4A 4F 45 33 4A 69 54 : 9TcFsOc+JOE3JiT
System.Net.Sockets Verbose: 0 : [5512] 00000070 : 48 6A 31 6E 54 59 41 46-32 62 70 55 3D 0D 0A 0D : Hj1nTYAF2bpU=...
System.Net.Sockets Verbose: 0 : [5512] 00000080 : 0A : .
System.Net.Sockets Verbose: 0 : [5512] Exiting Socket#47980820::Send() -> 129#129
System.Net.Sockets Verbose: 0 : [5512] Socket#47980820::Receive()

Jan 13, 2012 at 1:15 AM

It means the server side worked correctly, and client failed to fire the opened event.

Jan 13, 2012 at 1:16 AM

Is there a way debugging client side?

Jan 13, 2012 at 5:51 AM

Sure, I'm running a simple iPad single view application that is trying to establish the connection.  This is running inside MonoDevelop and I can set a breakpoint anywhere normally permitted.  The one in the Opened event just never gets hit though.  Though I have been able to stop execution on breakpoint set in Error event handler.

Jan 13, 2012 at 9:26 AM

Though I have been able to stop execution on breakpoint set in Error event handler??

 

What's the exception?

Jan 13, 2012 at 9:28 AM

You'd better build a debug version, so that you can debug into the source code of WebSocket4Net, like the class ProtocolProcessor,....

Jan 17, 2012 at 6:53 AM

Hey Kerry, it looks like we're going to be using a straight "regular" tcp connection to accomplish this rather than going through all the web sockets.  Not sure what I was thinking, just that we had an existing server in place.  But I've tested out using the TcpClient class within MonoTouch and it seems pretty straightforward.  Thanks for helping me though to this point, perhaps I'll get back in shortly.  I do think it'd be kind of cool to use web sockets from iOs - not sure why :)

Thanks again!

Jan 17, 2012 at 7:57 AM

Good!

I'll install Mac OS in my laptop by VirtualBox to test the WebSocket4Net.

Jan 31, 2012 at 12:25 PM

mklinker?

I probably have fixed the bug you met:

http://websocket4net.codeplex.com/SourceControl/changeset/changes/15842e65138d

If you have time, could you try this change?

Mar 13, 2012 at 4:05 PM

@kerryjiang

were you able to setup a WebSocket client on monotouch??

Mar 13, 2012 at 4:29 PM

Not yet, I haven't setup an environment!

Mar 13, 2012 at 4:45 PM

If you have an environment, I suggest you try to use the code of Silverlight version.

Oct 31, 2012 at 4:09 PM

Hi, WebSocket4Net provides MonoTouch support now. You can have it by downloading the latest source code from the master branch.