websockets socket servidor net example ejemplo asp c# asp.net session websocket connection

c# - servidor - websocket php



Cómo realizar un seguimiento de las conexiones establecidas utilizando WebSockets (2)

Por lo general, no haces algo como eso. El WebSocket debe ser justo y punto final a otra capa o subsistema. Por ejemplo, una arquitectura impulsada por eventos. Al conectarse, debe iniciar el controlador, recopilar datos del socket conectado como la cookie, la URL o lo que sea, y notificar a otra persona que ese usuario con esa cookie / url está conectado en ese socket.

Acerca de tu código:

  • No declare el búfer de lectura dentro del bucle, puede reutilizarlo.
  • WebSockets siempre envía datos de texto como UTF8, no ASCII.

Esta sería una forma de hacer un seguimiento de sus usuarios en un proyecto pequeño, pero le recomiendo que conecte el WebSocket a otra infraestructura de mensajes como MassTransit:

public class WSHandler : IHttpHandler { public bool IsReusable { get { return false; } } public void ProcessRequest(HttpContext context) { if (context.IsWebSocketRequest) { context.AcceptWebSocketRequest(ProcessWSChat); } } static readonly ConcurrentDictionary<IPrincipal, WebSocket> _users = new ConcurrentDictionary<IPrincipal, WebSocket>(); private async Task ProcessWSChat(AspNetWebSocketContext context) { WebSocket socket = context.WebSocket; ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[4096]); //Identify user by cookie or whatever and create a user Object var cookie = context.Cookies["mycookie"]; var url = context.RequestUri; IPrincipal myUser = GetUser(cookie, url); // Or uses the user that came from the ASP.NET authentication. myUser = context.User; _users.AddOrUpdate(myUser, socket, (p, w) => socket); while (socket.State == WebSocketState.Open) { WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None) .ConfigureAwait(false); String userMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count); userMessage = "You sent: " + userMessage + " at " + DateTime.Now.ToLongTimeString() + " from ip " + context.UserHostAddress.ToString(); var sendbuffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMessage)); await socket.SendAsync(sendbuffer , WebSocketMessageType.Text, true, CancellationToken.None) .ConfigureAwait(false); } // when the connection ends, try to remove the user WebSocket ows; if (_users.TryRemove(myUser, out ows)) { if (ows != socket) { // whops! user reconnected too fast and you are removing // the new connection, put it back _users.AddOrUpdate(myUser, ows, (p, w) => ows); } } } private IPrincipal GetUser(HttpCookie cookie, Uri url) { throw new NotImplementedException(); } }

Estoy tratando de dar vida a un servicio de chat en tiempo real para dispositivos multiplataforma. El problema es que el espacio de nombres System.Net.WebSockets no me permite realizar un seguimiento de una conexión establecida. Podría tomar un ID de sesión de la conexión actual, pero ¿cómo puedo decir que realice la siguiente acción en await socket.SendAsync(buffer, WebSocketMessageType.Text, CancellationToken.None) para un cliente específico?

Si pudiera usar Microsoft.WebSockets , tendría la posibilidad de crear un WebSocketCollection() y hacer algo como client.Send(message) , pero no puedo enviar un ArraySegment<byte[]> través de él. También creo que esto es más adecuado para los clientes y sitios web de AJAX y esto.

Ahora tengo el siguiente fragmento de código:

public class WSHandler : IHttpHandler { event NewConnectionEventHandler NewConnection; public void ProcessRequest(HttpContext context) { if (context.IsWebSocketRequest) { context.AcceptWebSocketRequest(ProcessWSChat); } } public bool IsReusable { get { return false; } } private async Task ProcessWSChat(AspNetWebSocketContext context) { WebSocket socket = context.WebSocket; int myHash = socket.GetHashCode(); 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.ASCII.GetString( buffer.Array, 0, result.Count); userMessage = "You sent: " + userMessage + " at " + DateTime.Now.ToLongTimeString() + " from ip " + context.UserHostAddress.ToString(); buffer = new ArraySegment<byte>( Encoding.ASCII.GetBytes(userMessage)); await socket.SendAsync( buffer, WebSocketMessageType.Text, true, CancellationToken.None); } else { break; } } } }

¿Cómo puedo extender mi proyecto, guardar las sesiones / conexiones y llamar a una conexión de usuario específica para enviar un mensaje?


Creo que reinventar la rueda sería muy estúpido, así que mejor uso SignalR para este propósito.

¡Gracias @Jonesy por informarme sobre esta biblioteca de Microsoft!

editar:

SignalR no funciona correctamente en modo no "IIS Express". "IIS local" hace que todo el proyecto falle.

editar:

SignalR funciona ahora. Una regla de reescritura hizo imposible obtener el camino correcto.