2010-02-06 9 views
60

Sto provando a implementare un server Web socket C#, ma mi dà alcuni problemi. Sto eseguendo un server web (ASP.NET) per ospitare la pagina con il javascript e il server socket Web è implementato come un'applicazione console C#.Server Websocket: la funzione onopen sulla presa Web non viene mai chiamata

Sono in grado di rilevare il tentativo di connessione dal client (chrome che esegue il javascript) e anche di recuperare l'handshake dal client. Ma il client non sembra accettare la stretta di mano che sto rinviando (la funzione onopen sul socket Web non viene mai chiamata).

Ho letto il The Web Socket protocol e non riesco a vedere cosa sto facendo male. Heres un po 'di codice del server:

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(); 

sto correndo al server web sulla porta 8080 e il server socket web sulla porta 8181, sia sul mio localhost.

Ho provato a inviare l'handshake in diverse codifiche (ASCII, byte e Hex) ma questo non sembra fare la differenza. La connessione non è mai completamente stabilita. Il javascript è simile al seguente:

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'); 
}; 

Sto indovinando che l'errore sta nel server di C# come cromo sta inviando le informazioni come dovrebbe, ma come detto la funzione onopen non viene mai chiamato.

Quindi la mia domanda in breve: ha qualsiasi di voi ha mai compiuto questo - e se sì, come hai fatto? E di causa: Vedete errori apparenti nel codice (speriamo che non sia molto da chiedere)

+1

Si consiglia di utilizzare Fleck, accessibile NuGet: http://nuget.org/packages/Fleck/ –

risposta

47

Probabilmente si tratta di un problema di codifica. Ecco un lavoro C# del server ho scritto:

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(); 
    } 
} 

e il corrispondente cliente ospitato su 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> 

Questo esempio stabilisce solo la stretta di mano. Sarà necessario modificare il server per continuare ad accettare i dati una volta stabilita l'handshake.

+1

Grazie! Risulta che era la parte WebSocket-Location della stretta di mano che mi stava dando problemi. Apparentemente non può essere solo 'ws: // localhost: 8181'. Dopo averlo modificato in "ws: // localhost: 8181/qualcosa" e modificato l'host in javascript sulla stessa cosa, ha funzionato. –

+0

Grazie per il post. Stavo tentando di farlo con Chrome + un file html statico e ho dovuto modificare l'origine per impedire la disconnessione immediata del browser: writer.WriteLine ("WebSocket-Origin: file: //"); –

+0

@Darin Il tuo codice funziona correttamente. Non ha funzionato quando ho rimosso "l'uso" e dichiarato "scrittore" come al solito. Il fatto è che lo scrittore non ha scritto di nuovo al cliente. Puoi spiegare questo? – prabhakaran

24

Utilizzare la codifica UTF8 per inviare messaggi di testo.

C'è un server WebSocket open source che è implementato da C#, è possibile utilizzarlo direttamente.

http://superwebsocket.codeplex.com/

E 'il mio progetto open source!

+2

Ora, SuperWebSocket contiene anche un'implementazione client WebSocket! –

3

.NET Framework 4.5 introduce il supporto per WebSockets in Windows Communication Foundation. WebSockets è una tecnologia efficiente basata su standard che consente la comunicazione bidirezionale tramite le porte HTTP standard 80 e 443. L'uso delle porte HTTP standard consente a WebSockets di comunicare attraverso il Web tramite intermediari. Sono state aggiunte due nuove associazioni standard per supportare la comunicazione tramite un trasporto WebSocket . NetHttpBinding e NetHttpsBinding. Le impostazioni specifiche di WebSockets possono essere configurate sull'elemento HttpTransportBinding accedendo alla proprietà WebSocketSettings .

Penso che usa ancora SOAP se

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

Problemi correlati