?? ch19.htm
字號:
<P>GOPHER_TYPE_PDF</P>
<P>GOPHER_TYPE_CALENDAR</P>
<P>GOPHER_TYPE_INLINE</P>
<P>GOPHER_TYPE_UNKNOWN</P>
<P>GOPHER_TYPE_ASK</P>
<P>GOPHER_TYPE_GOPHER_PLUS</P>
<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 CreateLocator()
describes the locator associated with the site you are investigating.</P>
<P>Add a pair of lines at the end of OnQuery() that call this new TryGopherSite()
function:</P>
<P>
<PRE> TryGopherSite(m_host);
TryGopherSite("gopher." + m_host);
</PRE>
<P>Build and run the program again. Again, you might 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>
<P><A HREF="javascript:popUp('19uvc10.gif')"><B>FIG. 19.10</B></A><B> </B><I>Query
finds two Harvard Gopher sites.</I></P>
<P>
<BLOCKQUOTE>
<P>
<HR>
<strong>TIP:</strong> Gopher is an older protocol that has been supplanted almost entirely
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 1990s to have an administrator who would set up the Gopher menus
and text.
<HR>
</BLOCKQUOTE>
<H2><A NAME="Heading6"></A>Using Gopher to Send a Finger Query</H2>
<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 <I>Finger</I>. 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. Although the WinInet
classes are a boon to new Internet programmers who don't quite know 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 Chapter 18, all
Internet transactions involve a host and a port. Well-known services use standard
port numbers. For example, when you call CInternetSession::OpenURL() with an URL
that begins with <B>http://</B>, the code behind the scenes connects to port 80 on
the remote host. When you call GetFtpConnection(), the connection is made to port
21 on the remote host. Gopher uses port 70. If you look at Figure 19.10, you'll 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 (GOPHER_TYPE_TEXT_FILE is defined to be 0), and a string
with a filename, any Gopher client simply sends the string, whether it's a filename
or not, to port 70. The Gopher server listening on that port responds by sending
the file.</P>
<P>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 \r\n, 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. Many other sites, though, 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--instead
of the default 70--and an empty filename, you can do a Finger query using the MFC
WinInet classes. First, add another function to CQueryDlg called TryFinger(), which
takes a CString host and returns void. The code for this function is very much like
TryGopherSite(), except that the connection is made to port 79:</P>
<P>
<PRE> connection = session.GetGopherConnection(host,NULL,NULL,79);
</PRE>
<P>After the connection is made, a text file locator is created:</P>
<P>
<PRE> CGopherLocator locator = connection->CreateLocator(NULL, NULL,
GOPHER_TYPE_TEXT_FILE);
</PRE>
<P>This time, rather than simply cast the locator into a CString, use it to open
a file:</P>
<P>
<PRE> CGopherFile* file = connection->OpenFile(locator);
</PRE>
<P>Then echo the first 20 lines of this file, just as TryURL() echoed the first 20
lines of the file returned by a Web server. The code for this is in Listing 19.7.</P>
<P>
<H4>Listing 19.7  QueryDlg.cpp--CQueryDlg::TryFinger() Excerpt</H4>
<PRE> if (file)
{
CString line;
for (int i=0; i < 20 && file->ReadString(line); i++)
{
m_out += line + "\r\n";
}
file->Close();
delete file;
</PRE>
<PRE> }
</PRE>
<P>Putting it all together, Listing 19.8 shows TryFinger().</P>
<P>
<H4>Listing 19.8  QueryDlg.cpp--CQueryDlg::TryFinger()</H4>
<PRE>void CQueryDlg::TryFinger(CString host)
{
CInternetSession session;
m_out += "Trying to Finger " + host + "\r\n";
UpdateData(FALSE);
CGopherConnection* connection = NULL;
try
{
connection = session.GetGopherConnection(host,NULL,NULL,79);
}
catch (CInternetException* pEx)
{
//if anything went wrong, just set connection to NULL
connection = NULL;
pEx->Delete();
}
if (connection)
{
m_out += "Connection established. \r\n";
CGopherLocator locator = connection->CreateLocator(NULL, NULL,
GOPHER_TYPE_TEXT_FILE);
CGopherFile* file = connection->OpenFile(locator);
if (file)
{
CString line;
for (int i=0; i < 20 && file->ReadString(line); i++)
{
m_out += line + "\r\n";
}
file->Close();
delete file;
}
connection->Close();
delete connection;
}
else
{
m_out += "No server found there. \r\n";
}
m_out += "------------------------\r\n";
UpdateData(FALSE);
</PRE>
<PRE>}
</PRE>
<P>Add a line at the end of OnQuery() that calls this new function:</P>
<P>
<PRE> TryFinger(m_host);
</PRE>
<P>Now, build and run the application. Figure 19.11 shows the result of a query on
the site <B>whitehouse.gov</B>, scrolled down to the Finger section.</P>
<P><A HREF="javascript:popUp('19uvc11.gif')"><B>FIG. 19.11</B></A><B> </B><I>Query
gets email addresses from the White House Finger server.</I></P>
<P>
<BLOCKQUOTE>
<P>
<HR>
<strong>NOTE:</strong> If the site you are investigating isn't running a Finger server,
the delay will be longer than usual and a message box will appear, telling you the
connection timed out. Click OK on the message box if it appears.[dagger]n
<HR>
</BLOCKQUOTE>
<H2><A NAME="Heading7"></A>Using Gopher to Send a Whois Query</H2>
<P>One last protocol provides information about sites. It, too, is an old protocol
not supported directly by the WinInet classes. It is called <I>Whois</I>, and it's
a service offered by only a few servers on the whole Internet. The servers that offer
this service are maintained by the organizations that register domain names. For
example, domain names that end in <B>.com</B> are registered through an organization
called InterNIC, and it runs a Whois server called <B>rs.internic.net</B> (the <I>rs</I>
stands for Registration Services.) Like Finger, Whois responds to a string sent on
its own port; the Whois port is 43. Unlike Finger, you don't send an empty string
in the locator; you send the name of the host that you want to look up. You connect
to <B>rs.internic.net</B> every time. (Dedicated Whois servers offer users a chance
to change this, but in practice, no one ever does.)</P>
<P>Add a function called TryWhois(); as usual, it takes a CString host and returns
void. The code is in Listing 19.9.</P>
<P>
<H4>Listing 19.9  QueryDlg.cpp--CQueryDlg::TryWhois()</H4>
<PRE>void CQueryDlg::TryWhois(CString host)
{
CInternetSession session;
m_out += "Trying Whois for " + host + "\r\n";
UpdateData(FALSE);
CGopherConnection* connection = NULL;
try
{
connection = session.GetGopherConnection ¬("rs.internic.net",NULL,NULL,43);
}
catch (CInternetException* pEx)
{
//if anything went wrong, just set connection to NULL
connection = NULL;
pEx->Delete();
}
if (connection)
{
m_out += "Connection established. \r\n";
CGopherLocator locator = connection->CreateLocator(NULL, host,
GOPHER_TYPE_TEXT_FILE);
CGopherFile* file = connection->OpenFile(locator);
if (file)
{
CString line;
for (int i=0; i < 20 && file->ReadString(line); i++)
{
m_out += line + "\r\n";
}
file->Close();
delete file;
}
connection->Close();
delete connection;
}
else
{
m_out += "No server found there. \r\n";
}
m_out += "------------------------\r\n";
UpdateData(FALSE);
</PRE>
<PRE>}
</PRE>
<P>Add a line at the end of OnQuery() to call it:</P>
<P>
<PRE> TryWhois(m_host);
</PRE>
<P>Build and run the application one last time. Figure 19.12 shows the Whois part
of the report for <B>mcp.com</B>--this is the domain for Macmillan Computer Publishing,
Que's parent company.</P>
<P><A HREF="javascript:popUp('19uvc12.gif')"><B>FIG. 19.12</B></A><B> </B><I>Query
gets real-life addresses and names from the InterNIC Whois server.</I></P>
<P>Adding code after the Finger portion of this application means that you can no
longer ignore the times when the Finger code can't connect. When the call to OpenFile()
in TryFinger() tries to open a file on a host that isn't running a Finger server,
an exception is thrown. Control will not return to OnQuery(), and TryWhois() will
never be called. To prevent this, you must wrap the call to OpenFile() in a try and
catch block. Listing 19.10 shows the changes to make.</P>
<P>
<H4>Listing 19.10  QueryDlg.cpp  Changes to TryFinger()</H4>
<PRE>//replace this line:
CGopherFile* file = connection->OpenFile(locator);
//with these lines:
CGopherFile* file = NULL;
try
{
file = connection->OpenFile(locator);
}
catch (CInternetException* pEx)
{
//if anything went wrong, just set file to NULL
file = NULL;
pEx->Delete();
</PRE>
<PRE> }
</PRE>
<P>Change TryFinger(), build Query again, and query a site that doesn't run a Finger
server, such as <B>microsoft.com</B>. You will successfully reach the Whois portion
of the application.</P>
<P>
<H2><A NAME="Heading8"></A>Future Work</H2>
<P>The Query application built in this chapter does a lot, but it could do much more.
There are email and news protocols that could be reached by stretching the WinInet
classes a little more and using them to connect to the standard ports for these other
services. You could also connect to some well-known Web search engines and submit
queries by forming URLs according to the pattern used by those engines. In this way,
you could automate the sort of poking around on the Internet that most of us do when
we're curious about a domain name or an organization.</P>
<P>If you'd like to learn more about Internet protocols, port numbers, and what's
happening when a client connects to a server, you might want to read Que's <I>Building
Internet Applications with Visual C++.</I> The book was written for Visual C++ 2.0,
and though all the applications in the book compile and run under later versions
of MFC, the applications would be much shorter and easier to write now. Still, the
insight into the way the protocols work is valuable.</P>
<P>The WinInet classes, too, can do much more than you've seen here. Query doesn't
use them to retrieve real files over the Internet. Two of the WinInet sample applications
included with Visual C++ 6.0 do a fine job of showing how to retrieve files:</P>
<UL>
<LI>FTPTREE builds a tree list of the files and directories on an FTP site.
<P>
<LI>TEAR brings back a page of HTML from a Web site.
</UL>
<P>There are a lot more Microsoft announcements to come in the next few months. Keep
an eye on the Web site <B>www.microsoft.com</B> for libraries and software development
kits that will make Internet software development even easier and faster.</P>
<H1></H1>
<CENTER>
<P>
<HR>
<A HREF="../ch18/ch18.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch20/ch20.htm"><IMG
SRC="../button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"
BORDER="0"></A><A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> <BR>
</P>
<P>© <A HREF="../copy.htm">Copyright</A>, Macmillan Computer Publishing. All
rights reserved.
</CENTER>
</BODY>
</HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -