2013-03-13 106 views
3

我想现在已经到了我问别人的时候了。是否有可能使用HTML5代码中的C#和服务器请求创建websocket服务器?C#作为用于HTML5 websocket连接的Websocket服务器

我目前使用websocket的系统包。我有我下载在互联网上的编码,在这里,它是:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace WebSocketChatServer 
{ 
    using WebSocketServer; 

    class ChatServer 
    { 
     WebSocketServer wss; 
     List<User> Users = new List<User>(); 
     string unknownName = "john doe"; 


     public ChatServer() 
     { 

      // wss = new WebSocketServer(8181, "http://localhost:8080", "ws://localhost:8181/chat"); 

      wss = new WebSocketServer(8080, "http://localhost:8080", "ws://localhost:8080/dotnet/Chats"); 


      wss.Logger = Console.Out; 
      wss.LogLevel = ServerLogLevel.Subtle; 
      wss.ClientConnected += new ClientConnectedEventHandler(OnClientConnected); 
      wss.Start(); 
      KeepAlive(); 




     } 

     private void KeepAlive() 
     { 
      string r = Console.ReadLine(); 
      while (r != "quit") 
      { 
       if(r == "users") 
       { 
        Console.WriteLine(Users.Count); 
       } 
       r = Console.ReadLine(); 
      } 
     } 



     void OnClientConnected(WebSocketConnection sender, EventArgs e) 
     { 
      Console.WriteLine("test"); 
      Users.Add(new User() { Connection = sender }); 
      sender.Disconnected += new WebSocketDisconnectedEventHandler(OnClientDisconnected); 
      sender.DataReceived += new DataReceivedEventHandler(OnClientMessage); 

     } 

     void OnClientMessage(WebSocketConnection sender, DataReceivedEventArgs e) 
     { 
      Console.WriteLine(sender); 
      User user = Users.Single(a => a.Connection == sender); 
      if (e.Data.Contains("/nick")) 
      { 
       string[] tmpArray = e.Data.Split(new char[] { ' ' }); 
       if (tmpArray.Length > 1) 
       { 
        string myNewName = tmpArray[1]; 
        while (Users.Where(a => a.Name == myNewName).Count() != 0) 
        { 
         myNewName += "_"; 
        } 
        if (user.Name != null) 
         wss.SendToAll("server: '" + user.Name + "' changed name to '" + myNewName + "'"); 
        else 
         sender.Send("you are now know as '" + myNewName + "'"); 
        user.Name = myNewName; 
       } 
      } 
      else 
      { 
       string name = (user.Name == null) ? unknownName : user.Name; 
       wss.SendToAllExceptOne(name + ": " + e.Data, sender); 
       sender.Send("me: " + e.Data); 
      } 
     } 

     void OnClientDisconnected(WebSocketConnection sender, EventArgs e) 
     { 
      try 
      { 

       User user = Users.Single(a => a.Connection == sender); 
       string name = (user.Name == null) ? unknownName : user.Name; 
       wss.SendToAll("server: "+name + " disconnected"); 
       Users.Remove(user); 
      } 
      catch (Exception exc) 
      { 

       Console.WriteLine("ehm..."); 
      } 

     } 
    } 
} 

而且我对客户端验证码:

<!HTML> 
    <head> 

     <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> 
     </script> 

     <script language="javascript" type="text/javascript"> 

     jQuery(document).ready(function(){ 
      var socket = new WebSocket("ws://localhost:8080"); 
      socket.onopen = function(){ 
       alert("Socket has been opened!"); 
      } 
     }); 
     </script> 
    </head> 
</HTML> 

当我跑我的C#控制台应用程序并加载客户端页面,该应用程序告诉我,有人连接到它正在收听的端口。但在我的客户端,因为我期待在Firebug的控制台,它给我的初学者的经典错误:

Firefox can't establish a connection to the server at ws://localhost:8080/ 

我想什么来实现是建立第一个成功的WebSocket连接和推进价值我的客户来自哪里我服务器。

我已经考虑了Alchemy,但是我拥有的版本是Visual Studio express 2010,免费版,它说“解决方案文件夹在此版本的应用程序中不受支持”。

任何帮助将非常感激。

回答

0

我修改了代码,我在网上下载,这里就是我现在得到:

using System; 
using System.Collections.Generic; 
using System.Net.Sockets; 
using System.Net; 
using System.IO; 
using System.Security.Cryptography; 
using System.Threading; 




namespace WebSocketServer 
{ 
    public enum ServerLogLevel { Nothing, Subtle, Verbose }; 
    public delegate void ClientConnectedEventHandler(WebSocketConnection sender, EventArgs e); 

    public class WebSocketServer 
    { 
     #region private members 
     private string webSocketOrigin;  // location for the protocol handshake 
     private string webSocketLocation; // location for the protocol handshake 
     #endregion 
     static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 
     static IPEndPoint ipLocal; 

     public event ClientConnectedEventHandler ClientConnected; 

     /// <summary> 
     /// TextWriter used for logging 
     /// </summary> 
     public TextWriter Logger { get; set; }  // stream used for logging 

     /// <summary> 
     /// How much information do you want, the server to post to the stream 
     /// </summary> 
     public ServerLogLevel LogLevel = ServerLogLevel.Subtle; 

     /// <summary> 
     /// Gets the connections of the server 
     /// </summary> 
     public List<WebSocketConnection> Connections { get; private set; } 

     /// <summary> 
     /// Gets the listener socket. This socket is used to listen for new client connections 
     /// </summary> 
     public Socket ListenerSocker { get; private set; } 

     /// <summary> 
     /// Get the port of the server 
     /// </summary> 
     public int Port { get; private set; } 


     public WebSocketServer(int port, string origin, string location) 
     { 
      Port = port; 
      Connections = new List<WebSocketConnection>(); 
      webSocketOrigin = origin; 
      webSocketLocation = location; 
     } 

     /// <summary> 
     /// Starts the server - making it listen for connections 
     /// </summary> 
     public void Start() 
     { 
      // create the main server socket, bind it to the local ip address and start listening for clients 
      ListenerSocker = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 
      ipLocal = new IPEndPoint(IPAddress.Loopback, Port); 
      ListenerSocker.Bind(ipLocal); 
      ListenerSocker.Listen(100); 



      LogLine(DateTime.Now + "> server stated on " + ListenerSocker.LocalEndPoint, ServerLogLevel.Subtle); 

      ListenForClients(); 
     } 

     // look for connecting clients 
     private void ListenForClients() 
     { 
      ListenerSocker.BeginAccept(new AsyncCallback(OnClientConnect), null); 
     } 

     private void OnClientConnect(IAsyncResult asyn) 
     { 

      byte[] buffer = new byte[1024]; 
      string headerResponse = ""; 

      // create a new socket for the connection 
      var clientSocket = ListenerSocker.EndAccept(asyn); 
      var i = clientSocket.Receive(buffer); 
      headerResponse = (System.Text.Encoding.UTF8.GetString(buffer)).Substring(0, i); 
      //Console.WriteLine(headerResponse); 


      if (clientSocket != null) 
      { 

       // Console.WriteLine("HEADER RESPONSE:"+headerResponse); 
       var key = headerResponse.Replace("ey:", "`") 
           .Split('`')[1]      // dGhlIHNhbXBsZSBub25jZQ== \r\n ....... 
           .Replace("\r", "").Split('\n')[0] // dGhlIHNhbXBsZSBub25jZQ== 
           .Trim(); 
       var test1 = AcceptKey(ref key); 
       var newLine = "\r\n"; 
       var name = "Charmaine"; 
       var response = "HTTP/1.1 101 Switching Protocols" + newLine 
         + "Upgrade: websocket" + newLine 
         + "Connection: Upgrade" + newLine 
         + "Sec-WebSocket-Accept: " + test1 + newLine + newLine 
         + "Testing lang naman po:" + name 
         ; 

       // which one should I use? none of them fires the onopen method 
       clientSocket.Send(System.Text.Encoding.UTF8.GetBytes(response)); 
      } 





      // keep track of the new guy 
      var clientConnection = new WebSocketConnection(clientSocket); 
      Connections.Add(clientConnection); 
      // clientConnection.Disconnected += new WebSocketDisconnectedEventHandler(ClientDisconnected); 
      Console.WriteLine("New user: " + ipLocal); 
      // invoke the connection event 
      if (ClientConnected != null) 
       ClientConnected(clientConnection, EventArgs.Empty); 

      if (LogLevel != ServerLogLevel.Nothing) 
       clientConnection.DataReceived += new DataReceivedEventHandler(DataReceivedFromClient); 



      // listen for more clients 
      ListenForClients(); 

     } 

     void ClientDisconnected(WebSocketConnection sender, EventArgs e) 
     { 
      Connections.Remove(sender); 
      LogLine(DateTime.Now + "> " + sender.ConnectionSocket.LocalEndPoint + " disconnected", ServerLogLevel.Subtle); 
     } 

     void DataReceivedFromClient(WebSocketConnection sender, DataReceivedEventArgs e) 
     { 
      Log(DateTime.Now + "> data from " + sender.ConnectionSocket.LocalEndPoint, ServerLogLevel.Subtle); 
      Log(": " + e.Data + "\n" + e.Size + " bytes", ServerLogLevel.Verbose); 
      LogLine("", ServerLogLevel.Subtle); 
     } 


     /// <summary> 
     /// send a string to all the clients (you spammer!) 
     /// </summary> 
     /// <param name="data">the string to send</param> 
     public void SendToAll(string data) 
     { 
      Connections.ForEach(a => a.Send(data)); 
     } 

     /// <summary> 
     /// send a string to all the clients except one 
     /// </summary> 
     /// <param name="data">the string to send</param> 
     /// <param name="indifferent">the client that doesn't care</param> 
     public void SendToAllExceptOne(string data, WebSocketConnection indifferent) 
     { 
      foreach (var client in Connections) 
      { 
       if (client != indifferent) 
        client.Send(data); 
      } 
     } 

     /// <summary> 
     /// Takes care of the initial handshaking between the the client and the server 
     /// </summary> 


     private void Log(string str, ServerLogLevel level) 
     { 
      if (Logger != null && (int)LogLevel >= (int)level) 
      { 
       Logger.Write(str); 
      } 
     } 

     private void LogLine(string str, ServerLogLevel level) 
     { 
      Log(str + "\r\n", level); 
     } 

     private static string AcceptKey(ref string key) 
     { 
      string longKey = key + guid; 
      byte[] hashBytes = ComputeHash(longKey); 
      return Convert.ToBase64String(hashBytes); 
     } 
     static SHA1 sha1 = SHA1CryptoServiceProvider.Create(); 
     private static byte[] ComputeHash(string str) 
     { 
      return sha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(str)); 
     } 



     private void ShakeHands(Socket conn) 
     { 
      using (var stream = new NetworkStream(conn)) 
      using (var reader = new StreamReader(stream)) 
      using (var writer = new StreamWriter(stream)) 
      { 
       //read handshake from client (no need to actually read it, we know its there): 
       LogLine("Reading client handshake:", ServerLogLevel.Verbose); 
       string r = null; 
       while (r != "") 
       { 
        r = reader.ReadLine(); 
        LogLine(r, ServerLogLevel.Verbose); 
       } 

       // send handshake to the client 
       writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake"); 
       writer.WriteLine("Upgrade: WebSocket"); 
       writer.WriteLine("Connection: Upgrade"); 
       writer.WriteLine("WebSocket-Origin: " + webSocketOrigin); 
       writer.WriteLine("WebSocket-Location: " + webSocketLocation); 
       writer.WriteLine(""); 
      } 


      // tell the nerds whats going on 
      LogLine("Sending handshake:", ServerLogLevel.Verbose); 
      LogLine("HTTP/1.1 101 Web Socket Protocol Handshake", ServerLogLevel.Verbose); 
      LogLine("Upgrade: WebSocket", ServerLogLevel.Verbose); 
      LogLine("Connection: Upgrade", ServerLogLevel.Verbose); 
      LogLine("WebSocket-Origin: " + webSocketOrigin, ServerLogLevel.Verbose); 
      LogLine("WebSocket-Location: " + webSocketLocation, ServerLogLevel.Verbose); 
      LogLine("", ServerLogLevel.Verbose); 

      LogLine("Started listening to client", ServerLogLevel.Verbose); 
      //conn.Listen(); 
     } 


    } 
} 

连接问题解决了,接下来将数据发送到客户端。

+0

你解决了发送数据问题吗?我下载了相同的示例,并得到了完全相同的问题> _ <我自己修复了连接问题,但它出来甚至发送了数据问题。呃,谁在这个世界上曾经用“websockets server example”来称呼这段垃圾代码? – Kosmos 2015-02-02 13:55:20

1

什么,你正在努力实现将容易得多,如果你看一看ASP.NET SignalR

它有高水平的集线器来实现实时通信的支持,也有一个永久连接低电平类有细粒度控制通信。

支持多种客户端类型,如果通信两端不支持websockets(可以选择使用长轮询或永久帧),则可以回退。

+1

但要求是使用html5和c# – Charmie 2013-03-13 07:35:19

+0

看看http://stackoverflow.com/questions/11140164/signalr-console-app-example - SignalR是ASP.Net的独立和与WebSockets一起工作。 – weismat 2013-03-13 07:50:22

+1

@weismat SignalR是asp.net的一部分..它不是独立的。检查此链接http://www.asp.net/signalr – scartag 2013-03-13 08:03:51

1

此错误的原因是(可能),因为您没有响应握手。连接建立后,浏览器发送一些数据,服务器必须做出适当的响应(否则浏览器将关闭连接)。你可以在wiki或直接在specification上阅读更多。

3

我已经为一个JavaScript/HTML 5游戏开发了大约7个月的服务器现在你有没有看过Alchemy Websockets?它非常易于使用。

例子:

using Alchemy; 
using Alchemy.Classes; 
namespace GameServer 
{ 
    static class Program 
    { 
     public static readonly ConcurrentDictionary<ClientPeer, bool> OnlineUsers = new ConcurrentDictionary<ClientPeer, bool>(); 
     static void Main(string[] args) 
     { 
      var aServer = new WebSocketServer(4530, IPAddress.Any) 
      { 
       OnReceive = context => OnReceive(context), 
       OnConnected = context => OnConnect(context), 
       OnDisconnect = context => OnDisconnect(context), 
       TimeOut = new TimeSpan(0, 10, 0), 
       FlashAccessPolicyEnabled = true 
      }; 
     } 
     private static void OnConnect(UserContext context) 
     { 
      var client = new ClientPeer(context); 
      OnlineUsers.TryAdd(client, false); 
      //Do something with the new client 
     } 
    } 
} 

正如你可以看到它很容易的工作,我觉得他们的文档非常好(注意ClientPeer是一个自定义类矿井只是用它作为一个例子)。

0

只需在下面的代码解决方案中更改WebSocketServer.cs文件中的shakehands,您的错误将消失..

private void ShakeHands(Socket conn) 
    { 
     using (var stream = new NetworkStream(conn)) 
     using (var reader = new StreamReader(stream)) 
     using (var writer = new StreamWriter(stream)) 
     { 
      //read handshake from client (no need to actually read it, we know its there): 
      LogLine("Reading client handshake:", ServerLogLevel.Verbose); 
      string r = null; 
      Dictionary<string, string> headers = new Dictionary<string, string>(); 
      while (r != "") 
      { 
       r = reader.ReadLine(); 
       string[] tokens = r.Split(new char[] { ':' }, 2); 
       if (!string.IsNullOrWhiteSpace(r) && tokens.Length > 1) 
       { 
        headers[tokens[0]] = tokens[1].Trim(); 
       } 
       LogLine(r, ServerLogLevel.Verbose); 
      } 


      //string line = string.Empty; 
      //while ((line = reader.ReadLine()) != string.Empty) 
      //{ 
      // string[] tokens = line.Split(new char[] { ':' }, 2); 
      // if (!string.IsNullOrWhiteSpace(line) && tokens.Length > 1) 
      // { 
      //  headers[tokens[0]] = tokens[1].Trim(); 
      // } 
      //} 

      string responseKey = ""; 
      string key = string.Concat(headers["Sec-WebSocket-Key"], "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); 
      using (SHA1 sha1 = SHA1.Create()) 
      { 
       byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(key)); 
       responseKey = Convert.ToBase64String(hash); 
      } 



      // send handshake to the client 
      writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake"); 
      writer.WriteLine("Upgrade: WebSocket"); 
      writer.WriteLine("Connection: Upgrade"); 
      writer.WriteLine("WebSocket-Origin: " + webSocketOrigin); 
      writer.WriteLine("WebSocket-Location: " + webSocketLocation); 
      //writer.WriteLine("Sec-WebSocket-Protocol: chat"); 
      writer.WriteLine("Sec-WebSocket-Accept: " + responseKey); 
      writer.WriteLine(""); 
     } 


     // tell the nerds whats going on 
     LogLine("Sending handshake:", ServerLogLevel.Verbose); 
     LogLine("HTTP/1.1 101 Web Socket Protocol Handshake", ServerLogLevel.Verbose); 
     LogLine("Upgrade: WebSocket", ServerLogLevel.Verbose); 
     LogLine("Connection: Upgrade", ServerLogLevel.Verbose); 
     LogLine("WebSocket-Origin: " + webSocketOrigin, ServerLogLevel.Verbose); 
     LogLine("WebSocket-Location: " + webSocketLocation, ServerLogLevel.Verbose); 
     LogLine("", ServerLogLevel.Verbose); 

     LogLine("Started listening to client", ServerLogLevel.Verbose); 
     //conn.Listen(); 
    } 
0

您也可以看看的WebSocketRPC库,它应该是非常简单易用,对于“原始”的连接和RPC连接(该消息也可以混)。


下可能是有用的你:
负责发送/接收原始消息位于Connection class的代码。 在存储库中,您还可以找到如何实现base JavaScript client

声明:我是作者。