2019/0610/番外篇 Web Socket 即時連線& 就業前準備與技巧

#番外篇 即時聊天室 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

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

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

@{
    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 &raquo;</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

<!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>&copy; @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)循環式品質管理循環

Last updated