HTML5学习之WebSocket通讯(六)
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Net.Sockets;
- using System.Security.Cryptography;
- using System.Text;
- using System.Threading.Tasks;
- namespace WebSocketServer
- {
- class Program
- {
- static void Main(string[] args)
- {
- WebSocketServerTest WSServerTest = new WebSocketServerTest();
- WSServerTest.Start();
- }
- }
- public class WebSocketServerTest : IDisposable
- {
- private WebSocketServer WSServer;
- public WebSocketServerTest()
- {
- //使用默认的设置
- WSServer = new WebSocketServer();
- }
- public void Dispose()
- {
- Close();
- }
- private void Close()
- {
- WSServer.Dispose();
- GC.SuppressFinalize(this);
- }
- ~WebSocketServerTest()
- {
- Close();
- }
- public void Start()
- {
- WSServer.NewConnection += new NewConnectionEventHandler(WSServer_NewConnection);
- WSServer.Disconnected += new DisconnectedEventHandler(WSServer_Disconnected);
- WSServer.StartServer();
- }
- void WSServer_Disconnected(Object sender, EventArgs e)
- {
- }
- void WSServer_NewConnection(string loginName, EventArgs e)
- {
- }
- }
- public class Logger
- {
- public bool LogEvents { get; set; }
- public Logger()
- {
- LogEvents = true;
- }
- public void Log(string Text)
- {
- if (LogEvents) Console.WriteLine(Text);
- }
- }
- public enum ServerStatusLevel { Off, WaitingConnection, ConnectionEstablished };
- public delegate void NewConnectionEventHandler(string loginName, EventArgs e);
- public delegate void DataReceivedEventHandler(Object sender, string message, EventArgs e);
- public delegate void DisconnectedEventHandler(Object sender, EventArgs e);
- public delegate void BroadcastEventHandler(string message, EventArgs e);
- public class WebSocketServer : IDisposable
- {
- private bool AlreadyDisposed;
- private Socket Listener;
- private int ConnectionsQueueLength;
- private int MaxBufferSize;
- private string Handshake;
- private StreamReader ConnectionReader;
- private StreamWriter ConnectionWriter;
- private Logger logger;
- private byte[] FirstByte;
- private byte[] LastByte;
- private byte[] ServerKey1;
- private byte[] ServerKey2;
- List<SocketConnection> connectionSocketList = new List<SocketConnection>();
- public ServerStatusLevel Status { get; private set; }
- public int ServerPort { get; set; }
- public string ServerLocation { get; set; }
- public string ConnectionOrigin { get; set; }
- public bool LogEvents
- {
- get { return logger.LogEvents; }
- set { logger.LogEvents = value; }
- }
- public event NewConnectionEventHandler NewConnection;
- public event DataReceivedEventHandler DataReceived;
- public event DisconnectedEventHandler Disconnected;
- private void Initialize()
- {
- AlreadyDisposed = false;
- logger = new Logger();
- Status = ServerStatusLevel.Off;
- ConnectionsQueueLength = ;
- MaxBufferSize = * ;
- FirstByte = new byte[MaxBufferSize];
- LastByte = new byte[MaxBufferSize];
- FirstByte[] = 0x00;
- LastByte[] = 0xFF;
- logger.LogEvents = true;
- }
- public WebSocketServer()
- {
- ServerPort = ;
- ServerLocation = string.Format("ws://{0}:4141/chat", getLocalmachineIPAddress());
- Initialize();
- }
- public WebSocketServer(int serverPort, string serverLocation, string connectionOrigin)
- {
- ServerPort = serverPort;
- ConnectionOrigin = connectionOrigin;
- ServerLocation = serverLocation;
- Initialize();
- }
- ~WebSocketServer()
- {
- Close();
- }
- public void Dispose()
- {
- Close();
- }
- private void Close()
- {
- if (!AlreadyDisposed)
- {
- AlreadyDisposed = true;
- if (Listener != null) Listener.Close();
- foreach (SocketConnection item in connectionSocketList)
- {
- item.ConnectionSocket.Close();
- }
- connectionSocketList.Clear();
- GC.SuppressFinalize(this);
- }
- }
- public static IPAddress getLocalmachineIPAddress()
- {
- string strHostName = Dns.GetHostName();
- IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
- foreach (IPAddress ip in ipEntry.AddressList)
- {
- //IPV4
- if (ip.AddressFamily == AddressFamily.InterNetwork)
- return ip;
- }
- return ipEntry.AddressList[];
- }
- public void StartServer()
- {
- Char char1 = Convert.ToChar();
- Listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
- Listener.Bind(new IPEndPoint(getLocalmachineIPAddress(), ServerPort));
- Listener.Listen(ConnectionsQueueLength);
- logger.Log(string.Format("聊天服务器启动。监听地址:{0}, 端口:{1}", getLocalmachineIPAddress(), ServerPort));
- logger.Log(string.Format("WebSocket服务器地址: ws://{0}:{1}/chat", getLocalmachineIPAddress(), ServerPort));
- while (true)
- {
- Socket sc = Listener.Accept();
- if (sc != null)
- {
- System.Threading.Thread.Sleep();
- SocketConnection socketConn = new SocketConnection();
- socketConn.ConnectionSocket = sc;
- socketConn.NewConnection += new NewConnectionEventHandler(socketConn_NewConnection);
- socketConn.DataReceived += new DataReceivedEventHandler(socketConn_BroadcastMessage);
- socketConn.Disconnected += new DisconnectedEventHandler(socketConn_Disconnected);
- socketConn.ConnectionSocket.BeginReceive(socketConn.receivedDataBuffer,
- , socketConn.receivedDataBuffer.Length,
- , new AsyncCallback(socketConn.ManageHandshake),
- socketConn.ConnectionSocket.Available);
- connectionSocketList.Add(socketConn);
- }
- }
- }
- void socketConn_Disconnected(Object sender, EventArgs e)
- {
- SocketConnection sConn = sender as SocketConnection;
- if (sConn != null)
- {
- Send(string.Format("【{0}】离开了聊天室!", sConn.Name));
- sConn.ConnectionSocket.Close();
- connectionSocketList.Remove(sConn);
- }
- }
- void socketConn_BroadcastMessage(Object sender, string message, EventArgs e)
- {
- if (message.IndexOf("login:") != -)
- {
- SocketConnection sConn = sender as SocketConnection;
- sConn.Name = message.Substring(message.IndexOf("login:") + "login:".Length);
- message = string.Format("欢迎【{0}】来到聊天室!", message.Substring(message.IndexOf("login:") + "login:".Length));
- }
- Send(message);
- }
- void socketConn_NewConnection(string name, EventArgs e)
- {
- if (NewConnection != null)
- NewConnection(name, EventArgs.Empty);
- }
- public void Send(string message)
- {
- foreach (SocketConnection item in connectionSocketList)
- {
- if (!item.ConnectionSocket.Connected) return;
- try
- {
- if (item.IsDataMasked)
- {
- DataFrame dr = new DataFrame(message);
- item.ConnectionSocket.Send(dr.GetBytes());
- }
- else
- {
- item.ConnectionSocket.Send(FirstByte);
- item.ConnectionSocket.Send(Encoding.UTF8.GetBytes(message));
- item.ConnectionSocket.Send(LastByte);
- }
- }
- catch (Exception ex)
- {
- logger.Log(ex.Message);
- }
- }
- }
- }
- public class SocketConnection
- {
- private Logger logger;
- private string name;
- public string Name
- {
- get { return name; }
- set { name = value; }
- }
- private Boolean isDataMasked;
- public Boolean IsDataMasked
- {
- get { return isDataMasked; }
- set { isDataMasked = value; }
- }
- public Socket ConnectionSocket;
- private int MaxBufferSize;
- private string Handshake;
- private string New_Handshake;
- public byte[] receivedDataBuffer;
- private byte[] FirstByte;
- private byte[] LastByte;
- private byte[] ServerKey1;
- private byte[] ServerKey2;
- public event NewConnectionEventHandler NewConnection;
- public event DataReceivedEventHandler DataReceived;
- public event DisconnectedEventHandler Disconnected;
- public SocketConnection()
- {
- logger = new Logger();
- MaxBufferSize = * ;
- receivedDataBuffer = new byte[MaxBufferSize];
- FirstByte = new byte[MaxBufferSize];
- LastByte = new byte[MaxBufferSize];
- FirstByte[] = 0x00;
- LastByte[] = 0xFF;
- Handshake = "HTTP/1.1 101 Web Socket Protocol Handshake" + Environment.NewLine;
- Handshake += "Upgrade: WebSocket" + Environment.NewLine;
- Handshake += "Connection: Upgrade" + Environment.NewLine;
- Handshake += "Sec-WebSocket-Origin: " + "{0}" + Environment.NewLine;
- Handshake += string.Format("Sec-WebSocket-Location: " + "ws://{0}:4141/chat" + Environment.NewLine, WebSocketServer.getLocalmachineIPAddress());
- Handshake += Environment.NewLine;
- New_Handshake = "HTTP/1.1 101 Switching Protocols" + Environment.NewLine;
- New_Handshake += "Upgrade: WebSocket" + Environment.NewLine;
- New_Handshake += "Connection: Upgrade" + Environment.NewLine;
- New_Handshake += "Sec-WebSocket-Accept: {0}" + Environment.NewLine;
- New_Handshake += Environment.NewLine;
- }
- private void Read(IAsyncResult status)
- {
- if (!ConnectionSocket.Connected) return;
- string messageReceived = string.Empty;
- DataFrame dr = new DataFrame(receivedDataBuffer);
- try
- {
- if (!this.isDataMasked)
- {
- // Web Socket protocol: messages are sent with 0x00 and 0xFF as padding bytes
- System.Text.UTF8Encoding decoder = new System.Text.UTF8Encoding();
- int startIndex = ;
- int endIndex = ;
- // Search for the start byte
- while (receivedDataBuffer[startIndex] == FirstByte[]) startIndex++;
- // Search for the end byte
- endIndex = startIndex + ;
- while (receivedDataBuffer[endIndex] != LastByte[] && endIndex != MaxBufferSize - ) endIndex++;
- if (endIndex == MaxBufferSize - ) endIndex = MaxBufferSize;
- // Get the message
- messageReceived = decoder.GetString(receivedDataBuffer, startIndex, endIndex - startIndex);
- }
- else
- {
- messageReceived = dr.Text;
- }
- if ((messageReceived.Length == MaxBufferSize && messageReceived[] == Convert.ToChar()) ||
- messageReceived.Length == )
- {
- logger.Log("接受到的信息 [\"" + string.Format("logout:{0}", this.name) + "\"]");
- if (Disconnected != null)
- Disconnected(this, EventArgs.Empty);
- }
- else
- {
- if (DataReceived != null)
- {
- logger.Log("接受到的信息 [\"" + messageReceived + "\"]");
- DataReceived(this, messageReceived, EventArgs.Empty);
- }
- Array.Clear(receivedDataBuffer, , receivedDataBuffer.Length);
- ConnectionSocket.BeginReceive(receivedDataBuffer, , receivedDataBuffer.Length, , new AsyncCallback(Read), null);
- }
- }
- catch (Exception ex)
- {
- logger.Log(ex.Message);
- logger.Log("Socket连接将会被终止。");
- if (Disconnected != null)
- Disconnected(this, EventArgs.Empty);
- }
- }
- private void BuildServerPartialKey(int keyNum, string clientKey)
- {
- string partialServerKey = "";
- byte[] currentKey;
- int spacesNum = ;
- char[] keyChars = clientKey.ToCharArray();
- foreach (char currentChar in keyChars)
- {
- if (char.IsDigit(currentChar)) partialServerKey += currentChar;
- if (char.IsWhiteSpace(currentChar)) spacesNum++;
- }
- try
- {
- currentKey = BitConverter.GetBytes((int)(Int64.Parse(partialServerKey) / spacesNum));
- if (BitConverter.IsLittleEndian) Array.Reverse(currentKey);
- if (keyNum == ) ServerKey1 = currentKey;
- else ServerKey2 = currentKey;
- }
- catch
- {
- if (ServerKey1 != null) Array.Clear(ServerKey1, , ServerKey1.Length);
- if (ServerKey2 != null) Array.Clear(ServerKey2, , ServerKey2.Length);
- }
- }
- private byte[] BuildServerFullKey(byte[] last8Bytes)
- {
- byte[] concatenatedKeys = new byte[];
- Array.Copy(ServerKey1, , concatenatedKeys, , );
- Array.Copy(ServerKey2, , concatenatedKeys, , );
- Array.Copy(last8Bytes, , concatenatedKeys, , );
- // MD5 Hash
- System.Security.Cryptography.MD5 MD5Service = System.Security.Cryptography.MD5.Create();
- return MD5Service.ComputeHash(concatenatedKeys);
- }
- public void ManageHandshake(IAsyncResult status)
- {
- string header = "Sec-WebSocket-Version:";
- int HandshakeLength = (int)status.AsyncState;
- byte[] last8Bytes = new byte[];
- System.Text.UTF8Encoding decoder = new System.Text.UTF8Encoding();
- String rawClientHandshake = decoder.GetString(receivedDataBuffer, , HandshakeLength);
- Array.Copy(receivedDataBuffer, HandshakeLength - , last8Bytes, , );
- //现在使用的是比较新的Websocket协议
- if (rawClientHandshake.IndexOf(header) != -)
- {
- this.isDataMasked = true;
- string[] rawClientHandshakeLines = rawClientHandshake.Split(new string[] { Environment.NewLine }, System.StringSplitOptions.RemoveEmptyEntries);
- string acceptKey = "";
- foreach (string Line in rawClientHandshakeLines)
- {
- Console.WriteLine(Line);
- if (Line.Contains("Sec-WebSocket-Key:"))
- {
- acceptKey = ComputeWebSocketHandshakeSecurityHash09(Line.Substring(Line.IndexOf(":") + ));
- }
- }
- New_Handshake = string.Format(New_Handshake, acceptKey);
- byte[] newHandshakeText = Encoding.UTF8.GetBytes(New_Handshake);
- ConnectionSocket.BeginSend(newHandshakeText, , newHandshakeText.Length, , HandshakeFinished, null);
- return;
- }
- string ClientHandshake = decoder.GetString(receivedDataBuffer, , HandshakeLength - );
- string[] ClientHandshakeLines = ClientHandshake.Split(new string[] { Environment.NewLine }, System.StringSplitOptions.RemoveEmptyEntries);
- logger.Log("新的连接请求来自" + ConnectionSocket.LocalEndPoint + "。正在准备连接 ...");
- // Welcome the new client
- foreach (string Line in ClientHandshakeLines)
- {
- logger.Log(Line);
- if (Line.Contains("Sec-WebSocket-Key1:"))
- BuildServerPartialKey(, Line.Substring(Line.IndexOf(":") + ));
- if (Line.Contains("Sec-WebSocket-Key2:"))
- BuildServerPartialKey(, Line.Substring(Line.IndexOf(":") + ));
- if (Line.Contains("Origin:"))
- try
- {
- Handshake = string.Format(Handshake, Line.Substring(Line.IndexOf(":") + ));
- }
- catch
- {
- Handshake = string.Format(Handshake, "null");
- }
- }
- // Build the response for the client
- byte[] HandshakeText = Encoding.UTF8.GetBytes(Handshake);
- byte[] serverHandshakeResponse = new byte[HandshakeText.Length + ];
- byte[] serverKey = BuildServerFullKey(last8Bytes);
- Array.Copy(HandshakeText, serverHandshakeResponse, HandshakeText.Length);
- Array.Copy(serverKey, , serverHandshakeResponse, HandshakeText.Length, );
- logger.Log("发送握手信息 ...");
- ConnectionSocket.BeginSend(serverHandshakeResponse, , HandshakeText.Length + , , HandshakeFinished, null);
- logger.Log(Handshake);
- }
- public static String ComputeWebSocketHandshakeSecurityHash09(String secWebSocketKey)
- {
- const String MagicKEY = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
- String secWebSocketAccept = String.Empty;
- // 1. Combine the request Sec-WebSocket-Key with magic key.
- String ret = secWebSocketKey + MagicKEY;
- // 2. Compute the SHA1 hash
- SHA1 sha = new SHA1CryptoServiceProvider();
- byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret));
- // 3. Base64 encode the hash
- secWebSocketAccept = Convert.ToBase64String(sha1Hash);
- return secWebSocketAccept;
- }
- private void HandshakeFinished(IAsyncResult status)
- {
- ConnectionSocket.EndSend(status);
- ConnectionSocket.BeginReceive(receivedDataBuffer, , receivedDataBuffer.Length, , new AsyncCallback(Read), null);
- if (NewConnection != null) NewConnection("", EventArgs.Empty);
- }
- }
- public class DataFrame
- {
- DataFrameHeader _header;
- private byte[] _extend = new byte[];
- private byte[] _mask = new byte[];
- private byte[] _content = new byte[];
- public DataFrame(byte[] buffer)
- {
- //帧头
- _header = new DataFrameHeader(buffer);
- //扩展长度
- if (_header.Length == )
- {
- _extend = new byte[];
- Buffer.BlockCopy(buffer, , _extend, , );
- }
- else if (_header.Length == )
- {
- _extend = new byte[];
- Buffer.BlockCopy(buffer, , _extend, , );
- }
- //是否有掩码
- if (_header.HasMask)
- {
- _mask = new byte[];
- Buffer.BlockCopy(buffer, _extend.Length + , _mask, , );
- }
- //消息体
- if (_extend.Length == )
- {
- _content = new byte[_header.Length];
- Buffer.BlockCopy(buffer, _extend.Length + _mask.Length + , _content, , _content.Length);
- }
- else if (_extend.Length == )
- {
- int contentLength = (int)_extend[] * + (int)_extend[];
- _content = new byte[contentLength];
- Buffer.BlockCopy(buffer, _extend.Length + _mask.Length + , _content, , contentLength > * ? * : contentLength);
- }
- else
- {
- long len = ;
- int n = ;
- for (int i = ; i >= ; i--)
- {
- len += (int)_extend[i] * n;
- n *= ;
- }
- _content = new byte[len];
- Buffer.BlockCopy(buffer, _extend.Length + _mask.Length + , _content, , _content.Length);
- }
- if (_header.HasMask) _content = Mask(_content, _mask);
- }
- public DataFrame(string content)
- {
- _content = Encoding.UTF8.GetBytes(content);
- int length = _content.Length;
- if (length < )
- {
- _extend = new byte[];
- _header = new DataFrameHeader(true, false, false, false, , false, length);
- }
- else if (length < )
- {
- _extend = new byte[];
- _header = new DataFrameHeader(true, false, false, false, , false, );
- _extend[] = (byte)(length / );
- _extend[] = (byte)(length % );
- }
- else
- {
- _extend = new byte[];
- _header = new DataFrameHeader(true, false, false, false, , false, );
- int left = length;
- int unit = ;
- for (int i = ; i > ; i--)
- {
- _extend[i] = (byte)(left % unit);
- left = left / unit;
- if (left == )
- break;
- }
- }
- }
- public byte[] GetBytes()
- {
- byte[] buffer = new byte[ + _extend.Length + _mask.Length + _content.Length];
- Buffer.BlockCopy(_header.GetBytes(), , buffer, , );
- Buffer.BlockCopy(_extend, , buffer, , _extend.Length);
- Buffer.BlockCopy(_mask, , buffer, + _extend.Length, _mask.Length);
- Buffer.BlockCopy(_content, , buffer, + _extend.Length + _mask.Length, _content.Length);
- return buffer;
- }
- public string Text
- {
- get
- {
- if (_header.OpCode != )
- return string.Empty;
- return Encoding.UTF8.GetString(_content);
- }
- }
- private byte[] Mask(byte[] data, byte[] mask)
- {
- for (var i = ; i < data.Length; i++)
- {
- data[i] = (byte)(data[i] ^ mask[i % ]);
- }
- return data;
- }
- }
- public class DataFrameHeader
- {
- private bool _fin;
- private bool _rsv1;
- private bool _rsv2;
- private bool _rsv3;
- private sbyte _opcode;
- private bool _maskcode;
- private sbyte _payloadlength;
- public bool FIN { get { return _fin; } }
- public bool RSV1 { get { return _rsv1; } }
- public bool RSV2 { get { return _rsv2; } }
- public bool RSV3 { get { return _rsv3; } }
- public sbyte OpCode { get { return _opcode; } }
- public bool HasMask { get { return _maskcode; } }
- public sbyte Length { get { return _payloadlength; } }
- public DataFrameHeader(byte[] buffer)
- {
- if (buffer.Length < )
- throw new Exception("无效的数据头.");
- //第一个字节
- _fin = (buffer[] & 0x80) == 0x80;
- _rsv1 = (buffer[] & 0x40) == 0x40;
- _rsv2 = (buffer[] & 0x20) == 0x20;
- _rsv3 = (buffer[] & 0x10) == 0x10;
- _opcode = (sbyte)(buffer[] & 0x0f);
- //第二个字节
- _maskcode = (buffer[] & 0x80) == 0x80;
- _payloadlength = (sbyte)(buffer[] & 0x7f);
- }
- //发送封装数据
- public DataFrameHeader(bool fin, bool rsv1, bool rsv2, bool rsv3, sbyte opcode, bool hasmask, int length)
- {
- _fin = fin;
- _rsv1 = rsv1;
- _rsv2 = rsv2;
- _rsv3 = rsv3;
- _opcode = opcode;
- //第二个字节
- _maskcode = hasmask;
- _payloadlength = (sbyte)length;
- }
- //返回帧头字节
- public byte[] GetBytes()
- {
- byte[] buffer = new byte[] { , };
- if (_fin) buffer[] ^= 0x80;
- if (_rsv1) buffer[] ^= 0x40;
- if (_rsv2) buffer[] ^= 0x20;
- if (_rsv3) buffer[] ^= 0x10;
- buffer[] ^= (byte)_opcode;
- if (_maskcode) buffer[] ^= 0x80;
- buffer[] ^= (byte)_payloadlength;
- return buffer;
- }
- }
- }
WebSocket客户端:
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html;charset=gb2312">
- <title>Web sockets test</title>
- <style type="text/css">
- .container { font-family: "Courier New"; width: 680px; height: 300px; overflow: auto; border: 1px solid black; }
- .LockOff { display: none; visibility: hidden; }
- .LockOn { display: block; visibility: visible; position: absolute; z-index: 999; top: 0px; left: 0px; width: 1024%; height: 768%; background-color: #ccc; text-align: center; padding-top: 20%; filter: alpha(opacity=75); opacity: 0.75; }
- </style>
- <script src="jquery-min.js" type="text/javascript"></script>
- <script type="text/javascript">
- var ws;
- var SocketCreated = false;
- var isUserloggedout = false;
- function lockOn(str) {
- var lock = document.getElementById('skm_LockPane');
- if (lock)
- lock.className = 'LockOn';
- lock.innerHTML = str;
- }
- function lockOff() {
- var lock = document.getElementById('skm_LockPane');
- lock.className = 'LockOff';
- }
- function ToggleConnectionClicked() {
- if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) {
- lockOn("离开聊天室...");
- SocketCreated = false;
- isUserloggedout = true;
- ws.close();
- } else {
- lockOn("进入聊天室...");
- Log("准备连接到聊天服务器 ...");
- try {
- if ("WebSocket" in window) {
- ws = new WebSocket("ws://" + document.getElementById("Connection").value);
- }
- else if ("MozWebSocket" in window) {
- ws = new MozWebSocket("ws://" + document.getElementById("Connection").value);
- }
- SocketCreated = true;
- isUserloggedout = false;
- } catch (ex) {
- Log(ex, "ERROR");
- return;
- }
- document.getElementById("ToggleConnection").innerHTML = "断开";
- ws.onopen = WSonOpen;
- ws.onmessage = WSonMessage;
- ws.onclose = WSonClose;
- ws.onerror = WSonError;
- }
- };
- function WSonOpen() {
- lockOff();
- Log("连接已经建立。", "OK");
- $("#SendDataContainer").show();
- ws.send("login:" + document.getElementById("txtName").value);
- };
- function WSonMessage(event) {
- Log(event.data);
- };
- function WSonClose() {
- lockOff();
- if (isUserloggedout)
- Log("【" + document.getElementById("txtName").value + "】离开了聊天室!");
- document.getElementById("ToggleConnection").innerHTML = "连接";
- $("#SendDataContainer").hide();
- };
- function WSonError() {
- lockOff();
- Log("远程连接中断。", "ERROR");
- };
- function SendDataClicked() {
- if (document.getElementById("DataToSend").value.trim() != "") {
- ws.send(document.getElementById("txtName").value + "说 :\"" + document.getElementById("DataToSend").value + "\"");
- document.getElementById("DataToSend").value = "";
- }
- };
- function Log(Text, MessageType) {
- if (MessageType == "OK") Text = "<span style='color: green;'>" + Text + "</span>";
- if (MessageType == "ERROR") Text = "<span style='color: red;'>" + Text + "</span>";
- document.getElementById("LogContainer").innerHTML = document.getElementById("LogContainer").innerHTML + Text + "<br />";
- var LogContainer = document.getElementById("LogContainer");
- LogContainer.scrollTop = LogContainer.scrollHeight;
- };
- $(document).ready(function () {
- $("#SendDataContainer").hide();
- var WebSocketsExist = true;
- try {
- var dummy = new WebSocket("ws://localhost:8989/test");
- } catch (ex) {
- try {
- webSocket = new MozWebSocket("ws://localhost:8989/test");
- }
- catch (ex) {
- WebSocketsExist = false;
- }
- }
- if (WebSocketsExist) {
- Log("您的浏览器支持WebSocket. 您可以尝试连接到聊天服务器!", "OK");
- document.getElementById("Connection").value = "192.168.1.108:4141/chat";
- } else {
- Log("您的浏览器不支持WebSocket。请选择其他的浏览器再尝试连接服务器。", "ERROR");
- document.getElementById("ToggleConnection").disabled = true;
- }
- $("#DataToSend").keypress(function (evt) {
- if (evt.keyCode == 13) {
- $("#SendData").click();
- evt.preventDefault();
- }
- })
- });
- </script>
- </head>
- <body>
- <div id="skm_LockPane" class="LockOff"></div>
- <form id="form1" runat="server">
- <h1>Web Socket 聊天室</h1>
- <br />
- <div>
- 按下连接按钮,会通过WebSocket发起一个到聊天浏览器的连接。
- </div>
- 服务器地址:
- <input type="text" id="Connection" />
- 用户名:
- <input type="text" id="txtName" value="黄晓安" />
- <button id='ToggleConnection' type="button" onclick='ToggleConnectionClicked();'>连接</button>
- <br />
- <br />
- <div id='LogContainer' class='container'></div>
- <br />
- <div id='SendDataContainer'>
- <input type="text" id="DataToSend" size="88" />
- <button id='SendData' type="button" onclick='SendDataClicked();'>发送</button>
- </div>
- <br />
- </form>
- </body>
- </html>
WebSocket 的局限性
WebSocket 的优点已经列举得很多了,但是作为一个正在演变中的 Web 规范,我们也要看到目前用 Websocket 构建应用程序的一些风险。首先,WebSocket 规范目前还处于草案阶段,也就是它的规范和 API 还是有变动的可能,另外的一个风险就是微软的 IE 作为占市场份额最大的浏览器,和其他的主流浏览器相比,对 HTML5 的支持是比较差的,这是我们在构建企业级的 Web 应用的时候必须要考虑的一个问题。
具体详解地址:http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/
HTML5学习之WebSocket通讯(六)的更多相关文章
- HTML5学习笔记(十六):原型、类和继承【JS核心知识点】
理解原型 在JavaScript中,只要声明了一个函数,就会为该函数创建一个名为prototype的属性,该属性指向当前函数的原型对象. 而函数的原型对象有一个constructor属性,该属性指向刚 ...
- HTML5学习总结-08 WebSocket 服务器推送
一 WebSocket 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展 ...
- HTML5 学习总结(一)——HTML5概要与新增标签
一.HTML5概要 1.1.为什么需要HTML5 HTML4陈旧不能满足日益发展的互联网需要,特别是移动互联网.为了增强浏览器功能Flash被广泛使用,但安全与稳定堪忧,不适合在移动端使用(耗电.触摸 ...
- 感谢各位亲们的大力支持,免费的HTML5学习课程《HTML5网页开发实例具体解释》连载已经结束了!
感谢各位亲们的大力支持,免费的HTML5学习课程<HTML5网页开发实例具体解释>连载已经结束了. 有兴趣的读者能够看我的博客,也能够看以下的链接逐个学习: 当里个当.免费的HTML5连 ...
- HTML5学习总结——canvas绘制象棋(canvas绘图)
一.HTML5学习总结——canvas绘制象棋 1.第一次:canvas绘制象棋(笨方法)示例代码: <!DOCTYPE html> <html> <head> & ...
- HTML5 学习笔记(一)——HTML5概要与新增标签
目录 一.HTML5概要 1.1.为什么需要HTML5 1.2.什么是HTML5 1.3.HTML5现状及浏览器支持 1.4.HTML5特性 1.5.HTML5优点与缺点 1.5.1.优点 1.5.2 ...
- [HTML5] 飞龙天惊-HTML5学习系列
飞龙天惊 cnblog URL:http://www.cnblogs.com/fly_dragon/ Html5 学习系列(一)认识HTML5 http://www.cnblogs.com/fly_d ...
- HTML5 学习笔记--------》HTML5概要与新增标签!
一.HTML5概要 1.1.为什么需要HTML5 HTML4陈旧不能满足日益发展的互联网需要,特别是移动互联网.为了增强浏览器功能Flash被广泛使用,但安全与稳定堪忧,不适合在移动端使用(耗电. ...
- 带你认识HTML5中的WebSocket
这篇文章主要介绍了带你认识HTML5中的WebSocket,本文讲解了HTML5 中的 WebSocket API 是个什么东东.HTML5 中的 WebSocket API 的用法.带Socket. ...
随机推荐
- JS判断设备的类型
利用JS判断浏览器的用户代理,从而获得设备类型.利用这个方法可以获得用户的设备是移动设备还是PC设备. JS代码如下: function browerType() { ...
- JQGrid 参数、属性API
JQGrid是一个在jquery基础上做的一个表格控件,以ajax的方式和服务器端通信. JQGrid Demo 是一个在线的演示项目.在这里,可以知道jqgrid可以做什么事情. 下面是转自其他人b ...
- Opencv,腐蚀,膨胀,轮廓检测,轮廓外接多边形
//形态学腐蚀 cvErode(pDstImage,pDstImage,,); //形态学膨胀 cvDilate(pDstImage,pDstImage,,); //中值滤波 cvSmooth(pDs ...
- static小结
1.隐藏:编译多个文件时,所有未加static的全局变量.全局函数都具有全局可见性. 如果加了static,就会对其他源文件隐藏,利用这一特性可以在不同文件中定义相同的 变量名或函数名,而不用担心冲突 ...
- mac 搭建APK反编译环境[转]
APKtool 用途:获取mainifest.xml res等资源文件 下载:http://ibotpeaches.github.io/Apktool/install/ 使用:apktool d te ...
- Android客户端的图形化拖放操作的设计实现
为什么要拖放?拖放在某些UI交互中可以简化用户操作. 拖放的步骤包括哪些?“Drag and Drop”,拖放,顾名思义,总共就分三步:1, 开始拖起来:2, 正在拖:3, 放下,进行操作:在这三步里 ...
- 项目: 推送水木文章到Kindle
代码在github:https://github.com/Viyu/PushNewsmth2Mail 当年买Kindle的时候,想再Kindle上阅读水木的帖子,但Kindle的Web上网体验太差,想 ...
- 基于用户相似性的协同过滤——Python实现
代码基本来自项亮的<推荐系统实践>,把书上的伪代码具体实现,还参考了https://www.douban.com/note/336280497/ 还可以加入对用户相似性的归一化操作,效果会 ...
- POCO浅探
POCO作用类似于POJO.POJO的内在含义是指那些从来没有任何类继承.也没有实现任何接口,更是没有被其他框架侵入的JAVA对象.POCO的含义与此是一致的.POJO的意义就在于它的简单灵活性,能够 ...
- ios NSURLSession completeHandler默认调用quque
注意 , [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSU ...