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
            );
    }
posted @   kiminozo  阅读(1236)  评论(2编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示