关闭时WebSockets错误

时间:2017-03-02 14:20:53

标签: javascript jquery asp.net html5 websocket

我是WebSockets的新手,正在尝试我在网上找到的一个例子。简单示例使服务器鹦鹉回到我在文本框中输入的内容。有一个按钮可以将文本发送到服务器,还有一个按钮可以关闭与服务器的连接。

以下是WebSocketHandler的代码:

<%@ WebHandler Language="C#" Class="WebSocketHandler" %>

using System;
using System.Text;
using System.Web;
using System.Web.WebSockets;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;

public class WebSocketHandler : IHttpHandler {

public void ProcessRequest (HttpContext context) {
    if (context.IsWebSocketRequest) {
        context.AcceptWebSocketRequest(DoTalking);
    }
}

public bool IsReusable {
    get {
        return false;
    }
}

public async Task DoTalking(AspNetWebSocketContext context) {
    WebSocket socket = context.WebSocket;

    while (true) {
        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);
        WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);

        if (socket.State == WebSocketState.Open) {
            string userMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
            userMessage = "You sent: " + userMessage + " at " + DateTime.Now.ToLongTimeString();
            buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMessage));
            await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
        } else {
            break;
        }
    }
}

这是客户端上的JQuery:

var socket;
$(document).ready(function () {
socket = new WebSocket("ws://localhost:61530/WebSocketHandler.ashx");

socket.onopen = function (evt) {
    $("#serverMessage").append("<h3>Connection Opened with the Echo server.</h3>");
};

socket.onmessage = function (evt) {
    $("#serverMessage").append("<h3>" + evt.data + "</h3>");
};

socket.onerror = function (evt) {
    $("#serverMessage").append("<h3>Unexpected Error</h3>");
};

socket.onclose = function (evt) {
    $("#serverMessage").append("<h3>Connection closed</h3>");
}

$("#btnSend").click(function () {
    if (socket.readyState === WebSocket.OPEN) {
        socket.send($("#txtMsg").val());
    } else {
        $("#serverMessage").append("<h3>The underlying connection is closed</h3>");
    }
});

$("#btnStop").click(function () {
    socket.close();
});
});

通过向服务器发送消息并获取响应,一切正常。问题是当我单击按钮关闭websocket时。单击该按钮时,它会首先触发onerror事件,然后触发onclose事件。任何人都可以告诉我为什么会这样做和/或如果我做错了什么? 提前谢谢。

注意:我已经在IE,Edge,Firefox,Chrome和Opera上试过了这个。该问题仅发生在IE,Edge和Firefox上。

1 个答案:

答案 0 :(得分:2)

我弄明白了这个问题。在我的处理程序中,我有一行来打破while循环,我不得不添加一个CloseAsync()调用以确保套接字以正常闭包关闭。以下是经过修改的DoTalking功能,可在所有浏览器上正常运行:

public async Task DoTalking(AspNetWebSocketContext context) {
    WebSocket socket = context.WebSocket;

    while (true) {
        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);
        WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);

        if (socket.State == WebSocketState.Open) {
            string userMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
            userMessage = "You sent: " + userMessage + " at " + DateTime.Now.ToLongTimeString();
            buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMessage));
            await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
        } else {
            // The following line is the line I had to add to correct the problem
            await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Socket closed", CancellationToken.None);
            break;
        }
    }
}
编辑:因为这只是我工作的一个例子,我只是这样做,但在生产环境中,我可能需要添加不同的代码来处理不同的关闭原因。这样,如果由于错误而关闭,我可以处理它与正常关闭不同。