Windows phone开发之支持的通信方式
主要是由webclient或httpwebrequest两个类提供,直接封装http协议访问web站点。最常用的通信方式。
2. wcf
wcf作为ms大力的通信方案非常强大,但是到了wp7上就变成了太监,只支持简单的basichttpbinding而且还有非常多的限制。
3 socket
7.1sdk里新增的通信方式,支持tcp和udp但只能使用异步的socketasynceventargs事件方式,也有不少限制。
选择通信方式
因为同时需要考虑到服务器端的实现,在服务器端尽量精简,最好不要有什么iis之类大型依赖。
对应是服务器端实现方式如下:
http协议 | httplistener |
wcf | wcf应用程序宿主 |
socket | socket |
由于我使用的是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”
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
}
复制代码
作者 fengyarongaa
上一篇: windows phone开发之获取屏幕分辨率 和 系统版本
下一篇: 困在QQ里的奇瑞
推荐阅读
-
Windows Phone开发之xaml传值交互与控件hyperlinkButton的使用
-
Windows phone开发之支持的通信方式
-
Qt开发笔记之编码x264码流并封装mp4(二):windows平台x264添加mp4支持,gpac库的介绍与编译
-
Windows Phone 7 开发探索笔记4——触控操作之XNA中的Gesture
-
Windows Phone 7 开发之Microsoft.Phone.Tasks中的各项Task
-
Windows phone开发之支持的通信方式
-
Windows Phone开发之xaml传值交互与控件hyperlinkButton的使用
-
Windows Phone 7 开发之Microsoft.Phone.Tasks中的各项Task
-
Windows Phone 7 开发探索笔记4——触控操作之XNA中的Gesture