📄 ch19.htm
字号:
<P>This code is very much like <font color="#008000">TryURL()</font>, except that instead of opening a file with <font color="#008000">session.OpenURL()</font>, it opens an FTP connection with <font color="#008000">session.GetFtpConnection()</font>.
Again, exceptions are caught and essentially ignored, with the routine just making sure that the connection pointer won't be used. The call to <font color="#008000">GetCurrentDirectory()</font> returns the directory on the remote site in which sessions
start. The rest of the routine is just like <font color="#008000">TryURL()</font>.</P>
<P>Add two lines at the end of <font color="#008000">OnQuery() </font>to call this new function:</P>
<pre><font color="#008000"> TryFTPSite(m_host);</font></pre>
<pre><font color="#008000"> TryFTPSite("ftp." + m_host);</font></pre>
<P>Build the application and try it: Figure 19.9 shows Query finding no FTP site at <B>microsoft.com</B> and finding one at <B>ftp.microsoft.com</B>. You may find the delay until results start to appear a little disconcerting. You could correct this by
using asynchronous sockets, or <I>threading,</I> so that early results could be added to the edit box while later results are still coming in over the wire, but for a simple demonstration application like this, just wait patiently until the results appear.
It may takes several minutes, depending on network traffic between your site and Microsoft's, your line speed, and so on.</P>
<A HREF="Ufigs09.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch19/Ufigs09.gif"><b>Fig. 19.9</b></A>
<P><I>Query finds one Microsoft FTP site.</I></P>
<P>If Query doesn't find Web pages or FTP sites, perhaps this domain does not exist at all, or does not have any Internet services other than e-mail, but there are a few more investigative tricks available. The results of these investigations will
definitely add to your knowledge of existing sites.</P>
<H3><B>Querying Gopher Sites</B></H3>
<P>As was the case with FTP, <font color="#008000">TryURL()</font> won't work for querying a Gopher site like <B>gopher.company.com</B>, because this returns a list of file names rather than a single file. The solution is to write a function called <font
color="#008000">TryGopherSite()</font> that is almost identical to <font color="#008000">TryFTPSite()</font>, except that it opens a <font color="#008000">CGopherConnection</font>, and instead of a single line describing the default directory, it echoes a
single line describing the Gopher locator associated with the site. Add TryGopherSite to CQueryDlg by right-clicking the class name in ClassView and choosing Add Function, as you did for <font color="#008000">TryFTPSite()</font>. The code for <font
color="#008000">TryGopherSite()</font> is in Listing 19.6.</P>
<P><I>Listing 19.6—QueryDlg.cpp—CQueryDlg::TryGopherSite()</I></P>
<pre><font color="#008000">void CQueryDlg::TryGopherSite(CString host)</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> CInternetSession session;</font></pre>
<pre><font color="#008000"> m_out += "Trying Gopher site " + host + "\r\n";</font></pre>
<pre><font color="#008000"> UpdateData(FALSE);</font></pre>
<pre><font color="#008000"> CGopherConnection* connection = NULL;</font></pre>
<pre><font color="#008000"> try</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> connection = session.GetGopherConnection(host);</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> catch (CInternetException* pEx)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> //if anything went wrong, just set connection to NULL</font></pre>
<pre><font color="#008000"> connection = NULL;</font></pre>
<pre><font color="#008000"> pEx->Delete();</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> if (connection)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> m_out += "Connection established. \r\n";</font></pre>
<pre><font color="#008000"> CString line;</font></pre>
<pre><font color="#008000"> CGopherLocator locator = connection->CreateLocator(NULL, NULL, </font><font color="#008000">GOPHER_TYPE_DIRECTORY);</font></pre>
<pre><font color="#008000"> line = locator;</font></pre>
<pre><font color="#008000"> m_out += "first locator is " + line + "\r\n";</font></pre>
<pre><font color="#008000"> connection->Close();</font></pre>
<pre><font color="#008000"> delete connection;</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> else</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> m_out += "No server found there. \r\n";</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> m_out += "-------------------------\r\n";</font></pre>
<pre><font color="#008000"> UpdateData(FALSE);</font></pre>
<pre><font color="#008000">}</font></pre>
<P>The call to <font color="#008000">CreateLocator()</font> takes three parameters. The first is the file name, which may include wild cards. <font color="#008000">NULL</font> means any file. The second parameter is a selector that can be <font
color="#008000">NULL</font>. The third is one of the following types:</P>
<ul>
<pre><font color="#008000">GOPHER_TYPE_TEXT_FILE</font></pre>
<pre><font color="#008000">GOPHER_TYPE_DIRECTORY</font></pre>
<pre><font color="#008000">GOPHER_TYPE_CSO</font></pre>
<pre><font color="#008000">GOPHER_TYPE_ERROR</font></pre>
<pre><font color="#008000">GOPHER_TYPE_MAC_BINHEX</font></pre>
<pre><font color="#008000">GOPHER_TYPE_DOS_ARCHIVE</font></pre>
<pre><font color="#008000">GOPHER_TYPE_UNIX_UUENCODED</font></pre>
<pre><font color="#008000">GOPHER_TYPE_INDEX_SERVER</font></pre>
<pre><font color="#008000">GOPHER_TYPE_TELNET</font></pre>
<pre><font color="#008000">GOPHER_TYPE_BINARY</font></pre>
<pre><font color="#008000">GOPHER_TYPE_REDUNDANT</font></pre>
<pre><font color="#008000">GOPHER_TYPE_TN3270</font></pre>
<pre><font color="#008000">GOPHER_TYPE_GIF</font></pre>
<pre><font color="#008000">GOPHER_TYPE_IMAGE</font></pre>
<pre><font color="#008000">GOPHER_TYPE_BITMAP</font></pre>
<pre><font color="#008000">GOPHER_TYPE_MOVIE</font></pre>
<pre><font color="#008000">GOPHER_TYPE_SOUND</font></pre>
<pre><font color="#008000">GOPHER_TYPE_HTML</font></pre>
<pre><font color="#008000">GOPHER_TYPE_PDF</font></pre>
<pre><font color="#008000">GOPHER_TYPE_CALENDAR</font></pre>
<pre><font color="#008000">GOPHER_TYPE_INLINE</font></pre>
<pre><font color="#008000">OPHER_TYPE_UNKNOWN</font></pre>
<pre><font color="#008000">GOPHER_TYPE_ASK</font></pre>
<pre><font color="#008000">GOPHER_TYPE_GOPHER_PLUS</font></pre>
</ul>
<P>Normally, you don't build locators for files or directories, instead you ask the server for them. The locator that will be returned from this call to <font color="#008000">CreateLocator()</font> describes the locator associated with the site you are
investigating.</P>
<P>Add a pair of lines at the end of <font color="#008000">OnQuery()</font> that call this new TryGopherSite() function:</P>
<pre><font color="#008000"> TryGopherSite(m_host);</font></pre>
<pre><font color="#008000"> TryGopherSite("gopher." + m_host);</font></pre>
<P>Build and run the program again. Again, you may have to wait several minutes for the results. Figure 19.10 shows that Query has found two Gopher sites for <B>harvard.edu</B>. In both cases, the locator describes the site itself. This is enough to prove
that there is a Gopher site at <B>harvard.edu</B>, which is all that Query is supposed to do.</P>
<A HREF="Ufigs10.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch19/Ufigs10.gif"><b>Fig. 19.10</b></A>
<P><I>Query finds two Harvard Gopher sites.</I></P>
<blockquote><p><img src="tip.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/tip.gif">
<P>Gopher is an older protocol that has been almost entirely supplemented by the World Wide Web. As a general rule, if a site has a Gopher presence, it's been on the Internet since before the World Wide Web existed (1989) or at least before the huge
upsurge in popularity began (1992). What's more, the site was probably large enough in the early 1990's to have an administrator who would set up the Gopher menus and text.</P>
<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>
<H3><B>Using Gopher to send a Finger Query</B></H3>
<P>There is another protocol that can give you information about a site. It's one of the oldest protocols on the Internet, and it's called Finger. You can finger a single user or an entire site, and though many sites have disabled Finger, many more will
provide you with useful information in response to a Finger request.</P>
<P>There is no MFC class or API function with the word <I>finger</I> in its name, but that doesn't mean you can't use the classes already presented. This section relies on a trick—and on knowledge of the Finger and Gopher protocols. While the WinInet
classes are a boon to new Internet programmers who don't know quite how the Internet works, they also have a lot to offer to old-timers who know what's going on under the hood.</P>
<P>As discussed in the "Using Windows Sockets" section of <A HREF="index19.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index19.htm" target="text">Chapter 19</A>, "Sockets, MAPI, and the Internet," all Internet transactions involve both a host and a port. Well-known services use standard
port numbers. For example, when you call <font color="#008000">CInternetSession::OpenURL()</font> with a URL that starts <B><font color="#008000">http://</font></B>, the code behind the scenes connects to port 80 on the remote host. When you call <font
color="#008000">GetFtpConnection()</font>,the connection is made to port 21 on the remote host. Gopher uses port 70. If you look at Figure 19.10, you will see that the locator that describes the <B>gopher.harvard.edu</B> site includes a mention of port
70.</P>
<P>The Gopher documentation makes this clear: If you build a locator with a host name, port 70, Gopher type 0 (<font color="#008000">GOPHER_TYPE_TEXT_FILE</font> is defined to be 0), and a string with a file name, any Gopher client simply sends the
string, whether it's a file name or not, to port 70. The Gopher server listening on that port responds by sending the file.</P>
<P>Now, Finger is a simple protocol, too. If you send a string to port 79 on a remote host, the Finger server that is listening there will react to the string by sending a Finger reply. If the string is only <font color="#008000">\r\n</font>, the usual
reply is a list of all the users on the host and some other information about them, such as their real names. (Many sites consider this an invasion of privacy or a security risk, and they disable Finger. But many other sites deliberately make this same
information available on their Web pages.)</P>
<P>Putting this all together, if you build a Gopher locator using port 79—rather than the default 70—and an empty file name, you can do a Finger query using the MFC WinInet classes. First, add another function to <font
color="#008000">CQueryDlg</font> called <font color="#008000">TryFinger()</font>, which takes a <font color="#008000">CString host</font> and returns <font color="#008000">void</font>. The code for this function is very much like <font
color="#008000">TryGopherSite()</font>, except that the connection is made to port 79:</P>
<pre><font color="#008000"> connection = session.GetGopherConnection(host,NULL,NULL,79);</font></pre>
<P>Once the connection is made, a text file locator is created:</P>
<pre><font color="#008000"> CGopherLocator locator = connection->CreateLocator(NULL, NULL, </font><font color="#008000">GOPHER_TYPE_TEXT_FILE);</font></pre>
<P>This time, rather than simply casting the locator into a <font color="#008000">CString</font>, use it to open a file:</P>
<pre><font color="#008000"> CGopherFile* file = connection->OpenFile(locator);</font></pre>
<P>Then echo the first 20 lines of this file, just as <font color="#008000">TryURL()</font> echoed the first 20 lines of the file returned by a Web server. The code to do this is in Listing 20.7.</P>
<P><I>Listing 20.7—QueryDlg.cpp—CQueryDlg::TryFinger() excerpt</I></P>
<pre><font color="#008000"> if (file)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> CString line;</font></pre>
<pre><font color="#008000"> for (int i=0; i < 20 && file->ReadString(line); i++)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> m_out += line + "\r\n";</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> file->Close();</font></pre>
<pre><font color="#008000"> delete file;</font></pre>
<pre><font color="#008000"> }</font></pre>
<P>Putting it all together, <font color="#008000">TryFinger()</font> is shown in Listing 19.8.</P>
<P><I>Listing 19.8—QueryDlg.cpp—CQueryDlg::TryFinger()</I></P>
<pre><font color="#008000">void CQueryDlg::TryFinger(CString host)</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> CInternetSession session;</font></pre>
<pre><font color="#008000"> m_out += "Trying to Finger " + host + "\r\n";</font></pre>
<pre><font color="#008000"> UpdateData(FALSE);</font></pre>
<pre><font color="#008000"> CGopherConnection* connection = NULL;</font></pre>
<pre><font color="#008000"> try</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> connection = session.GetGopherConnection(host,NULL,NULL,79);</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> catch (CInternetException* pEx)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> //if anything went wrong, just set connection to NULL</font></pre>
<pre><font color="#008000"> connection = NULL;</font></pre>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -