#番外篇 即時聊天室 Web Socket
MVC 範本
作法
Controller View 需要Log才需要Model
不用Home做增加新的API控制器空的不用範本
Using System.Web
安裝插件並Using
Nuget裝Microsoft WebSockets
原理
Ip + Port 綁再一起就是 sockets
在傳輸層自訂傳輸方式
不同語言有不同物件C++ WinSock
Clint -> Reguest -> Server -> Response -> Clint
第七層 Http 逃脫不出這種框架會有限制
更新必須要按重新整理,你一年十年不按伺服器更新你畫面也不會有更動
客戶端要允許Sockets讓伺服器推送資料給客戶端
在一樣在Http方式下利用WebSockets通知
首先利用 HttpResponseMessage物件
在途中把http封包拿走
再來利用HttpContext物件承接
Current AcceptWebSocketRequest ( 當前 接受 web插座回應
Handler處理器
待補
Return Request 要求 CreateResponse(HttpStatusCode.SwitchingProtocols);
HTTP狀態碼。交換協議
接著新增一個 class 用於編寫自己的 WebSocket 的方法
但記得要繼承 class ChatWebSocketHandler:WebSocketHandler
首先
new一個字串存聊天的人的姓名
WebSocketCollection 採集
一定要有個東西觸發 打開 websockets
複寫OnOpen
複寫 OnMessage
選API目的是為了這個config
裡面有寫API的預設網址要到這裡查
@RenderSection("scripts", required: false)
接著編寫View
寫JQ配合按鈕觸發傳送值
還沒講Layout 但這邊先提一下
配合@RenderSection("scripts", required: false)
就能寫獨立頁面的 script 並寫放在正確的位置 不然會亂掉
@section scripts { }
接著要使用JS的物件WebSocket把url傳給他
發生錯誤不會有任何訊息,所以為了好偵錯 onerror
接著寫 DOM增加訊息元素li到ul裡面
Log到console.log();會比較好偵錯
結果Var ws = new WebSocket(url);
hand shack錯誤 ? 丟到網路前就錯誤
再開個新的專案 剛剛的少了一些東西
必須把Web API打勾
什麼都沒改 就都ok了
發言後伺服器會
Brocass給所有人?
配合jq dom Attribute Readonly disable display none show讓使用者體驗更好
離開聊天室 反著做 jq
接著講一下要怎樣把聊天室架起來?
IIS實體路徑找專案資料夾直接選擇即可
但是要改送sockets的Ip 改為伺服器的IP
###ftp://mvc@10.10.3.189/WebSocket2/WebSocket2/App_Start/WebApiConfig.cs
Copy using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace WebSocket2
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 設定和服務
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
###ftp://mvc@10.10.3.189/WebSocket2/WebSocket2/Controllers/ChatController.cs
Copy using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web;
using Microsoft.Web.WebSockets;
namespace WebSocket2.Controllers
{
public class ChatController : ApiController
{
public HttpResponseMessage Get(string username)
{
HttpContext.Current.AcceptWebSocketRequest(new ChatWebSocketHandler(username));
return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
}
class ChatWebSocketHandler : WebSocketHandler
{
private string _username;
private static WebSocketCollection _chatClients = new WebSocketCollection();
public ChatWebSocketHandler(string username)
{
_username = username;
}
public override void OnOpen()
{
_chatClients.Add(this);
}
public override void OnMessage(string message)
{
_chatClients.Broadcast(_username + ":" + message);
}
}
}
}
###ftp://mvc@10.10.3.189/WebSocket2/WebSocket2/Views/Home/Index.cshtml
Copy @{
ViewBag.Title = "Home Page";
}
<div class="jumbotron">
<h1>ASP.NET</h1>
<p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
<p><a href="https://asp.net" class="btn btn-primary btn-lg">Learn more »</a></p>
</div>
<div class="row">
<div class="col-md-12">
<fieldset>
<legend>聊天室</legend>
<input id="username" name="username" type="text" /><input id="btnConnect" type="button" value="進入聊天室" />
<hr />
<input id="message" name="message" type="text" readonly="readonly" /><input id="btnSend" type="button" value="發言" disabled="disabled" />
<hr />
<input id="btnClose" type="button" value="離開聊天" />
<ul id="output"></ul>
</fieldset>
</div>
</div>
@section scripts{
<script>
$('#btnConnect').click(function () {
var url = "ws://10.10.3.189/api/Chat?username=" + $('#username').val();
var ws = new WebSocket(url);
console.log(ws);
$('#message').removeAttr('readonly');
$('#btnSend').removeAttr('disabled');
$('#username').attr('readonly', 'readonly');
$('#btnConnect').attr('disabled', 'disabled');
ws.onopen = function () {
ws.send("已進入聊天!!");
}
ws.onerror = function () {
alert('有錯誤');
}
ws.onmessage = function (e) {
$('#output').append($('<li>').text(e.data));
console.log(e.data);
}
$('#btnSend').click(function () {
ws.send($('#message').val());
});
$('#btnClose').click(function () {
ws.close();
$('#username').removeAttr('readonly');
$('#btnConnect').removeAttr('disabled');
$('#message').attr('readonly', 'readonly');
$('#btnSend').attr('disabled', 'disabled');
});
});
</script>
}
###ftp://mvc@10.10.3.189/WebSocket2/WebSocket2/Views/Shared/_Layout.cshtml
Copy <!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - 我的 ASP.NET 應用程式</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("應用程式名稱", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("首頁", "Index", "Home")</li>
<li>@Html.ActionLink("關於", "About", "Home")</li>
<li>@Html.ActionLink("連絡人", "Contact", "Home")</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - 我的 ASP.NET 應用程式</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>
#就業前準備與技巧
PDCA(Plan-Do-Check-Act)循環式品質管理循環