zoukankan      html  css  js  c++  java
  • 【Win 10 应用开发】TCP通信过程

    基于TCP协议的通信,估计大伙儿都不陌生的,以前玩.net或玩C++的时候应该玩得很多吧。现在老周简单介绍一下在RT中如何用。

    TCP是基于连接的,所以,肯定有一方是监听者,通常称服务端或服务器,它负责接受连接请求,但不负责通信;接受连接后得到一个专用于通信的套接字。

    1、new一个StreamSocketListener,它用于监听TCP连接。

    2、处理StreamSocketListener实例的ConnectionReceived事件,当有新连接传入,会发生该事件,并可以获得用于通信的socket。

    3、绑定本地结点。BindEndpointAsync绑定特定本机地址和端口(或服务,如果是蓝牙通信,就是服务名,大多数情况下是端口号)。BindServiceNameAsync方法绑定本地端号或服务,该方法不指定地址,即绑定本机所有地址,如果有需要,你可以指定绑定到哪张网卡。如果所指定的端口是空白字符串("",不能为null),就会自动选择一个随机端口进行绑定。要是绑定的是本地的随机端口,你可以从StreamSocketListener.Information的LocalPort属性中获取已绑定的端口。

    4、在StreamSocketListener.ConnectionReceived事件的处理中,访问事件参数的Socket属性得到一个StreamSocket实例,然后你就可以用它来进行通信了。

    5、当不需要时调用Dispose方法即可释放。

    下面来练习一下。老周发现一个现象,UWP两个应用程序在同一台机器上不能连接,要用两台机器来测试,但在同一个应用中就可以本地测试。

    不过,后来想想,其实也无妨,毕竟UWP是通用应用,如果服务器一个应用,客户一个应用,这样反而不合理了,因为这样用户就要安装两个应用,在通用平台而言不太好,把服务器和客户端都放在同一个应用中较好,让用户自行选择是作为服务器端还是客户端来运行。如果用户选择当前应用作为服务器,就开启监听;如果用户选择作为客户端运行,就允许其输入远程设备的IP和端口进行连接。

    下面代码开启连接监听并绑定机地端口。

                if (listener != null)
                {
                    listener.ConnectionReceived -= OnConnReceived;
                    listener.Dispose();
                    listener = null;
                }
    
                listener = new StreamSocketListener();
                listener.ConnectionReceived += OnConnReceived;
                await listener.BindServiceNameAsync("");

    调用BindServiceNameAsync时传递的是空字符串的参数,表示让应用程序自动选择一个随机端口来监听。为了让客户端知道该连接哪个端口,可以把本地监听端口显示在界面上。

      runPort.Text = listener.Information.LocalPort;

    处理ConnectionReceived事件,如果接收到连接请求,就向客户端发送一条文本消息:“你好,我是你外公,我叫服务器。”。

            private async void OnConnReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
            {
                // 获取用于通信的socket
                StreamSocket socket = args.Socket;
                // 向客户端发送字符串:
                //        你好,我是你外公,我叫服务器。
                using (DataWriter writer = new DataWriter(socket.OutputStream))
                {
                    string content = "你好,我是你外公,我叫服务器。";
                    writer.UnicodeEncoding = UnicodeEncoding.Utf8; //注意
                    // 计算长度
                    uint len = writer.MeasureString(content);
                    // 写入长度
                    writer.WriteUInt32(len);
                    // 再写内容
                    writer.WriteString(content);
                    // 提交数据
                    await writer.StoreAsync();
                }
                // 这个socket不要了,扔掉
                socket.Dispose();
            }


    前一文章中,老周给大伙介绍过DataWriter的作用,这时我们用得上,用来把字符串写入网络流。注意,应该设置UnicodeEncoding属性为Utf-8编码,这个编码比较通用,就不会出现乱码。

    由于字符串的长度是可变的,客户端并不知道我们要发送的内容有多大,为了让接收者能够准确接收数据,应该先向流中写入数据长度,然后再写内容。接收方在读的时候,可以先读出长度,再读内容,因为表示长度的值是uint,它的值大小是固定的4个字节。

    下面代码为客户端发起连接。

                StreamSocket socket = new StreamSocket();
                try
                {
                    HostName svname = new HostName(txtIp.Text);
    
                    // 连接
                    await socket.ConnectAsync(svname, txtPort.Text);
                    // 接收数据
                    DataReader reader = new DataReader(socket.InputStream);
                    reader.UnicodeEncoding = UnicodeEncoding.Utf8; //注意
                    // 长度
                    await reader.LoadAsync(sizeof(uint));
                    uint len = reader.ReadUInt32();
                    // 读内容
                    await reader.LoadAsync(len);
                    string msg = reader.ReadString(reader.UnconsumedBufferLength);
                    runRecMsg.Text = msg;
                    // 释放
                    reader.Dispose();


    在读取接收到的数据时,用的是DataReader类,而且记住要统一编码utf-8,然后先加载4个字节,读出内容长度,再加载剩余的字节,最后读出字符串。

    好,最后一步就是配置清单文件,打开清单文件,默认用设计器打开,切换到[功能]选项卡,勾选“Internet(客户端与服务器)”与“专用网络(客户端与服务器)”,而“Internet(客户端)”可以取消。

    XML代码如下。

      <Capabilities>
        <Capability Name="internetClientServer" />
        <Capability Name="privateNetworkClientServer" />
      </Capabilities>

    运行结果请看下面的艳图。

    啊,今天的话题就扯到这里吧,改天再扯其他话题。

    示例源代码下载

  • 相关阅读:
    百度mp3地址解密码
    VB 在EXE后附加信息
    截屏函数
    Base64和StrToByte
    The Android ION memory allocator, DMABUF is mentioned as well
    DDC EDID 介绍
    Memory management for graphic processors TTM的由来
    科普 写display driver的必看 How video card works [2D的四种主要操作]
    GEM vs TTM
    DMABUF 背景介绍文章 Sharing buffers between devices
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/5293133.html
Copyright © 2011-2022 走看看