The client socket examples in the previous chapter called the
getInputStream( )
and getOutputStream( )
methods. These examples do the same. The main difference
is that they get the socket from a
ServerSocket
’s accept( )
method, and that normally the server
creates or modifies the data and writes it to the client. Example 16-3 is a simple Echo
server,
which the Echo
client of Section 15.5 can connect to. This server handles one
complete connection with a client, then goes back and does the
accept( )
to wait for the
next client.
Example 16-3. EchoServer.java
/** * EchoServer - create server socket, do I-O on it. */ public class EchoServer { /** Our server-side rendezvous socket */ protected ServerSocket sock; /** The port number to use by default */ public final static int ECHOPORT = 7; /** Flag to control debugging */ protected boolean debug = true; /** main: construct and run */ public static void main(String[] argv) { new EchoServer(ECHOPORT).handle( ); } /** Construct an EchoServer on the given port number */ public EchoServer(int port) { try { sock = new ServerSocket(port); } catch (IOException e) { System.err.println("I/O error in setup"); System.err.println(e); System.exit(1); } } /** This handles the connections */ protected void handle( ) { Socket ios = null; BufferedReader is = null; PrintWriter os = null; while (true) { try { ios = sock.accept( ); System.err.println("Accepted from " + ios.getInetAddress().getHostName( )); is = new BufferedReader( new InputStreamReader(ios.getInputStream( ), "8859_1")); os = new PrintWriter( new OutputStreamWriter( ios.getOutputStream( ), "8859_1"), true); String echoLine; while ((echoLine = is.readLine( )) != null) { System.err.println("Read " + echoLine); os.print(echoLine + " "); System.err.println("Wrote " + echoLine); } System.err.println("All done!"); } catch (IOException e) { System.err.println(e); } finally { try { if (is != null) is.close( ); if (os != null) os.close( ); if (ios != null) ios.close( ); } catch (IOException e) { // These are unlikely, but might indicate that // the other end shut down early, a disk filled up // but wasn't detected until close, etc. System.err.println("IO Error in close"); } } } /*NOTREACHED*/ } }
To send a
string across an
arbitrary network connection, some authorities recommend sending both
the carriage return and the newline character. This explains the
in the code. The reason is that if the other
end is a DOS program or a Telnet-like program, it may be expecting
both characters. On the other hand, if you are writing both ends, you
can simply use println( )
, followed
always by an explicit flush( )
before
you read, to prevent the deadlock of having both ends trying to read
with one end’s data still in the
PrintWriter
’s buffer!
If you need to process binary data, use the data streams from
java.io
instead of the readers/writers. I need a
server for the DaytimeBinary
program of Section 15.6. In operation, it should look like the
following.
C:javasrc etwork>java DaytimeBinary Reme time is 3161316799 BASE_DIFF is 2209032000 Time diff == 952284799 Time on localhost is Sun Mar 05 19:33:19 GMT 2000 C:javasrc etwork>time Current time is 7:33:23.84p Enter new time: C:javasrc etwork>date Current date is Sun 03-05-2000 Enter new date (mm-dd-yy): C:javasrc etwork>
Well, it happens that I have such a program in my arsenal, so I present it in Example 16-4. Note that it directly uses certain public constants defined in the client class. Normally these are defined in the server class and used by the client, but I wanted to present the client code first.
Example 16-4. DaytimeServer.java (binary server protocol)
/** * DaytimeServer - send the binary time. */ public class DaytimeServer { /** Our server-side rendezvous socket */ ServerSocket sock; /** The port number to use by default */ public final static int PORT = 37; /** main: construct and run */ public static void main(String[] argv) { new DaytimeServer(PORT).runService( ); } /** Construct an EchoServer on the given port number */ public DaytimeServer(int port) { try { sock = new ServerSocket(port); } catch (IOException e) { System.err.println("I/O error in setup " + e); System.exit(1); } } /** This handles the connections */ protected void runService( ) { Socket ios = null; DataOutputStream os = null; while (true) { try { System.out.println("Waiting for connection on port " + PORT); ios = sock.accept( ); System.err.println("Accepted from " + ios.getInetAddress().getHostName( )); os = new DataOutputStream(ios.getOutputStream( )); long time = System.currentTimeMillis( ); time /= DaytimeBinary.MSEC; // Daytime Protocol is in seconds // Convert to Java time base. time += DaytimeBinary.BASE_DIFF; // Write it, truncating cast to int since it is using // the Internet Daytime protocol which uses 4 bytes. // This will fail in the year 2038, along with all // 32-bit timekeeping systems based from 1970. // Remember, you read about the Y2038 crisis here first! os.writeInt((int)time); os.close( ); } catch (IOException e) { System.err.println(e); } } } }
18.226.104.153