Servidor
Código C#:
Ver original
using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; using System.Threading; namespace Consola { internal class Program { static List<TcpClient> tcpClients = new List<TcpClient>(); static void Main(string[] args) { string ip = "127.0.0.1"; int port = 8080; var server = new TcpListener(IPAddress.Parse(ip), port); server.Start(); Console.WriteLine("Server has started on {0}:{1}, Waiting for a connection…", ip, port); TcpClient client = server.AcceptTcpClient(); tcpClients.Add(client); Console.WriteLine("A client connected."); NetworkStream stream = client.GetStream(); // enter to an infinite cycle to be able to handle every change in stream while (true) { while (!stream.DataAvailable) ; while (client.Available < 3) ; // match against "get" byte[] bytes = new byte[client.Available]; stream.Read(bytes, 0, client.Available); string s = Encoding.UTF8.GetString(bytes); if (Regex.IsMatch(s, "^GET", RegexOptions.IgnoreCase)) { Console.WriteLine("=====Handshaking from client=====\n{0}", s); // 1. Obtain the value of the "Sec-WebSocket-Key" request header without any leading or trailing whitespace // 2. Concatenate it with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" (a special GUID specified by RFC 6455) // 3. Compute SHA-1 and Base64 hash of the new value // 4. Write the hash back as the value of "Sec-WebSocket-Accept" response header in an HTTP response string swk = Regex.Match(s, "Sec-WebSocket-Key: (.*)").Groups[1].Value.Trim(); string swka = swk + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; byte[] swkaSha1 = System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(swka)); string swkaSha1Base64 = Convert.ToBase64String(swkaSha1); // HTTP/1.1 defines the sequence CR LF as the end-of-line marker byte[] response = Encoding.UTF8.GetBytes( "HTTP/1.1 101 Switching Protocols\r\n" + "Connection: Upgrade\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Accept: " + swkaSha1Base64 + "\r\n\r\n"); stream.Write(response, 0, response.Length); } else { bool fin = (bytes[0] & 0b10000000) != 0, mask = (bytes[1] & 0b10000000) != 0; // must be true, "All messages from the client to the server have this bit set" int opcode = bytes[0] & 0b00001111, // expecting 1 - text message offset = 2; ulong msglen = (ulong)(bytes[1] & 0b01111111); if (msglen == 126) { // bytes are reversed because websocket will print them in Big-Endian, whereas // BitConverter will want them arranged in little-endian on windows msglen = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0); offset = 4; } else if (msglen == 127) { // To test the below code, we need to manually buffer larger messages — since the NIC's autobuffering // may be too latency-friendly for this code to run (that is, we may have only some of the bytes in this // websocket frame available through client.Available). msglen = BitConverter.ToUInt64(new byte[] { bytes[9], bytes[8], bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2] }, 0); offset = 10; } if (msglen == 0) { Console.WriteLine("msglen == 0"); } else if (mask) { byte[] decoded = new byte[msglen]; byte[] masks = new byte[4] { bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3] }; offset += 4; for (ulong i = 0; i < msglen; ++i) decoded[i] = (byte)(bytes[(ulong)offset + i] ^ masks[i % 4]); string text = Encoding.UTF8.GetString(decoded); Console.WriteLine("{0}", text); } else Console.WriteLine("mask bit not set"); Console.WriteLine(); } } } } }
Cliente
Código HTML:
Ver original
<!DOCTYPE html> <html lang="en"> <head> <link href="Content/bootstrap.min.css" type="text/css" rel="stylesheet" /> </head> <body> <div class="card"> <div class="card-header"> </div> <div class="card-body"> <p> </p> <p> </p> <p> </p> </div> </div> <style type="text/css"> textarea { vertical-align: bottom; } #salida { overflow: auto; } #salida > p { overflow-wrap: break-word; } #salida span { color: blue; } #salida span.error { color: red; } </style> <script type="text/javascript"> $(document).ready(function () { const wsUri = "ws://127.0.0.1:8080/"; const websocket = new WebSocket(wsUri); $(document).on("click", "#boton", onClickButton); websocket.onopen = (e) => { writeToScreen("CONNECTED"); doSend("WebSocket rocks"); }; websocket.onclose = (e) => { writeToScreen("DISCONNECTED"); }; websocket.onmessage = (e) => { }; websocket.onerror = (e) => { }; function doSend(message) { writeToScreen(`SENT: ${message}`); websocket.send(message); } function writeToScreen(message) { } function onClickButton() { var text = $("#cajadetexto").val(); text && doSend(text); $("#cajadetexto").val(""); $("#cajadetexto").focus(); } }); </script> </body> </html>
Necesito que el cliente se ejecuta en un proyecto web mientras que el servidor en un proyecto de consola.
Intenté de todo, pero lo que obtuve fue lo de la imagen:
Espero sus respuestas y saludos.