代码改变世界

.NET Core 学习笔记之 WebSocketsSample

2019-06-30 14:48  音乐让我说  阅读(794)  评论(0)    收藏  举报

1. 服务端

代码如下:

Program:

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace WebSocketsServer
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }
}

 

Startup:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace WebSocketsServer
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            // configure keep alive interval, receive buffer size
            app.UseWebSockets();

            app.Map("/samplesockets", app2 =>
            {
                // middleware to handle websocket request
                app2.Use(async (context, next) =>
                {
                    if (context.WebSockets.IsWebSocketRequest)
                    {
                        var webSocket = await context.WebSockets.AcceptWebSocketAsync();
                        await SendMessagesAsync(context, webSocket, loggerFactory.CreateLogger("SendMessages"));
                    }
                    else
                    {
                        await next();
                    }
                }); 
            });

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Web Sockets sample");
            });
        }

        private async Task SendMessagesAsync(HttpContext context, WebSocket webSocket, ILogger logger)
        {
            var buffer = new byte[4096];
            WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            while (!result.CloseStatus.HasValue)
            {
                if (result.MessageType == WebSocketMessageType.Text)
                {
                    string content = Encoding.UTF8.GetString(buffer, 0, result.Count);
                    if (content.StartsWith("REQUESTMESSAGES:"))
                    {
                        string message = content.Substring("REQUESTMESSAGES:".Length);
                        for (int i = 0; i < 10; i++)
                        {
                            string messageToSend = $"{message} - {i}";
                            if (i == 9)
                            {
                                messageToSend += ";EOS"; // send end of sequence to not let the client wait for another message
                            }
                            byte[] sendBuffer = Encoding.UTF8.GetBytes(messageToSend);
                            await webSocket.SendAsync(new ArraySegment<byte>(sendBuffer), WebSocketMessageType.Text, endOfMessage: true, CancellationToken.None);
                            logger.LogDebug("sent message {0}", messageToSend);
                            await Task.Delay(1000);
                        }
                    }

                    if (content.Equals("SERVERCLOSE"))
                    {
                        await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Bye for now", CancellationToken.None);
                        logger.LogDebug("client sent close request, socket closing");
                        return;
                    }
                    else if (content.Equals("SERVERABORT"))
                    {
                        context.Abort();
                    }
                }

                result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
            }
        }
    }
}

launchSettings.json

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:58167/",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "WebSocketsServer": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:58168/"
    }
  }
}

 

 

 

2. 客户端

Program.cs

代码如下:

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

namespace WebSocketClient
{
    class Program
    {
        static async Task Main()
        {
            Console.WriteLine("Client - wait for server");
            Console.ReadLine();
            await InitiateWebSocketCommunication("ws://localhost:58167/samplesockets");
            //"ws://localhost:6295/samplesockets"
            //http://localhost:58167/
            Console.WriteLine("Program end");
            Console.ReadLine();          
        }

        static async Task InitiateWebSocketCommunication(string address)
        {
            try
            {
                var webSocket = new ClientWebSocket();
                await webSocket.ConnectAsync(new Uri(address), CancellationToken.None);

                await SendAndReceiveAsync(webSocket, "A");
                await SendAndReceiveAsync(webSocket, "B");
                await webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes("SERVERCLOSE")), 
                    WebSocketMessageType.Text, 
                    endOfMessage: true, 
                    CancellationToken.None);
                var buffer = new byte[4096];
                var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), 
                    CancellationToken.None);
                
                Console.WriteLine($"received for close: " +
                    $"{result.CloseStatus} " +
                    $"{result.CloseStatusDescription} " +
                    $"{Encoding.UTF8.GetString(buffer, 0, result.Count)}");
                await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, 
                    "Bye", 
                    CancellationToken.None);

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        static async Task SendAndReceiveAsync(WebSocket webSocket, string term)
        {
            byte[] data = Encoding.UTF8.GetBytes($"REQUESTMESSAGES:{term}");
            var buffer = new byte[4096];

            await webSocket.SendAsync(new ArraySegment<byte>(data), 
                WebSocketMessageType.Text, 
                endOfMessage: true, 
                CancellationToken.None);
            WebSocketReceiveResult result;
            bool sequenceEnd = false;
            do
            {
                result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), 
                    CancellationToken.None);
                string dataReceived = Encoding.UTF8.GetString(buffer, 0, result.Count);
                Console.WriteLine($"received {dataReceived}");
                if (dataReceived.Contains("EOS"))
                {
                    sequenceEnd = true;
                }

            } while (!(result?.CloseStatus.HasValue ?? false) && !sequenceEnd);
        }
    }
}

 

运行截图

 

谢谢浏览!