2010-02-06 15 views
60

Estoy tratando de implementar un servidor de socket web C#, pero me da algunos problemas. Estoy ejecutando un servidor web (ASP.NET) para alojar la página con javascript y el servidor de socket web está implementado como una aplicación de consola C#.servidor Websocket: la función onopen en el socket web nunca se llama

Soy capaz de detectar el intento de conexión del cliente (Chrome ejecutando el javascript) y también para recuperar el protocolo de enlace del cliente. Pero el cliente no parece aceptar el saludo de manos que estoy enviando (nunca se llama a la función onopen en el socket web).

He estado leyendo The Web Socket protocol y no puedo ver lo que estoy haciendo mal. Heres un poco del código del servidor:

Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8181); 
listener.Bind(ep); 
listener.Listen(100); 
Console.WriteLine("Wainting for connection..."); 
Socket socketForClient = listener.Accept(); 
if (socketForClient.Connected) 
{ 
    Console.WriteLine("Client connected"); 
    NetworkStream networkStream = new NetworkStream(socketForClient); 
    System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream); 
    System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream); 

    //read handshake from client: 
    Console.WriteLine("HANDSHAKING..."); 
    char[] shake = new char[255]; 
    streamReader.Read(shake, 0, 255); 

    string handshake = 
     "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" + 
     "Upgrade: WebSocket\r\n" + 
     "Connection: Upgrade\r\n" + 
     "WebSocket-Origin: http://localhost:8080\r\n" + 
     "WebSocket-Location: ws://localhost:8181\r\n" + 
     "\r\n"; 

    streamWriter.Write(handshake); 
    streamWriter.Flush(); 

estoy corriendo con el servidor web en el puerto 8080 y el servidor de socket web en el puerto 8181, tanto en mi localhost.

He intentado enviar el protocolo de enlace en diferentes codificaciones (ASCII, bytes y Hex) pero esto no parece marcar la diferencia. La conexión nunca está completamente establecida. El Javascript se parece a esto:

var ws; 
var host = 'ws://localhost:8181'; 
debug("Connecting to " + host + " ..."); 
try { 
ws = new WebSocket(host); 
} catch (err) { 
debug(err, 'error'); 
} 
ws.onopen = function() { 
debug("connected...", 'success'); 
}; 
ws.onclose = function() { 
debug("Socket closed!", 'error'); 
}; 
ws.onmessage = function (evt) { 
debug('response: ' + evt, 'response'); 
}; 

supongo que el error reside en el servidor de C# como el cromo es el envío de la información como debe ser, pero como dice la función onopen nunca es llamado.

Así que mi pregunta en resumen: Alguno de ustedes ha logrado esto - y si es así, ¿cómo lo hicieron? Y de la causa: ¿Ve algún error aparente en el código (espero que no sea mucho pedir)

+1

Es posible que desee utilizar Fleck, disponible en NuGet: http://nuget.org/packages/Fleck/ –

Respuesta

47

Probablemente es un problema de codificación. Aquí hay un trabajo servidor de C# escribí:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var listener = new TcpListener(IPAddress.Loopback, 8181); 
     listener.Start(); 
     using (var client = listener.AcceptTcpClient()) 
     using (var stream = client.GetStream()) 
     using (var reader = new StreamReader(stream)) 
     using (var writer = new StreamWriter(stream)) 
     { 
      writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake"); 
      writer.WriteLine("Upgrade: WebSocket"); 
      writer.WriteLine("Connection: Upgrade"); 
      writer.WriteLine("WebSocket-Origin: http://localhost:8080"); 
      writer.WriteLine("WebSocket-Location: ws://localhost:8181/websession"); 
      writer.WriteLine(""); 
     } 
     listener.Stop(); 
    } 
} 

y el cliente correspondiente alojado en localhost:8080:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
    <script type="text/javascript"> 
     var socket = new WebSocket('ws://localhost:8181/websession'); 
     socket.onopen = function() { 
     alert('handshake successfully established. May send data now...'); 
     }; 
     socket.onclose = function() { 
     alert('connection closed'); 
     }; 
    </script> 
    </head> 
    <body> 
    </body> 
</html> 

Este ejemplo sólo establece el apretón de manos. Tendrá que ajustar el servidor para continuar aceptando datos una vez que se haya establecido el protocolo de enlace.

+1

Gracias! Resulta que era la parte del apretón de manos de WebSocket-Location lo que me estaba dando problemas. Aparentemente no puede ser solo 'ws: // localhost: 8181'. Después de cambiarlo a 'ws: // localhost: 8181/algo' y cambiar el host en el javascript a la misma cosa, funcionó. –

+0

Gracias por la publicación. Lo estaba intentando con Chrome + un archivo html estático y tuve que cambiar el origen para evitar que el navegador se desconectara inmediatamente: writer.WriteLine ("Origen del origen web: archivo: //"); –

+0

@Darin Tu código está funcionando bien. No funcionó cuando eliminé ese "uso" y lo declare "escritor" como de costumbre. El caso es que el escritor no le escribió al cliente. ¿Puede explicar esto? – prabhakaran

24

Utilice la codificación UTF8 para enviar mensajes de texto.

Hay un servidor de websocket de fuente abierta que se implementa mediante C#, puede usarlo directamente.

http://superwebsocket.codeplex.com/

Es mi proyecto de código abierto!

+2

Ahora, SuperWebSocket también contiene una implementación del cliente WebSocket. –

3

.NET Framework 4.5 introduce soporte para WebSockets en Windows Communication Foundation. WebSockets es una tecnología eficiente basada en estándares que permite la comunicación bidireccional a través de los puertos HTTP estándar 80 y 44 de . El uso de puertos HTTP estándar permite que WebSockets se comuniquen a través de la web a través de intermediarios. Se han agregado dos nuevos enlaces estándar para admitir la comunicación a través de un transporte WebSocket . NetHttpBinding y NetHttpsBinding. La configuración específica de WebSockets se puede configurar en el elemento HttpTransportBinding accediendo a la propiedad WebSocketSettings .

Creo que todavía utiliza SOAP aunque

http://msdn.microsoft.com/en-us/library/hh674271(v=vs.110).aspx

Cuestiones relacionadas