http://www.developer.com/net/csharp/article.php/3429261/Mastering-Internet-Programming-on-Mobile-Devices-First-Steps.htm
So, you need to develop an application that will be able to send and receive some data over the Internet or an intranet from/to remote Web servers. This article set will help you figure out how to do it using WinInet for many common cases. This article will review the initial steps. Let's say a couple of words regarding which language to use or mainly which environment to use: CF.NET or native C/C++ code. With all the enhancements that CF.NET SP2 has, it still experiences particular troubles with communications; for example, communications through proxy servers requiring NTLM authentication. Native code provides many more opportunities on this topic. Thus, when making your final decision, keep all this in mind. In this article, we will use both C++ and C# for code snippets. Prior to establishing any connection, your application should have a valid URL to connect to. WinInet provides a wide set of functions to deal with. First, there are a couple of calls to verify whether there is an opportunity to start communications: You can use them to be sure the device is connected to the network and the request may be executed. Other useful API calls are: They show the existing capabilities on a particular system. Via these functions, you may deetct whether the system uses a proxy server to establish connection. The next group of functions helps you deal with URLs. They are listed below: You may use the above calls to manipulate by URLs. Applications can easily build a target URL from blocks, break the URL into its base and relative parts, replace unsafe characters in the URL, and so forth. Actually, all this is intuitive enough, so we will not dig in too much, just a simple code snippet for an example: As a result, crackedURL will contain a URL divided into base host address, relative path, port number, and so on. If you're developing in C#, compact framework classes do such conversions inside, so you don't need to worry about it in your code. The very first step in working with any library is its initialization. Before using any WinInet functions, your application should call the InternetOpen API to make all required initialization: You can specify any string as a lpszAgent value; for example, TEXT("CeHttp"). This name then will be used as the user agent in HTTP. The dwAccessType parameter is usually equal to INTERNET_OPEN_TYPE_PRECONFIG; in other words, all data is taken from the Registry. In this case, you can leave the next two parameters zeroed. Alternatively, you can specify the desired proxy and proxy bypass list. Note here that an empty string as a proxy name is treated as a legal one, so set lpszProxy to NULL if you don't need to connect via proxy servers. And finally, dwFlags is 0 or one of the following values: Thus, a typical initialization call may look like the following: Once WinInet is initialized, we're ready to establish connections to the desired URLs. You have two main options: In this section, we will discuss the first method—the InternetOpenUrl function. It is quite useful when you need to proceed with some simple operation; for example, to only download data file from a remote host. Thus, the code may look like: InternetOpenUrl internally establishes a connection to the remote host and returns a handle to the Internet session, which may be used later in all I/O operations; for example, InternetReadFile calls. After all, opened handles are released by InternetCloseHandle calls. An alternative way to get connected is to use InternetConnect-based APIs. The common working flow may be organized as follows: In C# terms, all the business looks even simpler: To illustrate all that was mentioned above, let's consider a couple of samples in both the C/C++ and C# languages: Both samples synchronously download some file from a Web server by the HTTP "GET" method. If you need to use the "POST" method, the only additional steps you will be required to do are: Win32 API: Sample: C#: Sample: After such manipulations, data will be sent to the remote server. In turn, the server can return some response that you can interpret as required in your partucular situation. In this article, we have discussed the very first and simple tasks of Internet programming on mobile devices. By using the provided information, you are already able to transmit data from/to Web servers. The next articles will overview asynchronous requests, cookies, secure connections, and XML HTTP features. Download the accompanying C++ code's zip file here. Download the accompanying C# code's zip file here. Alex Gusev started to play with mainframes at the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.
Mastering Internet Programming on Mobile Devices: First Steps
November 1, 2004
Managing URLs
DWORD InternetAttemptConnect(DWORD dwReserved);
BOOL InternetCheckConnection(LPCSTR lpszUrl,DWORD dwFlags,
DWORD dwReserved);
TCHAR szServer[1024];
TCHAR szPath[1024];
URL_COMPONENTS crackedURL;
memset(&crackedURL, 0, sizeof(crackedURL));
crackedURL.dwStructSize = sizeof(crackedURL);
crackedURL.lpszHostName = szServer;
crackedURL.dwHostNameLength = 1024;
crackedURL.lpszUrlPath = szPath;
crackedURL.dwUrlPathLength = 1024;
InternetCrackUrl (pszURL, 0, 0, &crackedURL);
Initializing the Internet Library
HINTERNET WINAPI InternetOpen(
LPCTSTR lpszAgent,
DWORD dwAccessType,
LPCTSTR lpszProxy,
LPCTSTR lpszProxyBypass,
DWORD dwFlags
);
HINTERNET hOpen = InternetOpen (L"CeHttp",
INTERNET_OPEN_TYPE_PRECONFIG, NULL,
NULL, 0);
Making Simple Connections to Remote Hosts
void CWceHttpDlg::OnGo()
{
HINTERNET hOpen = InternetOpen (L"WceHttp",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
if ( !hOpen )
{
AfxMessageBox(L"Failed to open WinInet");
return;
}
HINTERNET hOpenUrl = InternetOpenUrl(
hOpen,m_sURL,
NULL,0,
INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_KEEP_CONNECTION,
0);
if ( !hOpenUrl )
{
DWORD dwErr = GetLastError();
//Handle error
.................
AfxMessageBox(L"Failed to open WinInet");
InternetCloseHandle(hOpen);
return;
}
char szBuffer[4096];
DWORD dwNumberOfBytesRead = 0;
while ( InternetReadFile(hOpenUrl, szBuffer, 4096,
&dwNumberOfBytesRead) &&
dwNumberOfBytesRead )
{
// Do something with received block
....................................
}
InternetCloseHandle(hOpenUrl);
InternetCloseHandle(hOpen);
}
Working with Sessions and Synchronous Requests
// C/C++ sample, GET method
void CWceHttpDlg::OnButton2()
{
UpdateData();
BOOL bRC = TRUE;
HINTERNET hGETRequest;
DWORD dwFlags = INTERNET_FLAG_NO_CACHE_WRITE |
INTERNET_FLAG_KEEP_CONNECTION |
INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID|
INTERNET_FLAG_PRAGMA_NOCACHE;
LPTSTR pszAcceptTypes [] = {TEXT("text/*"), NULL};
TCHAR szServer [1024];
TCHAR szEndpoint [1024];
URL_COMPONENTS crackedURL;
int nPort;
HINTERNET hConnect;
HINTERNET hOpen;
CString sHTTPHeader;
CString sInfo;
if (m_sURL.IsEmpty ())
return;
//Crack URL ...
ZeroMemory (& crackedURL, sizeof (URL_COMPONENTS));
crackedURL.dwStructSize = sizeof (URL_COMPONENTS);
crackedURL.lpszHostName = szServer;
crackedURL.dwHostNameLength = 1024;
crackedURL.lpszUrlPath = szEndpoint;
crackedURL.dwUrlPathLength = 1024;
InternetCrackUrl (m_sURL, 0, 0, &crackedURL);
nPort = crackedURL.nPort;
hOpen = InternetOpen (L"WceHttp", INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
if ( !hOpen )
{
AfxMessageBox(L"Failed to open WinInet");
return;
}
hConnect = InternetConnect (hOpen, szServer, nPort, L"", L"",
INTERNET_SERVICE_HTTP, 0, 0);
if ( !hConnect )
{
sInfo.Format(L"InternetConnect failed: %lu", GetLastError ());
AfxMessageBox(sInfo);
return;
}
// Open an HTTP request handle...
hGETRequest = HttpOpenRequest (hConnect, L"GET", szEndpoint,
NULL, NULL, (LPCTSTR*)
pszAcceptTypes, dwFlags, 0);
if ( !hGETRequest )
{
sInfo.Format(L"HttpOpenRequest failed: %lu", GetLastError ());
AfxMessageBox(sInfo);
InternetCloseHandle (hConnect);
return;
}
// send the request...
sHTTPHeader = L"Content-Type: text/*\r\n";
if (! HttpSendRequest (hGETRequest, (LPCTSTR) sHTTPHeader,
sHTTPHeader.GetLength (), NULL, 0))
{
sInfo.Format(L"HttpSendRequest failed: %lu", GetLastError ());
AfxMessageBox(sInfo);
InternetCloseHandle (hGETRequest);
InternetCloseHandle (hConnect);
return;
}
char szBuffer[4096];
DWORD dwNumberOfBytesRead = 0;
TCHAR wszTmp[4097];
int i = 0;
DWORD dwTotal = 0;
while ( InternetReadFile(hGETRequest, szBuffer, 4096,
&dwNumberOfBytesRead) &&
dwNumberOfBytesRead )
{
memset(wszTmp,0,sizeof(wszTmp));
MultiByteToWideChar(CP_ACP,0,szBuffer,dwNumberOfBytesRead,
wszTmp,sizeof(wszTmp));
i++;
dwTotal += dwNumberOfBytesRead;
}
sInfo.Format(L"Read %d block(s) - %lu byte(s)",i,dwTotal);
AfxMessageBox(sInfo);
InternetCloseHandle (hGETRequest);
InternetCloseHandle (hConnect);
InternetCloseHandle (hOpen);
}
// C# sample, GET method
private void cmdConnect_Click(object sender, System.EventArgs e)
{
string url = txtURL.Text;
string proxy = txtProxy.Text;
try
{
if(!"".Equals(txtProxy.Text))
{
WebProxy proxyObject = new WebProxy("10.168.2.25:8080",true);
proxyObject.Credentials = new NetworkCredential
("alexg", "England2007", "posnet");
// Disable proxy use when the host is local.
proxyObject.BypassProxyOnLocal = true;
// HTTP requests use this proxy information.
GlobalProxySelection.Select = proxyObject;
}
WebRequest req = WebRequest.Create(url);
WebResponse result = req.GetResponse();
Stream ReceiveStream = result.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
StreamReader sr = new StreamReader( ReceiveStream, encode );
// Read the stream into arrays of 1024 characters
Char[] read = new Char[1024];
int count = sr.Read( read, 0, 1024 );
while (count > 0)
{
String str = new String(read, 0, count);
txtOutput.Text += str;
count = sr.Read(read, 0, 1024);
}
}
catch(WebException ex)
{
string message = ex.Message;
HttpWebResponse response = (HttpWebResponse)ex.Response;
if(null != response)
{
message = response.StatusDescription;
response.Close();
}
txtOutput.Text = message;
}
catch(Exception ex)
{
txtOutput.Text = ex.Message;
}
}
HttpSendRequest(hRequest, (LPCTSTR) sHTTPHeader,
sHTTPHeader.GetLength (), lpFormData,
dwFormDataLength))
...
// data is an array of length nLen which should be sent
WebRequest req = WebRequest.Create(url);
req.Method= "POST";
req.ComtentType = "text/xml";
req.ContentLength = nLen;
Stream reqStream = req.GetRequestStream();
reqStream.Write(data,0,nLen);
reqStream.Close();
WebResponse resp = req.GetResponse)();
...
Conclusion
Downloads
About the Author