设为首页 收藏本站
查看: 729|回复: 0

[经验分享] Windows phone开发之支持的通信方式

[复制链接]

尚未签到

发表于 2016-5-24 11:11:08 | 显示全部楼层 |阅读模式
1. HTTP协议

主要是由WebClient或HttpWebRequest两个类提供,直接封装HTTP协议访问Web站点。最常用的通信方式。

2. WCF

WCF作为MS大力推广的通信方案非常强大,但是到了WP7上就变成了太监,只支持简单的BasicHttpBinding而且还有非常多的限制。

3 Socket

7.1SDK里新增的通信方式,支持TCP和UDP但只能使用异步的SocketAsyncEventArgs事件方式,也有不少限制。


选择通信方式

因为同时需要考虑到服务器端的实现,在服务器端尽量精简,最好不要有什么IIS之类大型依赖。
对应是服务器端实现方式如下:

HTTP协议HttpListener
WCFWcf应用程序宿主
SocketSocket

由于我使用的是Win7 HttpListener和BasicHttpBinding在监听外网IP时都需要管理员身份验证,这点很不友好,我每次开程序都提示一下,不爽。所以决定使用Socket。


SOCKET协议选择

而Socket分为TCP和UDP,为了稳定选择了有重传功能和回复的TCP(其实UDP也不是什么问题)。
TCP需要3次握手来维持链接,但是按照“偶尔连接”(Occasionally Connect)的设计准则,我不能让手机一直保持连接,而且断线检查也是个麻烦事。
所以决定采用HTTP1.0类似的短链接方式,就是连上、发一条消息、然后断开的流程(暂时没有回复)




应用层消息报文设计

这个程序比较简单设计的报文也很简单,
因为内网传输不需要考虑身份验证,加密、完整性等,而且短链接不会遇到粘包和拆包之类的,真是太轻松了。
报文结构如下

Length长度4字节 int
Action动作32字节 UTF8编码
Context内容长度由Length描述 UTF8编码


Length表示Context的长度,报文本身长度为Length+4+32
Action目前只有”TAP”按键 一种
Context表示按键的类型 有2种分类


  • 一种是 Keyboard 直接对应键盘的键名称
  • 另一种是 Media 媒体控制用 包括TogglePlayPause(播放暂停)、Forward(前进)、Backward(后退)IncreaseVolume(提高音量)等

表示方式是“Media.TogglePlayPause”



DSC0000.gif View Code
namespace VirtualKeyboard.Contract
{
public static class KeyMethods
    {
public const string KeyboardPackage = "Keyboard";
public const string MediaPackage = "Media";

public static class Keyboard
        {
private const string KeyboardPre = KeyboardPackage + ".";

/// <summary>
/// Enter
/// </summary>
            public const string Enter = KeyboardPre + "Enter";

/// <summary>
/// Esc
/// </summary>
            public const string Esc = KeyboardPre + "Esc";
        }

public static class Media
        {
private const string MediaPre = MediaPackage + ".";

/// <summary>
///  切换播放暂停
/// </summary>
            public const string TogglePlayPause = MediaPre + "TogglePlayPause";

/// <summary>
/// 快进
/// </summary>
            public const string FastForward = MediaPre + "FastForward";

/// <summary>
/// 快退
/// </summary>
            public const string FastBackward = MediaPre + "FastBackward";

/// <summary>
/// 大步快进
/// </summary>
            public const string VeryFastForward = MediaPre + "VeryFastForward";

/// <summary>
/// 大步快退
/// </summary>
            public const string VeryFastBackward = MediaPre + "VeryFastBackward";

/// <summary>
/// 前进
/// </summary>
            public const string Forward = MediaPre + "Forward";

/// <summary>
/// 前退
/// </summary>
            public const string Backward = MediaPre + "Backward";

/// <summary>
/// 提高音量
/// </summary>
            public const string IncreaseVolume = MediaPre + "IncreaseVolume";

/// <summary>
/// 降低音量
/// </summary>
            public const string DecreaseVolume = MediaPre + "DecreaseVolume";

/// <summary>
/// 静音
/// </summary>
            public const string MuteVolume = MediaPre + "MuteVolume";

/// <summary>
/// 上一集
/// </summary>
            public const string PreviousTrack = MediaPre + "PreviousTrack";

/// <summary>
/// 下一集
/// </summary>
            public const string NextTrack = MediaPre + "NextTrack ";

/// <summary>
/// 停止
/// </summary>
            public const string Stop = MediaPre + "Stop";

/// <summary>
/// 全屏
/// </summary>
            public const string FullScreen = MediaPre + "FullScreen";
        }
    }
}
复制代码







客户端通信代码实现

View Code
public class SendCommandCompletedEventArgs : EventArgs
    {
public bool Success { get; internal set; }
public string ErrMessage { get; internal set; }
    }

public class Client
    {
const int ActionSize = 32;
const int BufferSize = 1024;

public event EventHandler<SendCommandCompletedEventArgs> SendCommandCompleted;

private void OnSendCommandCompleted(SendCommandCompletedEventArgs e)
        {
            EventHandler<SendCommandCompletedEventArgs> handler = SendCommandCompleted;
if (handler != null) handler(this, e);
        }

public Client()
        {

        }

public void SendCommandAsync(EndPoint endPoint, string action, string command)
        {
var actionBuffer = Encoding.UTF8.GetBytes(action);
var contextBuffer = Encoding.UTF8.GetBytes(command);

var bufferSize = contextBuffer.Length + ActionSize + 4;
var lengthBuffer = BitConverter.GetBytes(contextBuffer.Length);

var buffer = new byte[BufferSize];
int offset = 0;
            Array.Copy(lengthBuffer, 0, buffer, offset, lengthBuffer.Length);
            offset += 4;
            Array.Clear(buffer, offset, ActionSize);
            Array.Copy(actionBuffer, 0, buffer, offset, actionBuffer.Length);
            offset += ActionSize;
            Array.Copy(contextBuffer, 0, buffer, offset, contextBuffer.Length);

var socketAsyncEventArgs = new SocketAsyncEventArgs
                                           {
                                               UserToken =
new Socket(AddressFamily.InterNetwork, SocketType.Stream,
                                                              ProtocolType.Tcp)
                                           };
            socketAsyncEventArgs.Completed += AsyncCompleted;
            socketAsyncEventArgs.SetBuffer(buffer, 0, bufferSize);
            socketAsyncEventArgs.RemoteEndPoint = endPoint;
            ProcessConnect(socketAsyncEventArgs);
        }

#region Private
private void ProcessConnect(SocketAsyncEventArgs e)
        {
var socket = (Socket)e.UserToken;
bool willRaiseEvent = socket.ConnectAsync(e);
if (!willRaiseEvent)
            {
                ConnectCompleted(e);
            }
        }

private void ProcessSend(SocketAsyncEventArgs e)
        {
var socket = (Socket)e.UserToken;
bool willRaiseEvent = socket.SendAsync(e);
if (!willRaiseEvent)
            {
                SendCompleted(e);
            }
        }

private void AsyncCompleted(object sender, SocketAsyncEventArgs e)
        {
switch (e.LastOperation)
            {
case SocketAsyncOperation.Connect:
                    ConnectCompleted(e);
break;
case SocketAsyncOperation.Send:
                    SendCompleted(e);
break;
case SocketAsyncOperation.Receive:
                    ReceiveCompleted(e);
break;
default:
return;
            }

        }

private void ReceiveCompleted(SocketAsyncEventArgs e)
        {
        }
private void ConnectCompleted(SocketAsyncEventArgs e)
        {
if (e.SocketError == SocketError.Success)
            {
                ProcessSend(e);
            }
else
            {
                OnSendCommandCompleted(new SendCommandCompletedEventArgs { Success = false, ErrMessage = "接收器无法连接" });
            }
        }

private void SendCompleted(SocketAsyncEventArgs e)
        {
var socket = (Socket)e.UserToken;
            socket.Close();
if (e.SocketError == SocketError.Success)
            {
                OnSendCommandCompleted(new SendCommandCompletedEventArgs { Success = true });
            }
else
            {
                OnSendCommandCompleted(new SendCommandCompletedEventArgs { Success = false, ErrMessage = "发送命令失败" });
            }

        }
#endregion

    }
复制代码





转载自:http://www.cnblogs.com/kiminozo/archive/2012/01/25/2329384.html


  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-221105-1-1.html 上篇帖子: 安装PlayBook Qt开发工具:Qt Creator for Windows版本(beta) 下篇帖子: InletexEMC共享Windows屏幕的永久免费软件
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表