April 15, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Mastering Internet Programming on Mobile Devices: First Steps, Page 2

  • November 1, 2004
  • By Alex Gusev, Alex Gusev
  • Send Email »
  • More Articles »

Working with Sessions and Synchronous Requests

An alternative way to get connected is to use InternetConnect-based APIs. The common working flow may be organized as follows:

  1. Call InternetConnect to get session handle.
  2. Call HttpOpenRequest to define all desired request parameters and request type (HTTP or FTP).
  3. Call HttpSendRequest or HttpSendRequestEx to send the request to the remote host.
  4. Read the possible answer with InternetReadFile.
  5. Close the request handle.
  6. Repeat all from Step 2.
  7. Close the session handle.

In C# terms, all the business looks even simpler:

  1. Create an instance of the WebRequest (actually HttpWebRequest) class.
  2. Set up all required headers' values if needed.
  3. Retrieve the host response as an instance of the HttpWebResponse class.
  4. Read data from the response through the Stream and StreamReader classes.

To illustrate all that was mentioned above, let's consider a couple of samples in both the C/C++ and C# languages:

// 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;
   }
}

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:

  • Define request content type—"text/xml" or "application/x-www-form-urlencoded".
  • The request verb should be set to "POST" when calling either the HttpOpenRequest or HttpWebRequest.Method property.
  • Provide lpOptional and dwOptionalLength parameters to HttpOpenRequest as form data according to the HTTP specification.

Sample:

HttpSendRequest(hRequest, (LPCTSTR) sHTTPHeader,
                sHTTPHeader.GetLength (), lpFormData,
                dwFormDataLength))

C#:

  • Set the HttpWebRequest.ContentType property to the desired content type.
  • The HttpWebRequest.Method property should be set to "POST".
  • Create an instance of the Stream class on the HttpWebRequest object and then call its Write method.

Sample:

...
// 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)();
...

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.

Conclusion

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.

Downloads

Download the accompanying C++ code's zip file here.

Download the accompanying C# code's zip file here.

About the Author

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.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel