最近有个项目,客户需要通过浏览器查询一个运行与WEBSERVER上的普通应用程序的一些输出结果。我设想通过写一个ISAPI程序接收客户请求,然后由ISAPI通知应用程序输出计算结果。原本以为很简单的一个问题,让ISAPI直接向应用程序发个消息就成。后来发现由于ISAPI程序与IIS运行在同一程序空间,根本无法通过FindWindow一类的方法获得应用程序的窗口句柄,即使通过一些非常规的方法获得了城口句柄也无法向应用程序发送消息。原因还不能很准确的解释,估计是因为SERVICE程序的特殊性造成的吧。为了解决这个问题,想了很多办法,后来采用了利用SOCKET 象本机应用发送UDP报文的办法解决。注意只能采用标准的SOCKET编程,不能使用MFC的SOCKET类,因为在ISAPI的DLL中无法完成AfxSocketInit。关键代码如下:
ISAPI侧:
在构造函数中初始化SOCKET
WSADATA wsa;
WSAStartup(MAKEWORD(2,0),&wsa);
m_sendSocks=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP );
接受用户请求后发送UDP报文:
void CAewebExtension::GetPic(CHttpServerContext* pCtxt, LPTSTR szParam)
{
........
char szSend[20];
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(6801);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
sprintf(szSend,"%s,%d",magicWord,seqNo);
sendto(m_sendSocks,szSend,strlen(szSend),0, (struct sockaddr*)&addr, sizeof(struct sockaddr));
.......
}
析构函数
closesocket(m_sendSocks);
WSACleanup();
在应用程序侧由于是MFC的标准应用可直接采用CSocket类。在应用程序的MAINFRM里直接创建一个接收线程用于接受ISAPI的报文。
在ONCREATE里加入:
AfxBeginThread(WebNetMessage,(LPVOID)this->GetSafeHwnd()); //创建接收线程
线程代码:
UINT WebNetMessage( LPVOID pParam )
{
CSocket sockRecv;
CString csTmp,csTmp1;
sockRecv.Create(6801,SOCK_DGRAM,"127.0.0.1");
sockRecv.Bind(6801,"127.0.0.1");
while (true)
{
WPARAM wParam;
char szRecv[20];
CString szIP("127.0.0.1");
UINT uPort=6800;
int iRecv =sockRecv.ReceiveFrom(szRecv,20,szIP,uPort,0);
TRACE("received %s total=%d/n",szRecv,iRecv);
szRecv[iRecv]='/0';
csTmp=szRecv;
if (csTmp.Left(strlen(magicWord)).Compare(magicWord)==0)
{
csTmp1=csTmp.Right(csTmp.GetLength()-strlen(magicWord)-1);
wParam=atoi(csTmp1.LockBuffer());
csTmp1.UnlockBuffer();
::SendMessage((HWND)pParam,g_msg_request_pic, wParam,0 );
}
}
return 0;
}
from: http://aeea.bokee.com/