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

\#番外篇 即時聊天室 Web Socket

MVC 範本

作法

Controller View 需要Log才需要Model

不用Home做增加新的API控制器空的不用範本

Using System.Web

安裝插件並Using

Nuget裝Microsoft WebSockets

![](/files/-Lh0-V-WW2r4X8AyomJM)

原理

Ip + Port 綁再一起就是 sockets

在傳輸層自訂傳輸方式

不同語言有不同物件C++ WinSock

Clint -> Reguest -> Server -> Response -> Clint

第七層 Http 逃脫不出這種框架會有限制

更新必須要按重新整理，你一年十年不按伺服器更新你畫面也不會有更動

客戶端要允許Sockets讓伺服器推送資料給客戶端

在一樣在Http方式下利用WebSockets通知

首先利用 HttpResponseMessage物件

在途中把http封包拿走

再來利用HttpContext物件承接

Current AcceptWebSocketRequest ( 當前 接受 web插座回應

Handler處理器

![](/files/-Lh0-aBS9g2_rMARizh2)

待補

Return Request 要求 CreateResponse(HttpStatusCode.SwitchingProtocols);

HTTP狀態碼。交換協議

![](/files/-Lh0-gFaZL5mSyb43RNZ)

接著新增一個 class 用於編寫自己的 WebSocket 的方法

但記得要繼承  class ChatWebSocketHandler:WebSocketHandler

首先

new一個字串存聊天的人的姓名

WebSocketCollection 採集

一定要有個東西觸發 打開 websockets

複寫OnOpen

複寫 OnMessage

選API目的是為了這個config

![](/files/-Lh0-m_7B7OLaI4qWUUO)

裡面有寫API的預設網址要到這裡查

@RenderSection("scripts", required: false)

接著編寫View

寫JQ配合按鈕觸發傳送值

還沒講Layout 但這邊先提一下

配合@RenderSection("scripts", required: false)

就能寫獨立頁面的 script 並寫放在正確的位置 不然會亂掉

![](/files/-Lh0-rl7ayux0_QkiLMs)

@section scripts { }

接著要使用JS的物件WebSocket把url傳給他

發生錯誤不會有任何訊息，所以為了好偵錯 onerror

接著寫 DOM增加訊息元素li到ul裡面

Log到console.log();會比較好偵錯

結果Var ws = new WebSocket(url);

hand shack錯誤 ? 丟到網路前就錯誤

再開個新的專案 剛剛的少了一些東西

必須把Web API打勾

![](/files/-Lh0-wrEvenJ2zyyDLhf)

什麼都沒改 就都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&#xD;

```
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>

```

## #就業前準備與技巧

![](/files/-Lh00Sh2nqs3cVmzt1RD)

![](/files/-Lh00UNFD5vSUICOaJ_T)

![](/files/-Lh00W2vDQ1NRD2LdjLs)

### PDCA(Plan-Do-Check-Act)循環式品質管理循環

![](/files/-Lh00_BKXih5TzNDPepe)

![](/files/-Lh00awolGz2RKkAl2iD)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://johch3n611u.gitbook.io/c50108/ju-li-cheng-bei/201906/2019-0610.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
