📄 306-309.html
字号:
<HTML>
<HEAD>
<META name=vsisbn content="1571690433"><META name=vstitle content="Black Art of Java Game Programming"><META name=vsauthor content="Joel Fan"><META name=vsimprint content="Sams"><META name=vspublisher content="Macmillan Computer Publishing"><META name=vspubdate content="11/01/96"><META name=vscategory content="Web and Software Development: Programming, Scripting, and Markup Languages: Java"><TITLE>Black Art of Java Game Programming:Implementing a High Score Server on a Network</TITLE>
<!-- HEADER --><STYLE type="text/css"> <!-- A:hover { color : Red; } --></STYLE><META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW"><script><!--function displayWindow(url, width, height) { var Win = window.open(url,"displayWindow",'width=' + width +',height=' + height + ',resizable=1,scrollbars=yes'); if (Win) { Win.focus(); }}//--></script><SCRIPT><!--function popUp(url) { var Win = window.open(url,"displayWindow",'width=400,height=300,resizable=1,scrollbars=yes'); if (Win) { Win.focus(); }}//--></SCRIPT><script language="JavaScript1.2"><!--function checkForQuery(fm) { /* get the query value */ var i = escape(fm.query.value); if (i == "") { alert('Please enter a search word or phrase'); return false; } /* query is blank, dont run the .jsp file */ else return true; /* execute the .jsp file */}//--></script></HEAD><BODY>
<TABLE border=0 cellspacing=0 cellpadding=0>
<tr>
<td width=75 valign=top>
<img src="../1571690433.gif" width=60 height=73 alt="Black Art of Java Game Programming" border="1">
</td>
<td align="left">
<font face="arial, helvetica" size="-1" color="#336633"><b>Black Art of Java Game Programming</b></font>
<br>
<font face="arial, helvetica" size="-1"><i>by Joel Fan</i>
<br>
Sams, Macmillan Computer Publishing
<br>
<b>ISBN:</b> 1571690433<b> Pub Date:</b> 11/01/96</font>
</td>
</tr>
</table>
<P>
<!--ISBN=1571690433//-->
<!--TITLE=Black Art of Java Game Programming//-->
<!--AUTHOR=Joel Fan//-->
<!--AUTHOR=Eric Ries//-->
<!--AUTHOR=Calin Tenitchi//-->
<!--PUBLISHER=Macmillan Computer Publishing//-->
<!--IMPRINT=Sams//-->
<!--CHAPTER=8//-->
<!--PAGES=306-309//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="304-306.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="309-311.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H4 ALIGN="LEFT"><A NAME="Heading45"></A><FONT COLOR="#000077">The HighScoreServer Class</FONT></H4>
<P>The HighScoreServer is not going to be a Java applet. Instead it is going to be a full-fledged application. Our server is not going to do anything graphics or multimedia oriented, because no user will ever see the server run. Instead of snazzy sounds and pictures, the server will print out status reports of what it is doing, so that it can be debugged easily. So, let’s get started.
</P>
<P>Here is the basic code for our Java application. Save it in a file called HighScoreServer.java:</P>
<!-- CODE //-->
<PRE>
import java.net.*;
import java.io.*;
import HighScoreList;
class HighScoreServer{
public static void main(String args[]) {
System.out.println("Hello from the server application.");
System.out.println("This does nothing, so let's quit.");
System.exit(1);
}
}
</PRE>
<!-- END CODE //-->
<P>The first thing you should notice is the method main(). Just like in C/C++, this is the method that is invoked as soon as the application starts running. Our simple beginning writes out a little message to the System.out PrintStream, and then exits. Not too impressive. In order to spice this up, we are going to give it some rudimentary networking abilities. However, we are not going to implement our protocol just yet; we’ll just write enough code to help you get the picture of how this works. Change main() so it looks like this:
</P>
<!-- CODE //-->
<PRE>
public static void main(String args[]) {
try {
servSock = new ServerSocket(2357);
} catch (Exception e) {
System.out.println("Tried to set up ServerSocket, but ⇐
failed");
System.exit(1);
}
Socket sock = null;
try {
sock = servSock.accept();
System.out.println("Got connection: "+2357);
DataInputStream dis = new DataInputStream(
new bufferedInputStream( sock.getInputStream() ));
PrintStream ps = new PrintStream(
new bufferedOutputStream(sock.getOutputStream(),1024),false);
} catch (Exception e) {
System.out.println("Could not get connection");
System.exit(1);
}
String inputLine;
while (!inputLine.startsWith("bye")) {
inputLine = dis.readLine();
System.out.println("Got: "+inputLine);
if(inputLine.startsWith("request"))
ps.println("none");
}
try {
os.close();
is.close();
sock.close();
} catch (Exception e);
System.exit(1);
}
</PRE>
<!-- END CODE //-->
<P>Does this code block make sense? It should, but a few things are new and some may be a bit fuzzy. The new class here is ServerSocket, which tries to listen to a specific port and then waits for a connection. The accept() method blocks until it gets a connection, and when it does, it returns a socket that we can read/write to.
</P>
<P>This is a good start, but still doesn’t do too much. Even worse, as soon as it is done servicing one connection, it quits! This is no good at all. The server should keep waiting for a connection until it is cleared from memory (when someone on the server machine “kills” the server process). Sound familiar? This is very similar to what the HighScoreManager had to do when it checked for scores, and we can solve this problem the same way we did that one: with a thread!</P>
<P>This time, we are going to create a thread that is a subclass of Thread, rather than use the Runnable interface. This is mainly because, later on, we are going to want to create another thread to run concurrently with this one. But don’t worry about that yet. It’s time to create a new class, the ServerThread class, that will handle all of the server-side networking.</P>
<H4 ALIGN="LEFT"><A NAME="Heading46"></A><FONT COLOR="#000077">The ServerThread Class</FONT></H4>
<P>This class is going to do all of the things our previous HighScoreServer did and more. It will implement our simple little protocol, and will actually deal with a HighScoreList. Here is all of the initial code to put in ServerThread.java:
</P>
<!-- CODE //-->
<PRE>
import java.net.*;
import java.lang.*;
import java.io.*;
import java.util.*;
import HighScoreList;
public class ServerThread extends Thread {
ServerSocket servSock = null; // The server object
long lastChange; // Track the last time a change was made
HighScoreList L; // The list of high scores
ServerThread() {
}
public void run() {
}
}
</PRE>
<!-- END CODE //-->
<P>Notice that there is no start() or stop() method. Since we don’t need these methods to do anything special, we can rely just on the default methods in the Thread class to call run() when needed. Let’s start by writing the initialization code for this class. We are going to have the HighScoreServer pass a list of scores. We will then manage it for the server.
</P>
<H4 ALIGN="LEFT"><A NAME="Heading47"></A><FONT COLOR="#000077">Server Initialization Routine</FONT></H4>
<P>Change the initialization routine to this:
</P>
<!-- CODE //-->
<PRE>
ServerThread(HighScoreList theList) {
try {
servSock = new ServerSocket(2357);
} catch (Exception e) {
System.out.println("Failed to initialize server");
System.exit(1);
}
L = theList;
}
</PRE>
<!-- END CODE //-->
<P>Does this make sense? It should. All we did was create a new ServerSocket on port 2357 and then accept the HighScoreList we were given. Because this is the same list used by the HighScoreServer, any changes we make to it will be felt by any threads of HighScoreServer that use the same HighScoreList. This will become very important later on. Before we go on to write the run() method, we should add a small but important method to this class. The finalize() method is called in objects just before they are terminated. Because our run() method might be tied up doing Socket communications, and the stop() method may never get called, we want to be absolutely sure that, if this thread dies, it closes the ServerSocket it opened. Otherwise, we might block off port 2357 forever.
</P>
<!-- CODE SNIP //-->
<PRE>
public void finalize() {
try {
servSock.close();
} catch(Exception e);
servSock = null;
}
</PRE>
<!-- END CODE SNIP //-->
<P>Here we make sure that not only is <I>servSock</I> closed, but it is dead, by setting it to <I>null</I>.</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="304-306.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="309-311.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -