上一篇说图像压缩和显示的时候,大家已经看到了在客户端的捕捉键鼠消息的代码,这里就直接说在服务器的实现了。
代码其实很简单,但是需要注意的是,在网络接收消息后,不要在网络回调里,直接 mouse_event或者keybd_event 做其它事情也不行,除了从缓冲区取一个缓冲区,然后 Post 到 IOCP 以外,否则,轻则影响效率,重则死锁。当然接收的数据还是要处理的,用的是线程池函数 QueueUserWorkItem,你懂的。不过,QueueUserWorkItem 有时,有点问题(有时有 .Net 程序运行的时候,CPU 很高,原因不明,可能是要和 .Net 强线程吧),不过,我有仿 QueueUserWorkItem 的函数,可以避免这个问题,这里就不说了。
代码其实很简单,但是需要注意的是,在网络接收消息后,不要在网络回调里,直接 mouse_event或者keybd_event 做其它事情也不行,除了从缓冲区取一个缓冲区,然后 Post 到 IOCP 以外,否则,轻则影响效率,重则死锁。当然接收的数据还是要处理的,用的是线程池函数 QueueUserWorkItem,你懂的。不过,QueueUserWorkItem 有时,有点问题(有时有 .Net 程序运行的时候,CPU 很高,原因不明,可能是要和 .Net 强线程吧),不过,我有仿 QueueUserWorkItem 的函数,可以避免这个问题,这里就不说了。
DWORD WINAPI RunCommand(LPVOID lpParam)
{
SOCKET_POST_CTRL *pRecv = (SOCKET_POST_CTRL *) lpParam;
switch (pRecv->remoteCtrl.dwCtrl) {
case CTRL_MOUSE:
SetCursorPos(pRecv->remoteCtrl.x * GetSystemMetrics(SM_CXSCREEN) / pRecv->remoteCtrl.dwWidth,
pRecv->remoteCtrl.y * GetSystemMetrics(SM_CYSCREEN) / pRecv->remoteCtrl.dwHeight);
mouse_event(pRecv->remoteCtrl.dwFlags, 0, 0, 0, 0);
break;
case CTRL_KEYBOARD:
::keybd_event((BYTE) pRecv->remoteCtrl.nChar, (BYTE) pRecv->remoteCtrl.nChar, pRecv->remoteCtrl.nFlags, 0);
break;
default:
break;
}
SQ_PushBack(pRecv->hQueue, ForceCast<DWORD>(pRecv));
return 0;
}
VOID OnRecv(SOCKET_POST *pPost)
{
SOCKET_POST_CTRL *pRecv = (SOCKET_POST_CTRL *) pPost;
if (pRecv->dwBytesTrans == 0) {
IOCP_Close(pRecv->pInfo);
SQ_PushBack(pRecv->hQueue, ForceCast<DWORD>(pRecv));
}
else {
pRecv->dwLeftSize -= pRecv->dwBytesTrans;
if (pRecv->dwLeftSize > 0) {
pRecv->pWSABuf = &(pRecv->wsaBuf[0]);
pRecv->dwBufCount = ItemCount(pRecv->wsaBuf);
pRecv->wsaBuf[0].len= pRecv->dwLeftSize;
pRecv->wsaBuf[0].buf= (PCHAR) &(pRecv->pktHead);
pRecv->wsaBuf[0].buf+= (sizeof(pRecv->pktHead) + sizeof(pRecv->remoteCtrl) - pRecv->dwLeftSize);
IOCP_PostRecv(m_hIOCP, pRecv->pInfo, pRecv);
}
else {
switch (pRecv->pktHead.dwStamp) {
case STAMP_PACKET:
QueueUserWorkItem(RunCommand, pRecv, 0);
SQ_PopFront(m_hQueueRecv, ForceCast<LPDWORD>(&pRecv));
PostRecv(m_pInfo, pRecv);
break;
default:
IOCP_Close(pRecv->pInfo);
SQ_PushBack(pRecv->hQueue, ForceCast<DWORD>(pRecv));
break;
}
}
}
}