Winform+SignalR

如果您发现自己通过对 REST 服务的反复调用且频繁地检查信息,这可能是您应该转向 WebSocket的好兆头。比如一个网站的个人信息通知栏, 通过使用 WebSocket来减少带宽使用,因为它可以帮助人们不用花时间在主页上按 F5 来查看他们是否有新消息。

如果您发现您打开了 WebSocket连接,使用它们进行单个调用,然后关闭它们,或者如果您的连接保持打开但服务器仅在客户端请求时向客户端发送某些内容,请切换到 REST。

WebStock占用了连接数,节约了带宽; REST节约了连接数, 占了带宽. 看你如何取舍

Differences between SignalR and ASP.NET Core SignalR | Microsoft Docs

Winform+SignalR

Winform+SignalR

服务器端主动发消息给客户端:

IHubContext _myHubContext = GlobalHost.ConnectionManager.GetHubContext();
 _myHubContext.Clients.Group("Group1").addMessage("系统广播",@"{ 'people': [ { 'firstName': 'Bret', 'lastName':'Mc', 'email': 'brett@new.com' }]}");

客户端

DOCTYPE html>
<html>
<head>
    <title>SignalR Simple Chattitle>
    <style type="text/css">
        .container {
            background-color: #99CCFF;
            border: thick solid #808080;
            padding: 20px;
            margin: 20px;
        }
    style>
head>
<body>
    <div class="container">
        <input type="text" id="message" />
        <input type="button" id="sendmessage" value="Send" />
        <input type="hidden" id="displayname" />
        <ul id="discussion">ul>
    div>

    <script src="Scripts/jquery-1.6.4.min.js">script>

    <script src="Scripts/jquery.signalR-2.4.3.min.js">script>

    <script src="http://localhost:9021/signalr/hubs">script>

    <script type="text/javascript">
        $(function () {
            //Set the hubs URL for the connection
            $.connection.hub.url = "http://localhost:9021/signalr";

            // Declare a proxy to reference the hub.
            var chat = $.connection.myHub;

            // Create a function that the hub can call to broadcast messages.
            chat.client.addMessage = function (name, message) {
                // Html encode display name and message.
                var encodedName = $('').text(name).html();
                var encodedMsg = $('').text(message).html();
                // Add the message to the page.
                $('#discussion').append('' + encodedName
                    + ':  ' + encodedMsg + '');
            };
            // Get the user name and store it to prepend to messages.
            $('#displayname').val(prompt('Enter your name:', ''));
            // Set initial focus to message input box.
            $('#message').focus();

            //querystring
            $.connection.hub.qs = { "version": "1.0", "company": "Microsoft", "name": $('#displayname').val() };
            // Start the connection.
            $.connection.hub.start().done(function () {
                console.log("web socket connected...")
                $('#sendmessage').click(function () {

                    console.log("Call the Send method on the hub.")
                    // Call the Send method on the hub.
                    chat.server.send($('#displayname').val(), $('#message').val());
                    // Clear text box and reset focus for next comment.
                    $('#message').val('').focus();
                });
            });
        });
    script>
body>
html>

服务器端

using Microsoft.AspNet.SignalR;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace KD.LCSM
{

    ///
    /// 这个就是整个SignalR的核心了,它主要有几个函数需要重写,
    /// 如OnConnected、OnDisconnected、OnReconnected、以及一个通用的消息发送AddMessage函数。
    ///
    ///
    //Hub的别名,方便前台调用, 没有指定时 ,JavaScript 客户端采用camel 形式 MyHub=>myHub
    //[HubName("MyHub")] 使用 HubName 属性时,JavaScript 客户端上不会更改为 camel 大小写的名称。
    public class MyHub : Hub
    {
        ///
        /// 编写发送信息的方法
        ///
        ///
        ///
        public void Send(string name, string message)  //首页的方法
        {
            GlobalVariable.MainForm.WriteToConsole(string.Format("客户端 【{0}】发送:{1}", name, message));
            //调用所有客户注册的本地的JS方法(addMessage)
            Clients.All.addMessage(name, message); //转发到所有客户端,类似公开聊天室
            //Clients.Group("首页组").addMessage(name, message);

        }
        public void RemoveFromGroup(string name, string message)  //从首页组移除
        {
        }
        public void ShowStratorInfo(string name, string message)  //显示定子数据
        {
        }
        ///
        /// 在连接上时
        ///
        ///
        public override Task OnConnected()
        {
            var IP = Context.Request.Environment["server.RemoteIpAddress"];
            var name = Context.QueryString.Get("name");
            var version = Context.QueryString.Get("version");
            var Company = Context.QueryString.Get("Company");

            //var client = JsonConvert.DeserializeObject(Context.QueryString.Get("Param"));
            //if (client != null)
            {
                //client.ConnId = Context.ConnectionId;
                //将客户端连接加入界面列表, 并对客户进行分组
                GlobalVariable.MainForm.AddClient(Context.ConnectionId,name);

                this.Groups.Add(Context.ConnectionId, "Client");

                //向服务端写入一些数据

                GlobalVariable.MainForm.WriteToConsole(string.Format("客户端 【{0}】接入:{1} ,IP地址:{2}客户端总数:{3}",
                    name, Context.ConnectionId, IP, GlobalVariable.MainForm.ClientCount));

                return base.OnConnected();

            }
        }
        public override Task OnDisconnected(bool stopCalled)
        {
            Groups.Remove(Context.ConnectionId, "Client");
            GlobalVariable.MainForm.RemoveClient(Context.ConnectionId);
            GlobalVariable.MainForm.WriteToConsole(string.Format("客户端断开:{0}客户端总数:{1}",
            Context.ConnectionId, GlobalVariable.MainForm.ClientCount));
            return base.OnDisconnected(stopCalled);
        }
    }
}

SignalR 默认只能在Localhost, 外网访问 考虑用nginx来端口转发,把signalr路径开头的都转到localhost

, client========> server(192.168.0.X) ====> signalR(localhost:9021)

http://localhost:9021/signalr/negotiate?clientProtocol=2.1&version=1.0&company=Keding&name=apple&connectionData=[{"name":"myhub"}]&_=1647332664509

ws://localhost:9021/signalr/connect?transport=webSockets&clientProtocol=2.1&version=1.0&company=ms&name=apple&connectionToken=AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAsh3lDa2xnkSO5gf0fNXg9QAAAAACAAAAAAAQZgAAAAEAACAAAAAk+DIeew21HpF4AAab6oqj4Yb1NUUU0SDc6ZlBDoDKwgAAAAAOgAAAAAIAACAAAACGq+iSbpCACodCipNe8Cy/Y8PNHQFLYGH3btG2wsOAuzAAAAAujl4u+sTrCKQ5Z4g2XILvvm6o9nQrBfSX10akqA4HGQtmGiHJOpK9+XkECBdQBsJAAAAAzCxM9dY3PYM0e63JVjLvs+03E/WLKY5yYq9VFT12wQm4YVhVZ/5mnxihCLv2PeOpEPaXYtPG5CjJfU5H5wof+Q==&connectionData=[{"name":"myhub"}]&tid=5

http://localhost:9021/signalr/start?transport=webSockets&clientProtocol=2.1&version=1.0&company=ms&name=apple&connectionToken=AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAsh3lDa2xnkSO5gf0fNXg9QAAAAACAAAAAAAQZgAAAAEAACAAAAAk+DIeew21HpF4AAab6oqj4Yb1NUUU0SDc6ZlBDoDKwgAAAAAOgAAAAAIAACAAAACGq+iSbpCACodCipNe8Cy/Y8PNHQFLYGH3btG2wsOAuzAAAAAujl4u+sTrCKQ5Z4g2XILvvm6o9nQrBfSX10akqA4HGQtmGiHJOpK9+XkECBdQBsJAAAAAzCxM9dY3PYM0e63JVjLvs+03E/WLKY5yYq9VFT12wQm4YVhVZ/5mnxihCLv2PeOpEPaXYtPG5CjJfU5H5wof+Q==&connectionData=[{"name":"myhub"}]&_=1647332664551

nginx的conf文件

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    map $http_upgrade $connection_upgrade {
        default          keep-alive;  #默认为keep-alive 可以支持 一般http请求
        'websocket'      upgrade;     #如果为websocket 则为 upgrade 可升级的。
       }

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;

        }

    location ~ /signalr/ {
        proxy_pass   http://localhost:9021;
        #启用http长连接支持websocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

    }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }

    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

SignalR WebSocket localhost测试,第一次连接时间要一秒,重新刷新也要500ms

我用Microsoft.AspNet.SignalR.Core在winform里建立WebSocket服务器,

现在有个问题,我启动服务器, 客户端可以连接上, 但是我点停止服务器再点重新启动, 客户端就连不上了.

一定要退出exe,重新打开才能连上.

启动服务器用的是 ServerUri = “http://localhost”; SignalR = WebApp.Start(ServerUri); // 启动SignalR服务,

停止服务器用的 SignalR.Dispose();
SignalR = null;

Original: https://www.cnblogs.com/zitjubiz/p/winform_signalR.html
Author: Gu
Title: Winform+SignalR

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/564930/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球