Windows Mobile程序中如果要使用http或socket连接服务器,需要先连接网络。可以使用ConnMgrEstablishConnectionSync函数来连接。
DWORD dwStatus = 0;
HANDLE hConnection = NULL;
CONNMGR_CONNECTIONINFO sConInfo;
memset(&sConInfo, 0 ,sizeof(CONNMGR_CONNECTIONINFO));
sConInfo.cbSize = sizeof(CONNMGR_CONNECTIONINFO);
sConInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET;
sConInfo.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;
sConInfo.dwFlags = CONNMGR_FLAG_PROXY_HTTP
|CONNMGR_FLAG_PROXY_WAP
|CONNMGR_FLAG_PROXY_SOCKS4
|CONNMGR_FLAG_PROXY_SOCKS5;
sConInfo.bExclusive = FALSE;
sConInfo.bDisabled = FALSE;
sConInfo.guidDestNet = IID_DestNetWAP;
ConnMgrEstablishConnectionSync(&sConInfo, &hConnection, 15000, &dwStatus);
如果知道一个接入点的名称,则可以通过ConnMgrEnumDestinations得到相应接入点的guidDestNet。然后可以使用底层的INET接口连接HTTP了。完了吗?没有。还有个问题:代理服务器。我们都知道,移动的CMNET不需要代理,CMWAP则需要。接入点中可能含有代理服务器信息,而且接入类型包括HTTP、WAP、安全WAP、Socks等等,每一种都可能需要不同的代理。不要奢望ConnMgrEnumDestinations函数可以得到这么多的东东。
事实上,微软是提供了一个函数的,这就是传说中的ConnMgrProviderMessage。怎么样,这下总该圆满了吧?...还没完,接着往下走。
我测的结果,在真机上,这个函数从来没有成功过,Never。郁闷之极。与签名有关吗?未可知。
正面强攻不行。打枪的不要,悄悄的进村。我们来看看手机的注册表。在HKEY_LOCAL_MACHINE/Comm/ConnMgr项下,有详细的接入点的信息。Destinations子项下列出了手机所有的接入点,相应的键值有DestId这一项。我们的目光再跳到与ConnMgr平级的Providers项,也有很多信息,其中一子项{EF097F4C-DC4B-4c98-8FF6-AEF805DC0E8E},快接近我们要的宝贝了。该项有很多子项,我们遍历每一项,直到找到一个键值SrcId与我们上面说的DestId相等。看到了吧,与SrcId平级的键值有很多,不过我们目前需要的就那么两项,Type和Proxy。Type就是上面说的接入类型(HTTP、WAP、安全WAP、Socks等),而Proxy正是我们凄凄惨惨戚戚寻寻觅觅的一串字符。
以上是Windows Mobile5.0的结果。在Pocket PC2003和Smartphone2003中,HKEY_LOCAL_MACHINE/Comm/ConnMgr对应为HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/ConnMgr。
至此,寻宝经历告一段落。
看一下微软提供的一个Demo: #include<windows.h> #include<wininet.h> #include<iostream.h> DWORD dwNumKSent; DWORD dwNumKToSend; DWORD dwNumBytesComplete = 0; char lpOutBuf[1024]; HANDLE hConnectedEvent, hRequestCompleteEvent; HINTERNET hInstance, hConnect, hRequest; char *lpszUrl, *lpszServer; BOOL bAllDone = FALSE; void __stdcall Callback(HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus, LPVOID lpStatusInfo, DWORD dwStatusInfoLen); void main(int argc, char *argv[]) { if (argc != 4) { cout << "Usage: sendreqexasync <server> <url> <size in kilobytes>" << endl; cout << " Example: sendreqexasync www.foo.com /postfolder/upload.exe 256" << endl; return; } lpszServer = argv[1]; lpszUrl = argv[2]; dwNumKToSend = atoi(argv[3]); FillMemory(lpOutBuf, 1024, 'A'); hConnectedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); hRequestCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL); hInstance = InternetOpen("sendreqexasync", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);//异步 if (hInstance == NULL) { cout << "InternetOpen failed, error " << GetLastError(); return; } if (InternetSetStatusCallback(hInstance, (INTERNET_STATUS_CALLBACK)&Callback) == INTERNET_INVALID_STATUS_CALLBACK) { cout << "InternetSetStatusCallback failed, error " << GetLastError(); return; } hConnect = InternetConnect(hInstance, lpszServer, //服务器 INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1); if (hConnect == NULL) { if (GetLastError() != ERROR_IO_PENDING) { cout << "InternetConnect failed, error " << GetLastError(); return; } WaitForSingleObject(hConnectedEvent, INFINITE); } hRequest = HttpOpenRequest(hConnect, "POST", lpszUrl,//页面 NULL, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 2); if (hRequest == NULL) { if (GetLastError() != ERROR_IO_PENDING) { cout << "HttpOpenRequest failed, error " << GetLastError(); return; } WaitForSingleObject(hRequestCompleteEvent, INFINITE); } INTERNET_BUFFERS IntBuff; FillMemory(&IntBuff, sizeof(IntBuff), 0); IntBuff.dwStructSize= sizeof(IntBuff); IntBuff.dwBufferTotal = 1024*dwNumKToSend; IntBuff.lpcszHeader = "Content-Type: text/text/r/n"; IntBuff.dwHeadersLength = lstrlen(IntBuff.lpcszHeader); if (!HttpSendRequestEx(hRequest, &IntBuff, NULL, 0, 2)) { if (GetLastError() != ERROR_IO_PENDING) { cout << "HttpSendRequestEx failed, error " << GetLastError(); return; } cout << "HttpSendRequestEx called successfully" << endl; cout.flush(); WaitForSingleObject(hRequestCompleteEvent, INFINITE);//等待信号 } //此处 for(dwNumKSent = 0; dwNumKSent < dwNumKToSend; dwNumKSent++) { DWORD dwBytesWritten; if(!InternetWriteFile(hRequest, lpOutBuf, 1024, &dwBytesWritten)) { if (GetLastError() != ERROR_IO_PENDING) { cout << "InternetWriteFile failed, error " << GetLastError(); return; } else { cout << "InternetWriteFile completing asynchronously" << endl; cout.flush(); WaitForSingleObject(hRequestCompleteEvent, INFINITE);// } } } cout << "Calling HttpEndRequest" << endl; cout.flush(); if (!HttpEndRequest(hRequest, NULL, HSR_INITIATE, 2)) { if (GetLastError() == ERROR_IO_PENDING) { cout << "HttpEndRequest called" << endl; cout.flush(); WaitForSingleObject(hRequestCompleteEvent, INFINITE); } else { cout << "HttpEndRequest failed, error " << GetLastError() << endl; return; } } cout << "------------------- Read the response -------------------" << endl; char lpReadBuff[256]; do { INTERNET_BUFFERS InetBuff; FillMemory(&InetBuff, sizeof(InetBuff), 0); InetBuff.dwStructSize = sizeof(InetBuff); InetBuff.lpvBuffer = lpReadBuff; InetBuff.dwBufferLength = sizeof(lpReadBuff) - 1; cout << "Calling InternetReadFileEx" << endl; cout.flush(); if (!InternetReadFileEx(hRequest, &InetBuff, 0, 2)) { if (GetLastError() == ERROR_IO_PENDING) { cout << "Waiting for InternetReadFile to complete" << endl; cout.flush(); WaitForSingleObject(hRequestCompleteEvent, INFINITE); } else { cout << "InternetReadFileEx failed, error " << GetLastError(); cout.flush(); return; } } lpReadBuff[InetBuff.dwBufferLength] = 0; cout << lpReadBuff; cout.flush(); if (InetBuff.dwBufferLength == 0) bAllDone = TRUE; } while (bAllDone == FALSE); cout << endl << endl << "------------------- Request Complete ----------------" << endl; } void __stdcall Callback(HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus, LPVOID lpStatusInfo, DWORD dwStatusInfoLen) { cout << "Callback dwInternetStatus: " << dwInternetStatus << " Context: " << dwContext << endl; cout.flush(); switch(dwContext) { case 1: // Connection handle if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED) { INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo; hConnect = (HINTERNET)pRes->dwResult; cout << "Connect handle created" << endl; cout.flush(); SetEvent(hConnectedEvent); } break; case 2: // Request handle switch(dwInternetStatus) { case INTERNET_STATUS_HANDLE_CREATED: { INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo; hRequest = (HINTERNET)pRes->dwResult; cout << "Request handle created" << endl; cout.flush(); } break; case INTERNET_STATUS_REQUEST_SENT: { DWORD *lpBytesSent = (DWORD*)lpStatusInfo; cout << "Bytes Sent: " << *lpBytesSent << endl; dwNumBytesComplete += *lpBytesSent; } break; case INTERNET_STATUS_REQUEST_COMPLETE: { INTERNET_ASYNC_RESULT *pAsyncRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo; cout << "Function call finished" << endl; cout << "dwResult: " << pAsyncRes->dwResult << endl; cout << "dwError: " << pAsyncRes->dwError << endl; cout.flush(); SetEvent(hRequestCompleteEvent); } break; case INTERNET_STATUS_RECEIVING_RESPONSE: cout << "Receiving Response" << endl; cout.flush(); break; case INTERNET_STATUS_RESPONSE_RECEIVED: { DWORD *dwBytesReceived = (DWORD*)lpStatusInfo; cout << "Received " << *dwBytesReceived << endl; cout.flush(); } } } } |