WP7应用开发笔记(6) 服务器设计
TCP服务器
服务器类图
这里模仿了WebFrom的IHttpHandler,我设计了一个ITcpHandler提供给ServiceListener让外部解析。实现类是KeyMethodHandler。
报文TcpContext包含了TcpRequest和TcpResponse,TcpRequest和消息报文结构相同,增加了从Socket获取的TcpEndpoint,TcpResponse仅仅只是回调状态和消息(暂时没有使用)。
ServiceListener、BufferManager、SocketAsyncEventArgsPool和MDSN上标准的例子接近,原则上都是为了重用Buffer和SocketAsyncEventArgs对象,节约内存开销。
回顾一下SocketAsyncEventArgs方式的Socket代码写法
var e = new SocketAsyncEventArgs();
e.Completed += this.OnAccept;
e.AcceptSocket = null;
...
private void ProcessAccept(SocketAsyncEventArgs e){
...
bool willRaiseEvent = this.listener.AcceptAsync(e);
if (!willRaiseEvent)
{
this.OnAccept(null, e);
}
}
...
private void OnAccept(object sender, SocketAsyncEventArgs e)
{
try
{
if (e.SocketError != SocketError.Success)
{
...
return;
}
Socket client = e.AcceptSocket;
if (client == null)
{
...
return;
}
var asyncEventArg = eventPool.Pop();
if (asyncEventArg == null)
{
...
return;
}
var token = (AsyncUserToken)asyncEventArg.UserToken;
token.Socket = client;
token.EndPoint = (IPEndPoint)client.RemoteEndPoint;
bool willRaiseEvent = client.ReceiveAsync(asyncEventArg);
if (!willRaiseEvent)
{
this.ProcessReceive(asyncEventArg);
}
}
catch (Exception err)
{
Debug.Print("Accept exception,{0}", err);
}
finally
{
e.AcceptSocket = null;
this.ProcessAccept(e);
}
}
命令解析
命令解析的类图
KeyMethodHandler包含了2个ICommand接口,分别的实现是KeyboardCommand用于触发直接按键事件,另外一个是MediaCommand 用于触发媒体按键。这2个类都包含了IKeyboardHook接口,实现是KeyboardHook用于调用系统接口。
媒体按键一般都组合快捷键,而且可以配置,配置类就是MediaMethodConfig.
调用系统接口触发键盘的实现:
public interface IKeyBoardHook { void PressKey(Keys keyCode); void PressKey(Keys[] keyCode); } public sealed class KeyBoardHook : IKeyBoardHook { private static readonly KeyBoardHook instance = new KeyBoardHook(); public static KeyBoardHook Instance { get { return instance; } } private KeyBoardHook() { } private enum KeyBoard { KeyDown = 0x0001, KeyUp = 0x0002 } public void PressKey(Keys keyCode) { PressKey(new[] { keyCode }); } public void PressKey(Keys[] keyCodes) { if (keyCodes == null || keyCodes.Length == 0) return; int length = keyCodes.Length; for (int i = 0; i < length; i++) { PutDownKey(keyCodes[i]); } Thread.SpinWait(5000); for (int i = length - 1; i >= 0; i--) { ReceiveKey(keyCodes[i]); } } private static void PutDownKey(Keys keyCode) { KeyboardEvent((byte)keyCode, 0, KeyBoard.KeyDown, 0); } private static void ReceiveKey(Keys keyCode) { KeyboardEvent((byte)keyCode, 0, KeyBoard.KeyUp, 0); } [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "keybd_event")] private static extern void KeyboardEvent( byte bVk, byte bScan, KeyBoard dwFlags, int dwExtraInfo ); }