HTML5 功能:(Canvas vs GDI+)& 网页上的双工通信(Websocket vs WCF)






4.23/5 (8投票s)
HTML5 具有一些令人兴奋的功能,
背景
几个月前,我的公司举办了一场关于 HTML 5 的比赛。这让我想起了我还是学生时的 OPT 科目。我把这个想法带入比赛,以最大限度地应用 HTML 5 的特性。我在比赛中加入了两个最重要的特性
- 画布
- Websocket
应用程序中实现了三个功能
- 网页上的 P2P 通信
- 画布上的动画
- 网页上的订阅
引言
- 我编写了一个 .NET Windows 窗体应用程序作为 websocket 服务器。在 Windows 应用程序中,我实现了一个 OPT 逻辑,并通过 socket 将所有关键事件开放给外部编程。实际上,任何 socket 连接都可以从服务器获取数据。
- 我不会详细解释 OPT。基本上,问题是生产 P。
要生产 P,首先需要生产两个组件:P1 和 P2。我们可以通过销售 P 以及 P1、P2 来赚钱。P 的价格 > P1+P2 的价格。
有 3 台机器:一台红色机器,一台绿色机器,一台黄色机器,用于生产 P1、P2 和 P。
为了生产 P1,红色机器需要预热 A 分钟(我忘记了这个数字),并且生产一个 P1 需要 ** 美元。
为了生产 P2,绿色机器需要预热 B 分钟,然后在 P2 上工作 C 分钟。这是第一步。第二步是预热红色机器 D 分钟,在 P2 上工作 E 分钟。这时,红色机器将停止生产 P1(我们只有一台红色机器),然后绿色机器继续在 P2 上工作,进行第三步以完成 P2 的生产。
为了生产 P,黄色机器需要预热 F 分钟。使用一个 P1 和一个 P2,黄色机器将在 G 分钟内生产一个 P。
所有制造商都需要钱。
每周支付工资。
问题是:如何管理生产以获得最大收益。
我在窗口应用程序中放了一个我认为最好的算术计算。在您按下 GO 按钮后,应用程序将运行算术以获得最大收益。

我将 Windows 窗体上的所有效果重现在网页上。

Using the Code
WebSocket
我参考了 https://codeproject.org.cn/KB/webservices/c_sharp_web_socket_server.aspx?bcsi_scan_84C04EB1A8996739=IUdio+8K+Vb+tVCNrQ5lbwYAAABJQgES&bcsi_scan_filename=c_sharp_web_socket_server.aspx 来编写 websocket 服务器。websocket 连接最重要的部分是握手信息。当 Chrome 尝试连接一个 websocket 服务器时,它将发送一个握手信息
GET /chat HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: www.zendstudio.net:9108
Origin: http://www.zendstudio.net
Cookie: somenterCookie
当服务器获取信息时,回复
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: localhost
WebSocket-Location: ws:///chat
建立连接
- 在 P、P1 和 P3 生产过程中产生的所有关键数据都将通过 websocket 订阅。定义了 3 个结构来包含这些信息
//JSonObject has an extension method to convert the object to JSON object public class MileStoneMessage :JSonObject { #region Properties N:Total number; R: Remain number; S:Sales Number; SR: Sales Revenue; M:Material public int P_N { get; set; } public int P_R { get; set; } public int P_S { get; set; } public decimal P_SR { get; set; } public int P2_N { get; set; } public int P2_R { get; set; } public int P2_S { get; set; } public int P2_U { get; set; } public decimal P2_SR { get; set; } public int P1_N { get; set; } public int P1_R { get; set; } public int P1_S { get; set; } public int P1_U { get; set; } public decimal P1_SR { get; set; } public decimal Salary { get; set; } public decimal MCost { get; set; } public decimal M_R { get; set; } public string T_P { get; set; } #endregion } public class ClientInstruction : JSonObject { public InstructionType Type { get; set; } public int Number { get; set; } public string Sender { get; set; } public string To { get; set; } public string Notice{ get; set; } }
- Websocket 服务器也接受以下指令来控制 Windows 窗体,这意味着我们可以从网页控制 Windows 窗体。
[DataContract] public enum InstructionType { [EnumMember] Auto=0, [EnumMember] Manual=1, [EnumMember] Start=2, [EnumMember] Pause=3, [EnumMember] Stop=4, [EnumMember] Timer=5, [EnumMember] InputP1=6, [EnumMember] InputP2=7, [EnumMember] Private = 8,//private message [EnumMember] Register = 9//new user }
- 服务器发送消息
public void SendToAll(string message) { foreach (var c in Connections) { try { if (!c.Send(message)) DisposedConnections.Add(c); } catch { DisposedConnections.Add(c); } } foreach (var c in DisposedConnections) { Connections.Remove(c); } DisposedConnections.Clear(); }
- JavaScript 连接 websocket 服务器
ws = new WebSocket('ws://' + document.getElementById("server").value + ':8181/TWCompetition', 'ClientInstruction'); ws.onopen = function () { status = 1; for (var i = 0; i < onOpenEventListeners.length; i++) onOpenEventListeners[i](); } ws. önclose = function () { status = 0; for (var i = 0; i < onCloseEventListeners.length; i++) onCloseEventListeners[i](); }
- JavaScript 接收来自 websocket 的消息
ws.onmessage = function (evt) { var message = eval('(' + evt.data + ')'); switch (message.Key) { case "InitData": if (message.Trace.length > 0) RenderMoneyInitTrace( "MoneyDashboard", message.Trace, "MoneyIcon"); break; case "Users": OnlineUsers = message; DisplayUsers(); break; case "Private": var sender = message.Sender; var conversationMessage = message.Message; var name; if(conversationMessage=="black you"){ if(blackyouObj!=null) { blackyouObj.OpenBlack(); ClosePrivateWindow("PW"+sender); return; } } for (i = 0; i < OnlineUsers.Keys.length; i++) { if (OnlineUsers.Keys[i] == sender) { name = OnlineUsers.Names[i]; } } PrivateConversation(sender, name, conversationMessage) break; case "Register": Token = message.Token; SendName(document.getElementById('name').value); break; case "OneSecond": for (var i = 0; i < onSecondEventListeners.length; i++) onSecondEventListeners[i](message); break; default: for (var j = 0; j < onMilestoneEventListeners.length; j++) onMilestoneEventListeners[j](message); break; } } }
- JavaScript 发送回指令
var SendInstruction = function (type, number) { var json = JSON.stringify({ Type: type, Number: number }); ws.Send(json); }
画布
在某种程度上,JavaScript 在画布上绘制形状的语法与 GDI+ 语法非常相似。JavaScript 绘制线条
ctx.beginPath();
ctx.moveTo(14, 10);
ctx.lineTo(23, 15);
ctx.lineTo(14, 20);
ctx.closePath();
JavaScript 绘制渐变
grd = ctx.createLinearGradient(0, canvas.height-mywidth, 0, canvas.height);
grd.addColorStop(0, "gray");
grd.addColorStop(0.5, "white");
grd.addColorStop(1, "gray");
如何演示
- 在 WindowsOpt 文件夹下,双击 opt.exe。
- 看看 Windows 窗体的右上角。选择一个可用的 IP 来建立客户端连接。
- 单击 Game Control 面板上的 GO 按钮,Windows 窗体开始运行动画。
- 设置好 websocket 后,您将看到与 Windows 窗体完全相同的动画在您的网页上,您也可以控制游戏。
- 您还可以看到一个 thoughtworker 正在屏幕上运行
- P2P 通信,有点像 Google talk
- 在新标签页中以不同的名称登录 WebOPT.html。然后您将看到在线用户列表。您的名字是粉红色的,其他人的名字是绿色的。
- 单击列表中的某人,左下角会弹出一个对话框。
- 在其中写任何内容并按 Enter 键。然后您就进入了私人对话。
我在里面设计了一个有趣的东西,删除对话框中的所有文本并输入小写的“black you”。您正在与之交谈的人将看到一个黑屏,并显示一个有趣的表情,持续几秒钟。
您在网页中看到的所有彩色内容都是由 JavaScript 编写的。页面上没有链接到图片的图片。这就是我所说的 - HTML5 中的 Canvas 可以替代 GDI+。