locked
web sockets not working after establishing the connection?

    Question

  • Hello guys.

    I've already asked this before, but never got an answer. So, I'm asking it again and putting all the code I'm using here.

    I've build a web socket object in a new ASP.NET 4.5 project. Here's the code I used in my socket class:

    namespace Sockets
    {
        public class MySocket : WebSocketHandler
        {
            private static readonly WebSocketCollection _clientes =
       new WebSocketCollection();
            private readonly JavaScriptSerializer serializer =
              new JavaScriptSerializer();
            private readonly string _username;

            public MySocket(string username = "")
            {
                _username = username;
            }

            public override void OnOpen()
            {
                _clientes.Add(this);
                _clientes.Broadcast(serializer.Serialize(
                    CriaMensagem("Iniciou a sessão.")));
            }
            private Mensagem CriaMensagem(String texto)
            {
                return new Mensagem
                {
                    data = DateTime.Now.ToShortTimeString(),
                    utilizador = _username,
                    texto = texto
                };
            }
            public override void OnMessage(string message)
            {
                var msg = serializer.Deserialize<Mensagem>(message);
                _clientes.Broadcast(serializer.Serialize(
                   CriaMensagem(msg.texto)));
            }
            public override void OnClose()
            {
                _clientes.Remove(this);
                _clientes.Broadcast(serializer.Serialize(
                 CriaMensagem("Terminou sessão")));
            }
            private class Mensagem
            {
                public String data { get; set; }
                public string texto { get; set; }
                public string utilizador { get; set; }
            }

        }
    }

    And here's how it's exposed from an ashx handler:

    <%@ WebHandler Language="C#" CodeBehind="Socket.ashx.cs" Class="Sockets.Socket" %>
    namespace Sockets {
        public class Socket : IHttpHandler {
            #region IHttpHandler Members

            public void ProcessRequest(HttpContext context) {
                if (context.IsWebSocketRequest) {
                    string username = context.Request.Params["username"] ?? "";
                    context.AcceptWebSocketRequest(new MySocket(username));
                }
            }

            public bool IsReusable {
                get { throw new NotImplementedException(); }
            }

            #endregion
        }
    }

    Now, I've built a small test page and I'm able to send an receive several messages, so I'm assuming the previous code is working.

    The problem: I've tried building a metro app with JS and my app crashes when I try to recoved the data reader from the callback message. Here's the markup I'm using in my page:

    <body>
        <h1>MessageWebSocket</h1>
        <div id="grid">
            <div id="login">
                <label for="username">Nome:</label>
               <input type="text" id="username" placeholder="Nome de utilizador"/>
               <input type="button" value="Ligar-se" id="ligar"/>
            </div>
            <div id="dados">
                <label for="msgEnviar">Mensagem:</label><br/>
                <input type="text" id="msgEnviar" />
                <input type="button" value="Enviar mensagem" id="enviar"/><br/>
                <input type="button" value="Encerrar" id="encerrar"/>
                <div id="info"></div>
            </div>     
              
        </div>
    </body>

    And here's the JS code:

    (function () {
        "use strict";

        var baseUrl = "ws://localhost/sockets/socket.ashx";
        var app = WinJS.Application;
        
        var divLogin = null, divDados = null,
            socket = null, divInfo = null, txt = null;
        app.onactivated = function (eventObject) {
            divLogin = document.getElementById("login");
            divDados = document.getElementById("dados");
            divInfo = document.getElementById("info");
            txt = document.getElementById("msgEnviar");
            document.getElementById("ligar").addEventListener("click", efetuaLogin);
            document.getElementById("encerrar").addEventListener("click", encerraSessao);
            document.getElementById("enviar").addEventListener("click", enviaMsg);
        };
        
        function efetuaLogin() {
            var username = document.getElementById("username").value;
            var url = baseUrl + "?username=" + username;
            socket = new Windows.Networking.Sockets.MessageWebSocket();
            socket.control.messageType = Windows.Networking.Sockets.SocketMessageType.utf8;
            socket.addEventListener("messagereceived", mensagemRecebida);
            socket.addEventListener("closed", socketEncerrado);
            var uri = new Windows.Foundation.Uri(url);
            return socket.connectAsync(uri)
                .done(function () {
                    divLogin.style.display = "none";
                    divDados.style.display = "block";
                    imprimeMsg("Ligado ao servidor");
                });
        }
        function encerraSessao() {
            if (socket) {
                estaEncerrar = true;
                socket.close();
                divLogin.style.display = "block";
                divDados.style.display = "none";
                socket = null;
                estaEncerrar = false;
                imprimeMsg("Socket cliente encerrado");
            }
        }
        function enviaMsg() {
            var writer = new Windows.Storage.Streams.DataWriter(socket.outputStream);
            writer.writeString(txt.value);
            writer.storeAsync()
                .then(function () {
                    writer.detachBuffer();
                });
        }
        function mensagemRecebida(e) {
            var reader = e.getDataReader();
            var totalChars = reader.unconsumedBufferLength;
            if (totalChars <= 0) return;
            var aux = JSON.parse(reader.readString(totalChars));
            imprimeMsg(aux.utilizador + "[" + aux.data + "]: " + aux.texto);
        }
        var estaEncerrar = false;
        function socketEncerrado() {
            if (socket != null && !estaEncerrar) {
                imprimeMsg("Sessao desligada servidor");
                encerraSessao();
            }
        }

        function imprimeMsg(msg) {
            divInfo.innerHTML += msg + "<br>";
        }
        app.oncheckpoint = function (eventObject) {
            // TODO: This application is about to be suspended. Save any state
            // that needs to persist across suspensions here. You might use the 
            // WinJS.Application.sessionState object, which is automatically
            // saved and restored across suspension. If you need to complete an
            // asynchronous operation before your application is suspended, call
            // eventObject.setPromise(). 
        };

        app.start();
    })();

    Any clue son what's going on here?


    Luis Abreu

    Sunday, June 17, 2012 12:05 PM

Answers

All replies

  • Hi Luis,

    Is the handler on the same machine?  If so, this is blocked by the system.

    -Jeff


    Jeff Sanders (MSFT)

    Tuesday, June 19, 2012 5:59 PM
    Moderator
  • Everything is on the same machine.

    Can you be more specific about "blocked by system"? Are you talking about the metro app? If so, doesn't VS automatically removes the localhost restriction? or are you talking about something else?

    As I mentioned, I've also built an html page and everything works there...


    Luis Abreu

    Tuesday, June 19, 2012 8:47 PM
  • Yes an HTML page is not running as a Metro style app so it will work fine.

    No VS does not automatically remove the restiction.  Also your app will not pass through the Store process if it is using localhost.  You can hit an external webservice however!


    Jeff Sanders (MSFT)

    Wednesday, June 20, 2012 2:00 PM
    Moderator
  • But is there any way for me to test it on the same machine? 


    Luis Abreu

    Wednesday, June 20, 2012 5:59 PM
  • Wednesday, June 20, 2012 6:00 PM
    Moderator
  • I'll give it a try and I'll return if it doesn't work.



    Luis Abreu

    Wednesday, June 20, 2012 6:32 PM
  • Nop, it does not work.

    THere's something definitely wrong with the code and I don't know what it is.

    As I said, I've also built a simple html page to send and receive messages. that page works. establishing the connection from the metro app does work. What doesn't work is receiving the second message from the web socket. when that happens, the app crashes on the e.getDataReader line. btw, the message sent by the metro app is being correctly broadcasting to the other clients and it's being shown in my HTML test page.

    Would you mind running my code? If you want, I can send you both projects (asp.net socket and the metro apps)

    thanks.


    Luis Abreu

    Wednesday, June 27, 2012 9:07 AM
  • Has anyone managed to use web sockets? 

    thanks.


    Luis Abreu

    Monday, July 02, 2012 8:37 PM
  • Hey Luis,

    Send me your code and I will take a crack at it!

    -Jeff


    Jeff Sanders (MSFT)

    Tuesday, July 03, 2012 2:57 PM
    Moderator
  • Thanks Jeff.

    Have already sent it to you.



    Luis Abreu

    Tuesday, July 03, 2012 11:31 PM