C# WebSockets On Windows 7 with OWIN

依然范特西╮ 提交于 2019-12-14 02:27:05

问题


I am trying to use WebSockets on Windows 7. I trying to use System.Net.Sockets, I have tried following these examples, but each of them has one problem or another running on Windows 7:

WebSocket Server in C# ,Writing a WebSocket server in C# , Creating a “Hello World” WebSocket example , How to implement an asynchronous socket in C#, MULTI-THREADED TCP SERVER IN C# ,Paul Batum

I have looked into several 3rd party tools, but it looks like they are either no longer supported or in beta.

Here's the code I have so far:

public class WebSocketService {
    private TcpListener _listener;
    private TcpClient _tcpClient;
    public event Action<NetworkStream> OnLoadData;

    public WebSocketService() {
       Listen();
    }

    public void Listen(int port) {
       _listener = new TcpListener(IPAddress.Parse("127.0.0.1"), port);
       _listener.Start();
       _listener.BeginAcceptTcpClient(HandleAsyncConnection, null);
    }

    private void HandleAsyncConnection(IAsyncResult result)
    {
        try
        {
            _tcpClient = _listener.EndAcceptTcpClient(result);
            _tcpClient.NoDelay = true;
            NetworkStream stream = _tcpClient.GetStream();

            // extract the connection details and use those details to build a connection
            ConnectionDetails connectionDetails = GetConnectionDetails(stream, _tcpClient);
            PerformHandshake(stream, connectionDetails.Header);

            if (connectionDetails.Path.Equals("/myApiPath"))
            {
                OnLoadData?.Invoke(stream);
            }

        }
        catch (Exception ex)
        {
            //write ex to log
            throw;
        }
    }

    private static ConnectionDetails GetConnectionDetails(NetworkStream stream, TcpClient tcpClient)
    {
        // read the header and check that it is a GET request
        string header = HttpHelper.ReadHttpHeader(stream);
        var getRegex = new Regex(@"^GET(.*)HTTP\/1\.1", RegexOptions.IgnoreCase);

        Match getRegexMatch = getRegex.Match(header);
        if (getRegexMatch.Success)
        {
            // extract the path attribute from the first line of the header
            string path = getRegexMatch.Groups[1].Value.Trim();

            // check if this is a web socket upgrade request
            var webSocketUpgradeRegex = new Regex("Upgrade: websocket", RegexOptions.IgnoreCase);
            Match webSocketUpgradeRegexMatch = webSocketUpgradeRegex.Match(header);

            if (webSocketUpgradeRegexMatch.Success)
            {
                return new ConnectionDetails(stream, tcpClient, path, ConnectionType.WebSocket, header);
            }

            return new ConnectionDetails(stream, tcpClient, path, ConnectionType.Http, header);
        }

        return new ConnectionDetails(stream, tcpClient, string.Empty, ConnectionType.Unknown, header);
    }

    private void PerformHandshake(Stream stream, string header)
    {
       try
        {
            Regex webSocketKeyRegex = new Regex("Sec-WebSocket-Key: (.*)");
            Regex webSocketVersionRegex = new Regex("Sec-WebSocket-Version: (.*)");

            // check the version. Support version 13 and above
            const int webSocketVersion = 13;
            int secWebSocketVersion = Convert.ToInt32(webSocketVersionRegex.Match(header).Groups[1].Value.Trim());
            if (secWebSocketVersion < webSocketVersion)
            {
                //throw some exception
            }

            string secWebSocketKey = webSocketKeyRegex.Match(header).Groups[1].Value.Trim();
            string setWebSocketAccept = ComputeSocketAcceptString(secWebSocketKey);
            var newLine = "\r\n";

            string response = ("HTTP/1.1 101 Switching Protocols" + newLine
                               + "Connection: Upgrade" + newLine
                               + "Upgrade: websocket" + newLine
                               + "Sec-WebSocket-Accept: " + setWebSocketAccept + newLine + newLine);

            WriteHttpHeader(response, stream);

        }
        catch (Exception ex)
        {
            // Write Log Entry(ex);
            WriteHttpHeader("HTTP/1.1 400 Bad Request", stream);
            throw;
        }
    }
}

When the OnLoadData event fires it calls another class which simply has:

var jsonSerializerSettings = new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            };

            var message = JsonConvert.SerializeObject(someData, jsonSerializerSettings);
            var messageData = Encoding.UTF8.GetBytes(message);


            _clientStream.Write(messageData, 0, messageData.Length);
            _clientStream.Flush();

I then get this error:

An established connection was aborted by the software in your host machine at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size) NativeErrorCode 10053 int SocketErrorCode ConnectionAborted System.Net.Sockets.SocketError

I am looking for a simple C# WebSockets implementation that works on Windows 7. I cannot use SignalR or ASP.NET because I am using OWIN to self-host Web API.

I took a look at this post, but I can't figure out how the OP made it work. Anyone know how to do this?

来源:https://stackoverflow.com/questions/47481999/c-sharp-websockets-on-windows-7-with-owin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!