📄 728-732.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:The Internet MahJong Server</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=18//-->
<!--PAGES=728-732//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="724-728.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="732-735.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H3><A NAME="Heading14"></A><FONT COLOR="#000077">The Basic Server</FONT></H3>
<P>We are now ready to start writing the server, which is a Java application that runs forever. It’s always a good idea to write a simple version first. In this case, it only handles login, logout, communications, and joining and leaving tables. The packets needed for this task are summarized in Table 18-1. Client-to-server packets start with “CP” and vice versa with “SP”.
</P>
<TABLE WIDTH="100%"><CAPTION ALIGN=LEFT><B>Table 18-1</B> A basic list of packets
<TR>
<TH COLSPAN="3"><HR>
<TR>
<TH WIDTH="40%" ALIGN="LEFT">Packet Type
<TH WIDTH="20%" ALIGN="LEFT" VALIGN="BOTTOM">Fields
<TH WIDTH="40%" ALIGN="LEFT" VALIGN="BOTTOM">Description
<TR>
<TH COLSPAN="3"><HR>
<TR>
<TD>CP_LOGIN
<TD>name
<TD>Log in to the server.
<TR>
<TD>CP_QUIT
<TD>
<TD>Quit from the server.
<TR>
<TD VALIGN="TOP">CP_MESSAGE
<TD VALIGN="TOP">type, text
<TD>Sends a message, type is to server, all, or table.
<TR>
<TD VALIGN="TOP">CP_TABLE_JOIN
<TD VALIGN="TOP">id
<TD>Join or leave (id = -1) table.
<TR>
<TD VALIGN="TOP">CP_TABLE_SERVE
<TD VALIGN="TOP">options
<TD>Serve a new table (options reserved).
<TR>
<TD>SP_YOU_ARE
<TD>id
<TD>Your ID.
<TR>
<TD>SP_LOGIN
<TD>result
<TD>Your login result.
<TR>
<TD VALIGN="TOP">SP_JOIN
<TD VALIGN="TOP">id, name
<TD>Play logged in under this name.
<TR>
<TD>SP_LEAVE
<TD>id
<TD>Player quit.
<TR>
<TD VALIGN="TOP">SP_MESSAGE
<TD VALIGN="TOP">type, id, text
<TD>Player sends message, type is from server, all, or table.
<TR>
<TD VALIGN="TOP">SP_TABLE_OPT
<TD VALIGN="TOP">t, options
<TD>This table is open (options reserved).
<TR>
<TD VALIGN="TOP">SP_TABLE_PLAYER
<TD VALIGN="TOP">t, s, id
<TD>Player on this table in this seat, id = -1 means left table.
<TR>
<TD COLSPAN="3"><HR>
</TABLE>
<H4 ALIGN="LEFT"><A NAME="Heading15"></A><FONT COLOR="#000077">The Server Class</FONT></H4>
<P>The server class contains the main() method. Its job is to do some initialization, create a ServerSocket, and accept connections.
</P>
<!-- CODE //-->
<PRE>
package server;
import java.net.*;
import java.io.*;
class FullServerException extends Exception;
class Server {
public static void main (String args[]) {
ServerSocket main_sock = null;
try {
main_sock = new ServerSocket(5656); // default port
} catch (IOException e) {
System.out.println;
System.exit(1);
}
while (true) {
try {
Socket s = main_sock.accept(); // accept connection
DataInputStream i = new DataInputStream(s.getInputStream());
DataOutputStream o = new DataOutputStream(s.getOutputStream());
(new Player(s, i, o)).start(); // start thread
} catch (Exception e) {
System.out.println;
}
}
}
}
</PRE>
<!-- END CODE //-->
<H4 ALIGN="LEFT"><A NAME="Heading16"></A><FONT COLOR="#000077">The Player and PlayerOutput Classes</FONT></H4>
<P>We first group some information about a player into the Player class:
</P>
<!-- CODE //-->
<PRE>
package server;
import java.net.*;
import java.io.*;
class Player extends Thread {
public static Player[] global = new Player[100];
public int id = -1;
public String name = null;
private Socket sock;
private DataInputStream in;
private DataOutputStream out;
public boolean connected = true;
private PlayerOutput out_thread = null;
public Table table = null;
public int seat = -1;
}
</PRE>
<!-- END CODE //-->
<P>The above definition includes the player’s name, his socket connection, table and seat, and so on. There is a static array <I>global</I> that holds all the players on the server. Each player has a unique ID, which is an index into this array. To construct a new Player instance, we need to find an empty slot. Here it is important to use the <I>synchronized</I> statement on the array <I>global</I>, because our server will be a multithreaded program, and other threads may want to modify <I>global</I>, too. In case the server is full, we throw a FullServerException to inform our caller, Server.main().</P>
<!-- CODE //-->
<PRE>
public Player (Socket s, DataInputStream in, DataOutputStream out)
throws FullServerException {
synchronized (global) { // find a unique player id
for (int i = 0; i < global.length; i++) {
if (global[i] == null) {
id = i;
global[i] = this;
break;
}
}
}
if (id == -1) // all slots full
throw new FullServerException();
sock = s;
this.in = in;
this.out = out;
(out_thread = new PlayerOutput(this, out)).start();
output(Packet.SPYouAre(id)); // notify the player
}
</PRE>
<!-- END CODE //-->
<P>We need methods to send out packets. Player.output() sends a packet to a player. I will explain it in more detail soon. The static method outputAll() sends a packet to everyone on the server. It works by first acquiring the monitor associated with <I>global</I> and then calling every player’s output() method. We also need a disconnect() method, called when a player decides to quit (his client sends the server a CP_QUIT packet for this purpose) or when his network connection is somehow dead.</P>
<!-- CODE //-->
<PRE>
public void output (byte[] p) {
if (connected)
out_thread.output(p);
}
public static void outputAll (byte[] p) {
synchronized (global) { // critical section
for (int i = 0; i < global.length; i++) {
Player him = global[i];
// only send to players who have logged in
if (him != null && him.name != null)
him.output(p);
}
}
}
public synchronized void disconnect () {
if (id == -1) return; // we do it only once
connected = false;
if (table != null) // leave the table
table.leave(this);
synchronized (global) { // critical section
global[id] = null; // will GC eventually
}
try { // close the socket
in.close();
out.close();
sock.close();
} catch (IOException e) {
} if (name != null) // announce leave
outputAll(Packet.SPLeave(id));
id = -1; // we're done here
}
// ...
}
</PRE>
<!-- END CODE //-->
<P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="724-728.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="732-735.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -