DatagramSocket 远程访问树莓派

上一篇《如何利用 CSharp 控制 LED 灯》中,我介绍了如何用 C# 控制 LED 灯,只需要简简单单的10几行代码就可以点亮了一个 LED 灯。不过,所有代码都是直接运行在树莓派上,有没有办法通过其它电脑或手机远程控制树莓派来点亮 LED 灯呢?


要实现这个能力,我们需要的是把控制指令通过网络传递到树莓派,然后树莓派上的接收器在接收到指令后执行点亮或熄灭 LED 类的操作。

鉴于 WCF 是微软 .Net 平台上分布式通信框架,因此最先想到的就是使用它构建通信模块,可惜在目前 Universal App Platform 上还无法使用。虽然 WCF 无法使用,但是底层的 socket 肯定是 OK 的。


如果你之前使用过 socket 进行网络编程,那会发现下面的代码相当简单,因为这个 DEMO 不需要可靠连接,所以使用 UDP 这种无连接的方式。

代码主要分为两部分:服务端用于接收并处理消息,客户端用于发送消息。


接收方

参考 C# 的 UDP 编程方式,首先绑定本地的端口用于监听发往该端口的数据,然后就调用 receive 方法开始监听。开发 Universal App,大同小异:与上一篇所采用的项目类型相同,因为不需要 UI,所以使用 "Background application" 作为项目模板。

public async void Run(IBackgroundTaskInstance taskInstance)
{
    // 
    // TODO: Insert code to start one or more asynchronous methods 
    //

    DatagramSocket socket = new DatagramSocket();
    
    //注册消息接收的处理方法
    socket.MessageReceived += Sock_MessageReceived;
    
    //树莓派的地址是 192.168.188.103。下面的代码用于绑定到 192.168.188.103:8888 这个地址上
    await socket.BindEndpointAsync(new Windows.Networking.HostName("192.168.188.103"), "8888"); 

    Debug.WriteLine("Bound");

    //阻止应用程序退出
    taskInstance.GetDeferral();
}

private void Sock_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
}

请注意最后一行,在后台任务中我们经常会调用一些异步的方法,而这些方法并不会立刻结束,GetDeferral 的目的就是为了阻止当前应用程序的退出,从而保证那异步方法的正确执行。当执行完成后,可以调用 BackgroundTaskDeferral.Complete() 方法来表示任务执行完毕,可以正常退出了。

与 socket 编程不太一样的地方是这里不需要额外调用 receive 之类的方法启动 “接收” 流程,只要 BindEndpointAsync 执行完成,就会自动开始进行监听。


发送方

由于发送方的应用程序直接运行在正常的 windows 操作系统或手机中,所以完全可以用曾经开发操作系统应用程序的方式进行开发,为了简单起见,我使用 UdpClient 来搭建客户端代码:

class Program
{
    static void Main(string[] args)
    {
        UdpClient udp = new UdpClient();
        udp.Connect("192.168.188.103", 8888);
        Console.WriteLine("Start Send");
        byte[] byt = UTF8Encoding.Default.GetBytes("hello");
        while (true)
        {
            udp.Send(byt, byt.Length);

            Console.Read();
            Console.WriteLine("Send");
        }
    }
}

上面的代码很简单,就不再解释了。


为 App 增加访问网络的权限


默认情况下,这个 App 部署到 Win 10 IoT 中是无法获取访问网络的能力的,要想访问网络,必须要手动授予。如果开发的是 Windows 8 或 Windows Phone 的 APP,可以通过 GUI 界面进行设置,但是在 Universal APP 中却只能手动在配置文件里进行修改,找到 Package.appxmanifest 文件,找到 Capabilities:

<Package>
  ....
  <Capabilities>
    <Capability Name="internetClientServer"/>
  </Capabilities>
</Package>

internetClientServer 用于从网络上接收和发送数据。(如果已经添加了 internetClientServer,则不需要再添加 internetClient)


一切就绪,剩下的就是编写 Sock_MessageReceived 方法了,这里不再赘述。


参考资源

Capability

C# Socket编程笔记

文章索引

[隐 藏]

本站采用知识共享署名 3.0 中国大陆许可协议进行许可。 ©2014 Charley Box | 关于本站 | 浙ICP备13014059号