Networking. Introduction In this chapter –Swing GUI component JEditorPane (view HTML docs)...

Preview:

Citation preview

Networking

Introduction

• In this chapter– Swing GUI component JEditorPane (view HTML docs)

– Socket-based communications• View networking like file I/O

– Stream sockets • When connection in place, data flows in continuous streams

• TCP protocol

• Preferred

Manipulating URLs

• Internet has many protocols– HTTP protocol

• Basis of World Wide Web

• Uses URLs to locate data

– Can represent files, directories, complex lookups

– Java can manipulate URLs easily

• Example Applet– Display list of web sites with JList

• Get parameters from HTML file

– Change to web site user selects

– Applet must be run in Explorer or Communicator (not appletviewer)

Manipulating URLs

– getParameter( name )• Returns parameter from HTML document

– Hashtable• Stores key/value pairs (method put)

60 title = getParameter( "title" + counter );

1 <APPLET CODE= "SiteSelector.class" WIDTH=300 HEIGHT=75>

2 <PARAM NAME="title0" VALUE="Java Home Page">

3 <PARAM NAME="location0" VALUE="http://java.sun.com/">

63 location = getParameter( "location" + counter );

66 url = new URL( location );

26 sites = new Hashtable();

67 sites.put( title, url );

Manipulating URLs

– ListSelectionListener• Method valueChanged (event handler)• getSelectedValue

– Returns selected item• Hashtable method get( key )

– Returns value as Object reference

– Cast to URL reference

36 siteChooser.addListSelectionListener(37 new ListSelectionListener() {38 public void valueChanged( ListSelectionEvent e )39 {40 Object o = siteChooser.getSelectedValue();41 URL newDocument = (URL) sites.get( o );42 AppletContext browser = getAppletContext();43 browser.showDocument( newDocument );44 }45 }

Manipulating URLs

– getAppletContext• Returns reference to AppletContext object

• Represents browser executing applet

– showDocument( URL )• Loads URL

36 siteChooser.addListSelectionListener(37 new ListSelectionListener() {38 public void valueChanged( ListSelectionEvent e )39 {40 Object o = siteChooser.getSelectedValue();41 URL newDocument = (URL) sites.get( o );42 AppletContext browser = getAppletContext();43 browser.showDocument( newDocument );44 }45 }

1. HTML file with parameters-------------------

1. import

1.1 Class SiteSelector (extends JApplet)

1.2 Hashtable

1 <APPLET CODE= "SiteSelector.class" WIDTH=300 HEIGHT=75>

2 <PARAM NAME="title0" VALUE="Java Home Page">

3 <PARAM NAME="location0" VALUE="http://java.sun.com/">

4 <PARAM NAME="title1" VALUE="Deitel">

5 <PARAM NAME="location1" VALUE="http://www.deitel.com/">

6 <PARAM NAME="title2" VALUE="Gamelan">

7 <PARAM NAME="location2" VALUE="http://www.gamelan.com/">

8 <PARAM NAME="title3" VALUE="JavaWorld">

9 <PARAM NAME="location3" VALUE="http://www.javaworld.com/">

10 </APPLET>

11 // Fig. 21.1: SiteSelector.java

12 // This program uses a button to load a document from a URL.

13 import java.net.*;

14 import java.util.*;

15 import javax.swing.*;

16 import javax.swing.event.*;

17 import java.awt.*;

18 import java.applet.AppletContext;

19

20 public class SiteSelector extends JApplet {

21 private Hashtable sites;

22 private Vector siteNames;

23

24 public void init()

25 {

2626 sites = new Hashtable();

27 siteNames = new Vector();

28

29 getSitesFromHTMLParameters();

Hashtables store key/value pairs (more chapter 23).

1.3 GUI

1.4 Event handler

1.5 getSelectedValue

1.6 get

1.7 getAppletContext

1.8 showDocument

2. getSitesFromHTML Parameters

34

35 final JList siteChooser = new JList( siteNames );

36 siteChooser.addListSelectionListener(

37 new ListSelectionListener() {

38 public void valueChanged( ListSelectionEvent e )

39 {

4040 Object o = siteChooser.getSelectedValue();

41 URL newDocument = (URL) sites.get( o );

42 AppletContext browser = getAppletContext();

43 browser.showDocument( newDocument );

44 }

45 }

46 );

47 c.add( new JScrollPane( siteChooser ),

48 BorderLayout.CENTER );

49 }

50

51 private void getSitesFromHTMLParameters()

52 {

53 // look for applet parameters in the HTML document

54 // and add sites to Hashtable

55 String title, location;

56 URL url;

57 int counter = 0;

58

30

31 Container c = getContentPane();

32 c.add( new JLabel( "Choose a site to browse" ),

33 BorderLayout.NORTH );

Get selected site, cast to URL. Display in browser.

2.1 getParameter

2.2 put6767 sites.put( title, url );

68 siteNames.addElement( title );

69 }

70 catch ( MalformedURLException e ) {

71 e.printStackTrace();

72 }

73 }

74 else

75 break;

76

77 ++counter;

78 }

79 }

80 }

59 while ( true ) {

60 title = getParameter( "title" + counter );

6162 if ( title != null ) {

63 location = getParameter( "location" + counter );

64 65 try {

66 url = new URL( location );

Add key/value pair to hashtable.

Reading a File on a Web Server

• Reading files from a web server– JEditorPane (javax.swing)

• Can display text and HTML

– Applets can only read files from original server

Reading a File on a Web Server

– JEditorPane• Method setPage( locationString )

– Download and display page

– Hyperlinks• Text, images, GUI components that access another document

on web

• Generates HyperLinkEvent, notifies HyperLinkListeners

58 contents.setPage( location );

32 contents = new JEditorPane();

33 contents.setEditable( false );34 contents.addHyperlinkListener(35 new HyperlinkListener() {36 public void hyperlinkUpdate( HyperlinkEvent e )

Reading a File on a Web Server

– Method getEventType• Inner class EventType has three types

– ACTIVATED - clicked– ENTERED - mouse over hyperlink– EXITED - mouse leaves hyperlink

– Method getURL - returns URL of link

36 public void hyperlinkUpdate( HyperlinkEvent e )

37 {

38 if ( e.getEventType() ==

39 HyperlinkEvent.EventType.ACTIVATED )

40 getThePage( e.getURL().toString() );

41 }

Reading a File on a Web Server

– setCursor( Cursor ) (inherited by JFrame)• Sets mouse cursor

– static method getPredefinedCursor( int cursorType )

• Returns Cursor• cursorType

– Cursor.WAIT_CURSOR– Cursor.DEFAULT_CURSOR

54 setCursor( Cursor.getPredefinedCursor(

55 Cursor.WAIT_CURSOR ) );

68 setCursor( Cursor.getPredefinedCursor(

69 Cursor.DEFAULT_CURSOR ) );

1. import

1.1 extends JFrame

1.2 Constructor

1 // Fig. 21.2: ReadServerFile.java

2 // This program uses a JEditorPane to display the

3 // contents of a file on a Web server.

4 import java.awt.*;

5 import java.awt.event.*;

6 import java.net.*;

7 import java.io.*;

8 import javax.swing.*;

9 import javax.swing.event.*;

10

1111 public class ReadServerFile extends JFrame {

12 private JTextField enter;

13 private JEditorPane contents;

14

15 public ReadServerFile()

16 {

17 super( "Simple Web Browser" );

18

19 Container c = getContentPane();

20

21 enter = new JTextField( "Enter file URL here" );

22 enter.addActionListener(

23 new ActionListener() {

24 public void actionPerformed( ActionEvent e )

25 {

26 getThePage( e.getActionCommand() );

27 }

28 }

29 );

JFrame inherits setCursor method, which our class can now use.

7800

1.3 JEditorPane

1.4 addHyperLink Listener

2. Method getThePage

2.1 setCursor

2.2 setPage

34 contents.addHyperlinkListener(35 new HyperlinkListener() {36 public void hyperlinkUpdate( HyperlinkEvent e )37 {38 if ( e.getEventType() ==3939 HyperlinkEvent.EventType.ACTIVATED )4040 getThePage( e.getURL().toString() );41 }42 }43 );4445 c.add( new JScrollPane( contents ),46 BorderLayout.CENTER );4748 setSize( 400, 300 );49 show();50 }5152 private void getThePage( String location )53 {5454 setCursor( Cursor.getPredefinedCursor(55 Cursor.WAIT_CURSOR ) );5657 try {5858 contents.setPage( location );59 enter.setText( location );60 }

30 c.add( enter, BorderLayout.NORTH );

31

3232 contents = new JEditorPane();

33 contents.setEditable( false );

Create JEditorPane, register event handler (HyperLinkEvents).

Get the URL of hyperlink, call utility method getThePage.

Make sure user clicked hyperlink (ACTIVATED).

Change cursor to a waiting state (downloading file).

Display new page in JEditorPane.

3. main

67

68 setCursor( Cursor.getPredefinedCursor(

69 Cursor.DEFAULT_CURSOR ) );

70 }

71

72 public static void main( String args[] )

73 {

74 ReadServerFile app = new ReadServerFile();

75

76 app.addWindowListener(

77 new WindowAdapter() {

78 public void windowClosing( WindowEvent e )

79 {

80 System.exit( 0 );

81 }

82 }

83 );

84 }

85 }

61 catch ( IOException io ) {62 JOptionPane.showMessageDialog( this,63 "Error retrieving specified URL",64 "Bad URL",65 JOptionPane.ERROR_MESSAGE );66 }

Program Output

Program Output

Establishing a Simple Server (Using Stream Sockets)

• Creating a Java server– Create ServerSocket object

ServerSocket s = new ServerSocket( port, queueLength );

• Register port number and set max number of waiting clients

• Binds server to port, waits for clients

– Server listens indefinitely (blocks) for clients

Socket connection = s.accept()• Connections managed by Socket objects

• Returns Socket when connection established

Establishing a Simple Client (Using Stream Sockets)

• Creating a Java server– Get I/O objects for communication

• OutputStream - sends info to client• InputStream - gets info from client

• Server's input stream is client's output stream, and vice versa

– Use Socket object to get references to streams• connection.getInputStream()• connection.getOutputStream()

– Methods write and read• Send individual bytes

Establishing a Simple Client (Using Stream Sockets)

• Creating a Java server– Chaining stream types (sending objects and data, not bytes)ObjectInputStream input = new ObjectInputStream( connection.getInputStream() )

– Processing phase• Server/client communicate using InputStream and OutputStream

– Termination• Transmission complete

• Method close (of Socket)

connection.close()

– Networking appears as sequential file I/O• Sockets simplify networking

Establishing a Simple Client (Using Stream Sockets)

• Creating a Java client– Create Socket to connect to server

Socket connection = new Socket( serverAddress, port )

• If successful, returns Socket– Else throws subclass of IOException

– Get stream objects• connection.getInputStream()• connection.getOutputStream()• Use chaining if transmitting objects and data, not pure bytes

– ObjectInputStream, ObjectOutputStream

Establishing a Simple Client (Using Stream Sockets)

• Creating a Java client– Processing phase

• Communicate using stream objects

– Termination• Transmission complete• connection.close() (close Socket)

– Client must determine when server done• read returns -1 when eof found• ObjectInputStream generates EOFException

Client/Server Interaction with Stream Socket Connections

• Upcoming program– Simple client/server chat application

– Use stream sockets

– Client connects, transmit String objects• do-while loop to get input

• Event handler calls sendData method to send output

– When either sends TERMINATE, connection terminates• Server waits for next client

– GUI:

Client/Server Interaction with Stream Socket Connections

• Server

– Once connection (Socket) established• getInetAddress() - returns InetAddress object• getHostName() - returns client's host name

– Create ObjectOutputStream• flush()

– Sends stream header to client

– Required by client's ObjectInputStream

63 output = new ObjectOutputStream(64 connection.getOutputStream() );65 output.flush();

60 connection.getInetAddress().getHostName() );

Client/Server Interaction with Stream Socket Connections

– Send/receive data• Method sendData called by event handler

• Buffer flushed after every transmission

– Sets cursor position to end of text• Allows JTextArea to scroll with text

– Server processes single connection at a time• More likely to have separate threads for each connection

108 private void sendData( String s )109 {111 output.writeObject( "SERVER>>> " + s );112 output.flush();113 display.append( "\nSERVER>>>" + s );

81 display.setCaretPosition(

82 display.getText().length() );

1. Constructor

1.1 GUI components

1 // Fig. 21.3: Server.java

2 // Set up a Server that will receive a connection

3 // from a client, send a string to the client,

4 // and close the connection.

5 import java.io.*;

6 import java.net.*;

7 import java.awt.*;

8 import java.awt.event.*;

9 import javax.swing.*;

10

11 public class Server extends JFrame {

12 private JTextField enter;

13 private JTextArea display;

14 ObjectOutputStream output;

15 ObjectInputStream input;

16

17 public Server()

18 {

19 super( "Server" );

20

21 Container c = getContentPane();

22

23 enter = new JTextField();

24 enter.setEnabled( false );

1.2 Event handler

1.3 GUI

2. Method runServer

2.1 ServerSocket

34

35 display = new JTextArea();

36 c.add( new JScrollPane( display ),

37 BorderLayout.CENTER );

38

39 setSize( 300, 150 );

40 show();

41 }

42

43 public void runServer()

44 {

45 ServerSocket server;

46 Socket connection;

47 int counter = 1;

48

49 try {

50 // Step 1: Create a ServerSocket.

5151 server = new ServerSocket( 5000, 100 );

52

25 enter.addActionListener(

26 new ActionListener() {

27 public void actionPerformed( ActionEvent e )

28 {

2929 sendData( e.getActionCommand() );

30 }

31 }

32 );

33 c.add( enter, BorderLayout.NORTH );

The event handlers calls method sendData, using text in JTextField as argument.

Register port 5000, server will allow 100 clients to wait in queue.

2.2 accept

2.3 getHostName

2.4 Get streams

2.5 writeObject

2.6 Loop

67 connection.getInputStream() );68 display.append( "\nGot I/O streams\n" );69 70 // Step 4: Process connection.71 String message =72 "SERVER>>> Connection successful";73 output.writeObject( message );74 output.flush();75 enter.setEnabled( true );767777 do {78 try {79 message = (String) input.readObject();80 display.append( "\n" + message );81 display.setCaretPosition(82 display.getText().length() );83 }

5353 while ( true ) {54 // Step 2: Wait for a connection.55 display.setText( "Waiting for connection\n" );5656 connection = server.accept();57 58 display.append( "Connection " + counter +59 " received from: " +6060 connection.getInetAddress().getHostName() );6162 // Step 3: Get input and output streams.6363 output = new ObjectOutputStream(64 connection.getOutputStream() );65 output.flush();66 input = new ObjectInputStream(

Infinite loop to wait for connections from clients.

Wait for connection (server.accept() waits indefinitely).

Display host location.

Set up I/O streams, flush buffer (sends stream data). Send confirmation message.

Loop to get input. Set cursor to end of text.

2.6 Loop

2.7 close

3. Method sendData

3.1 writeObject

3.2 flush100 catch ( EOFException eof ) {101 System.out.println( "Client terminated connection" );102 }103 catch ( IOException io ) {104 io.printStackTrace();105 }106 }107108 private void sendData( String s )109 {110 try {111111 output.writeObject( "SERVER>>> " + s );112 output.flush();113 display.append( "\nSERVER>>>" + s );114 }

84 catch ( ClassNotFoundException cnfex ) {85 display.append(86 "\nUnknown object type received" );87 }8888 } while ( !message.equals( "CLIENT>>> TERMINATE" ) );8990 // Step 5: Close connection.91 display.append( "\nUser terminated connection" );92 enter.setEnabled( false );9393 output.close();94 input.close();95 connection.close();9697 ++counter;98 }99 }

Loop until TERMINATE string sent.

Close connection and I/O streams.

Send String object to client. Flush buffer to ensure it is sent, and update server's display.

4. main

133

134 app.runServer();

135 }

136}

115 catch ( IOException cnfex ) {

116 display.append(

117 "\nError writing object" );

118 }

119 }

120

121 public static void main( String args[] )

122 {

123 Server app = new Server();

124

125 app.addWindowListener(

126 new WindowAdapter() {

127 public void windowClosing( WindowEvent e )

128 {

129 System.exit( 0 );

130 }

131 }

132 );

Client/Server Interaction with Stream Socket Connections

• Client– Similar to server

– Creates same GUI

– Loops to wait for input• Sends output through event handler and sendData

Client/Server Interaction with Stream Socket Connections

– Create Socket with two arguments• Internet address of server and port number

– static method getByName (Class InetAddress)• Returns InetAddress object

• Takes String• Could have taken "localhost" or called static method getLocalHost

– Create I/O objects as before• Output of server is input of client

50 client = new Socket(

51 InetAddress.getByName( "127.0.0.1" ), 5000 );

1. Constructor

1.1 GUI

1 // Fig. 21.4: Client.java

2 // Set up a Client that will read information sent

3 // from a Server and display the information.

4 import java.io.*;

5 import java.net.*;

6 import java.awt.*;

7 import java.awt.event.*;

8 import javax.swing.*;

9

10 public class Client extends JFrame {

11 private JTextField enter;

12 private JTextArea display;

13 ObjectOutputStream output;

14 ObjectInputStream input;

15 String message = "";

16

17 public Client()

18 {

19 super( "Client" );

20

21 Container c = getContentPane();

22

23 enter = new JTextField();

24 enter.setEnabled( false );

1.2 Event handler

1.3 GUI

2. Method runClient

2.1 Socket

3435 display = new JTextArea();36 c.add( new JScrollPane( display ),37 BorderLayout.CENTER );3839 setSize( 300, 150 );40 show();41 }4243 public void runClient() 44 {45 Socket client;4647 try {48 // Step 1: Create a Socket to make connection.49 display.setText( "Attempting connection\n" );50 client = new Socket( 51 InetAddress.getByName( "127.0.0.1" ), 5000 );52535455

25 enter.addActionListener(26 new ActionListener() {27 public void actionPerformed( ActionEvent e )28 {2929 sendData( e.getActionCommand() );30 }31 }32 );33 c.add( enter, BorderLayout.NORTH );

Client gets text from JTextField and calls sendData.

Create Socket to server, make connection.

2.2 I/O streams

2.3 flush

2.4 Loop

67 // Step 3: Process connection.

68 enter.setEnabled( true );

69

70 do {

71 try {

72 message = (String) input.readObject();

73 display.append( "\n" + message );

74 display.setCaretPosition(

75 display.getText().length() );

76 }

77 catch ( ClassNotFoundException cnfex ) {

78 display.append(

79 "\nUnknown object type received" );

80 }

81 } while ( !message.equals( "SERVER>>> TERMINATE" ) );

82

56 display.append( "Connected to: " +

57 client.getInetAddress().getHostName() );

58

59 // Step 2: Get the input and output streams.

60 output = new ObjectOutputStream(

61 client.getOutputStream() );

6262 output.flush();

63 input = new ObjectInputStream(

64 client.getInputStream() );

65 display.append( "\nGot I/O streams\n" );

66

Code similar to server. Create I/O objects, flush buffer, loop to wait for and process input.

2.5 close

3. Method sendData

100 message = s;

101 output.writeObject( "CLIENT>>> " + s );

102 output.flush();

103 display.append( "\nCLIENT>>>" + s );

104 }

105 catch ( IOException cnfex ) {

106 display.append(

107 "\nError writing object" );

108 }

109 }

110

83 // Step 4: Close connection.84 display.append( "Closing connection.\n" );85 input.close();86 output.close();87 client.close();88 }89 catch ( EOFException eof ) {90 System.out.println( "Server terminated connection" );91 }92 catch ( IOException e ) {93 e.printStackTrace();94 }95 }9697 private void sendData( String s )98 {99 try {

4. main

Program Output

111 public static void main( String args[] )

112 {

113 Client app = new Client();

114

115 app.addWindowListener(

116 new WindowAdapter() {

117 public void windowClosing( WindowEvent e )

118 {

119 System.exit( 0 );

120 }

121 }

122 );

123

124 app.runClient();

125 }

126}

127

ProgramOutput

Connectionless Client/Server Interaction with Datagrams

• Connection-oriented interaction– Like phone call

• Have connection to other end

• Connection maintained for duration of call, even if not talking

• Connectionless interaction– Like sending postal mail

– Use datagrams, packets of data

– If large packet, break into smaller pieces• Send separately

• May arrive out of order or not arrive at all

• Duplicates may arrive

Connectionless Client/Server Interaction with Datagrams

– DatagramSocket( port )• Binds server to port

– DatagramPacket( byteArray, byteArray.length )

• Create DatagramPacket to store received packet• byteArray stores data

– Method receive( packetToStore )• Blocks until packet arrives, stores in packetToStore

27 socket = new DatagramSocket( 5000 );

40 byte data[] = new byte[ 100 ];

41 receivePacket =

42 new DatagramPacket( data, data.length );

45 socket.receive( receivePacket );

Connectionless Client/Server Interaction with Datagrams

– getAddress - returns InetAddress– getPort, getLength - return integers– getData - returns byte array

• Used in String constructor to create string

48 display.append( "\nPacket received:" +49 "\nFrom host: " + receivePacket.getAddress() +50 "\nHost port: " + receivePacket.getPort() +51 "\nLength: " + receivePacket.getLength() +52 "\nContaining:\n\t" +53 new String( receivePacket.getData(), 0,54 receivePacket.getLength() ) );

Connectionless Client/Server Interaction with Datagrams

– Echo packet back to client• DatagramPacket( byteArray, length, InetAddress, port )

• Method send( packetToSend )

58 sendPacket =

59 new DatagramPacket( receivePacket.getData(),60 receivePacket.getLength(),

62 receivePacket.getPort() );

63 socket.send( sendPacket );

61 receivePacket.getAddress(),

1. Declarations

1.1 DatagramSocket

1 // Fig. 21.5: Server.java

2 // Set up a Server that will receive packets from a

3 // client and send packets to a client.

4 import java.io.*;

5 import java.net.*;

6 import java.awt.*;

7 import java.awt.event.*;

8 import javax.swing.*;

9

10 public class Server extends JFrame {

11 private JTextArea display;

12

13 private DatagramPacket sendPacket, receivePacket;

14 private DatagramSocket socket;

15

16 public Server()

17 {

18 super( "Server" );

19

20 display = new JTextArea();

21 getContentPane().add( new JScrollPane( display),

22 BorderLayout.CENTER );

23 setSize( 400, 300 );

24 show();

25

26 try {

27 socket = new DatagramSocket( 5000 );

28 }

Create new DatagramSocket, binds server to port.

2. Method waitForPackets

2.1 receivePacket

2.2 receive

2.3 Process packet

2.4 Echo packet

3435 public void waitForPackets()36 {3737 while ( true ) {38 try {39 // set up packet40 byte data[] = new byte[ 100 ];41 receivePacket =4242 new DatagramPacket( data, data.length );4344 // wait for packet45 socket.receive( receivePacket );46 47 // process packet48 display.append( "\nPacket received:" +49 "\nFrom host: " + receivePacket.getAddress() +50 "\nHost port: " + receivePacket.getPort() +51 "\nLength: " + receivePacket.getLength() +52 "\nContaining:\n\t" +5353 new String( receivePacket.getData(), 0,54 receivePacket.getLength() ) );5556 // echo information from packet back to client57 display.append( "\n\nEcho data to client...");

29 catch( SocketException se ) {30 se.printStackTrace();31 System.exit( 1 );32 }33 }

5858 sendPacket =59 new DatagramPacket( receivePacket.getData(),

Create new DatagramPacket to receive info.

Gather and display packet data. Convert byte array to a String.

Create packet back to client.

Loop to wait for packets.

2.5 send

3. main67 }68 catch( IOException io ) {69 display.append( io.toString() + "\n" );70 io.printStackTrace();71 }72 }73 }7475 public static void main( String args[] )76 {77 Server app = new Server();7879 app.addWindowListener(80 new WindowAdapter() {81 public void windowClosing( WindowEvent e )82 {83 System.exit( 0 );84 }85 }86 );8788 app.waitForPackets();89 }90 }

60 receivePacket.getLength(),

61 receivePacket.getAddress(),

62 receivePacket.getPort() );

6363 socket.send( sendPacket );

64 display.append( "Packet sent\n" );

65 display.setCaretPosition(

66 display.getText().length() );

Send packet back to client.

Program Output

Connectionless Client/Server Interaction with Datagrams

• Client– Similar to server

– Has JTextField• Sends packets with event handler for JTextField• Convert String to byteArray

– String.getBytes()

– Have loop to receive echoed packets from server

– Constructor needs no arguments• Uses next available port

• Server gets client's port number as part of DatagramPacket

31 socket = new DatagramSocket();

1. Constructor

1.1 GUI

1.2 Register event handler

1 // Fig. 21.6: Client.java

2 // Set up a Client that will send packets to a

3 // server and receive packets from a server.

4 import java.io.*;

5 import java.net.*;

6 import java.awt.*;

7 import java.awt.event.*;

8 import javax.swing.*;

9

10 public class Client extends JFrame implements ActionListener {

11 private JTextField enter;

12 private JTextArea display;

13

14 private DatagramPacket sendPacket, receivePacket;

15 private DatagramSocket socket;

16

17 public Client()

18 {

19 super( "Client" );

20

21 enter = new JTextField( "Type message here" );

22 enter.addActionListener( this );

23 getContentPane().add( enter, BorderLayout.NORTH );

24 display = new JTextArea();

25 getContentPane().add( new JScrollPane( display ),

26 BorderLayout.CENTER );

27 setSize( 400, 300 );

28 show();

29

1.3 DatagramSocket

2. waitForPackets

2.1 DatagramPacket

2.2 receive

2.3 Process packet

34 se.printStackTrace();

35 System.exit( 1 );

36 }

37 }

38

39 public void waitForPackets()

40 {

4141 while ( true ) {

42 try {

43 // set up packet

44 byte data[] = new byte[ 100 ];

45 receivePacket =

46 new DatagramPacket( data, data.length );

47

48 // wait for packet

49 socket.receive( receivePacket );

50

51 // process packet

52 display.append( "\nPacket received:" +

53 "\nFrom host: " + receivePacket.getAddress() +

54 "\nHost port: " + receivePacket.getPort() +

55 "\nLength: " + receivePacket.getLength() +

56 "\nContaining:\n\t" +

57 new String( receivePacket.getData(), 0,

58 receivePacket.getLength() ) );

30 try {

3131 socket = new DatagramSocket();

32 }

33 catch( SocketException se ) {

No argument constructor.

Similar to server, loop to receive echoed packets.

3. actionPerformed

3.1 Create packet

3.2 send

67 }6869 public void actionPerformed( ActionEvent e )70 {71 try {72 display.append( "\nSending packet containing: " +73 e.getActionCommand() + "\n" );7475 String s = e.getActionCommand();7676 byte data[] = s.getBytes();7778 sendPacket = new DatagramPacket( data, data.length,79 InetAddress.getLocalHost(), 5000 );80 socket.send( sendPacket );81 display.append( "Packet sent\n" );82 display.setCaretPosition(83 display.getText().length() );8485 }86 catch ( IOException exception ) {87 display.append( exception.toString() + "\n" );88 exception.printStackTrace();89 }90 }

59 display.setCaretPosition(60 display.getText().length() );61 }62 catch( IOException exception ) {63 display.append( exception.toString() + "\n" );64 exception.printStackTrace();65 }66 }

Convert String to a byte array, use to initialize DatagramPacket.

Program Output

100 System.exit( 0 );

101 }

102 }

103 );

104

105 app.waitForPackets();

106 }

107}

91

92 public static void main( String args[] )

93 {

94 Client app = new Client();

95

96 app.addWindowListener(

97 new WindowAdapter() {

98 public void windowClosing( WindowEvent e )

99 {

Client/Server Tic-Tac-Toe Using a Multithreaded Server

• Tic-Tac-Toe – Create application allowing two clients to connect to server

• When each client connects– Player object created in separate thread

– Manages connection

– Server maintains board information• Byte array represents board

• Determines if moves are valid

– Each client has own GUI• Has board information

Client/Server Tic-Tac-Toe Using a Multithreaded Server

– Server creates ServerSocket• Waits for two connections, creates two Player objects

– Initialize Player objects• Connection to respective client, reference to server, number

50 for ( int i = 0; i < players.length; i++ ) {52 players[ i ] =

53 new Player( server.accept(), this, i );

54 players[ i ].start();

29 server = new ServerSocket( 5000, 2 );

152 connection = s;

139class Player extends Thread {

148 public Player( Socket s, TicTacToeServer t, int num )

165 control = t;

166 number = num;

Client/Server Tic-Tac-Toe Using a Multithreaded Server

– Update server (display) and send client their mark (X or O)

– Suspend Player X

• Notify Player X after Player O connects• Code comes after loop to initialize both Players

183 control.display( "Player " +

184 ( number == 0 ? 'X' : 'O' ) + " connected" );

185 output.writeChar( mark );

197 while ( threadSuspended )

198 wait();

178 public void run()

192 if ( mark == 'X' ) {

196 synchronized( this ) {

64 synchronized ( players[ 0 ] ) {

65 players[ 0 ].threadSuspended = false;

66 players[ 0 ].notify();

Client/Server Tic-Tac-Toe Using a Multithreaded Server

• Game begins playing– run method executes while loop

– Read integer representing move from client• Test if valid (control.validMove)

• If so, send message to server and client

210 while ( !done ) {

211 int location = input.readInt();

213 if ( control.validMove( location, number ) ) {214 control.display( "loc: " + location );

215 output.writeUTF( "Valid move." );

Client/Server Tic-Tac-Toe Using a Multithreaded Server

– Method validMove• synchronized - one move at a time

– If player not currentPlayer, put in wait state• When other player moves, notify

79 public synchronized boolean validMove( int loc,

80 int player )

86 while ( player != currentPlayer ) {

88 wait();

Client/Server Tic-Tac-Toe Using a Multithreaded Server

– Checks if location occupied• If not, updates byte array, currentPlayer• otherPlayerMoved - informs other client of move

• Notify waiting client

• Return true (valid move)

100 notify(); // tell waiting player to continue

101 return true;

95 if ( !isOccupied( loc ) ) {

96 board[ loc ] =

97 (byte) ( currentPlayer == 0 ? 'X' : 'O' );

98 currentPlayer = ( currentPlayer + 1 ) % 2;

99 players[ currentPlayer ].otherPlayerMoved( loc );

1. Constructor

1.1 Initialization

1.2 ServerSocket

1 // Fig. 21.7: TicTacToeServer.java2 // This class maintains a game of Tic-Tac-Toe for two3 // client applets.4 import java.awt.*;5 import java.awt.event.*;6 import java.net.*;7 import java.io.*;8 import javax.swing.*;910 public class TicTacToeServer extends JFrame {11 private byte board[];12 private boolean xMove;13 private JTextArea output;14 private Player players[];15 private ServerSocket server;16 private int currentPlayer;1718 public TicTacToeServer()19 {20 super( "Tic-Tac-Toe Server" );21

2222 board = new byte[ 9 ];23 xMove = true;24 players = new Player[ 2 ];25 currentPlayer = 0;26 27 // set up ServerSocket28 try {

2929 server = new ServerSocket( 5000, 2 );30 }

Server creates ServerSocket to get connections.

Use nine element byte array to represent board. Create Player array.

1.3 GUI

2. Method execute

2.1 Initialize players

34 catch( IOException e ) {35 e.printStackTrace();36 System.exit( 1 );37 }3839 output = new JTextArea();40 getContentPane().add( output, BorderLayout.CENTER );41 output.setText( "Server awaiting connections\n" );4243 setSize( 300, 300 );44 show();45 }4647 // wait for two connections so game can be played48 public void execute()49 {50 for ( int i = 0; i < players.length; i++ ) {51 try {52 players[ i ] =

5353 new Player( server.accept(), this, i );54 players[ i ].start();55 }56 catch( IOException e ) {57 e.printStackTrace();58 System.exit( 1 );59 }60 }

313233

Initialize Player objects with client connection. Player X begins in wait state.

2.2 notify player X

3. Method display

4. Method validMove (synchronized)

67 }

68

69 }

70

71 public void display( String s )

72 {

73 output.append( s + "\n" );

74 }

75

76 // Determine if a move is valid.

77 // This method is synchronized because only one move can be

78 // made at a time.

79 public synchronized boolean validMove( int loc,

80 int player )

81 {

82 boolean moveDone = false;

83

84

85

86 while ( player != currentPlayer ) {

87 try {

88 wait();

89 }

61

62 // Player X is suspended until Player O connects.

63 // Resume player X now.

64 synchronized ( players[ 0 ] ) {

65 players[ 0 ].threadSuspended = false;

6666 players[ 0 ].notify();

Notify player X to resume execution.

Allow only one move at a time.

If player is not the current player, send to wait state.

4.1 Update information

5. isOccupied

6. gameOver100 notify(); // tell waiting player to continue101 return true;

102 }103 else

104 return false;105 }106

107 public boolean isOccupied( int loc )108 {

109 if ( board[ loc ] == 'X' || board [ loc ] == 'O' )110 return true;111 else

112 return false;113 }

114115 public boolean gameOver()116 {117 // Place code here to test for a winner of the game118 return false;

119 }

90 catch( InterruptedException e ) {91 e.printStackTrace();

92 }93 }

9495 if ( !isOccupied( loc ) ) {96 board[ loc ] =

97 (byte) ( currentPlayer == 0 ? 'X' : 'O' );98 currentPlayer = ( currentPlayer + 1 ) % 2;

99 players[ currentPlayer ].otherPlayerMoved( loc );

If location unoccupied, update current player, inform other player of move, board, and notify waiting players.

7. main

8. Class Player

133 game.execute();

134 }

135}

136

137

138// Player class to manage each Player as a thread

139class Player extends Thread {

140 private Socket connection;

141 private DataInputStream input;

142 private DataOutputStream output;

143 private TicTacToeServer control;

144 private int number;

145 private char mark;

146 protected boolean threadSuspended = true;

147

120

121 public static void main( String args[] )

122 {

123 TicTacToeServer game = new TicTacToeServer();

124

125 game.addWindowListener( new WindowAdapter() {

126 public void windowClosing( WindowEvent e )

127 {

128 System.exit( 0 );

129 }

130 }

131 );

132

8.1 Constructor

8.2 I/O streams

8.3 otherPlayerMoved

165 control = t;166 number = num;167 }168169 public void otherPlayerMoved( int loc )170 {171 try {

172172 output.writeUTF( "Opponent moved" );173 output.writeInt( loc );174 }175 catch ( IOException e ) { e.printStackTrace(); }176 }177

148148 public Player( Socket s, TicTacToeServer t, int num )149 {150 mark = ( num == 0 ? 'X' : 'O' );151152 connection = s;153 154 try {155 input = new DataInputStream(156 connection.getInputStream() );157 output = new DataOutputStream(158 connection.getOutputStream() );159 }160 catch( IOException e ) {161 e.printStackTrace();162 System.exit( 1 );163 }164

Initialize with client connection, reference to server object, and player number.

Inform Player of other's move.

8.4 run

8.4.1 Inform server

8.4.2 Send mark

8.4.3 Player X waits

197 while ( threadSuspended )198 wait();

199 }200 } 201 catch ( InterruptedException e ) {202 e.printStackTrace();

203 }204205 output.writeUTF(206 "Other player connected. Your move." );

207 }208

178 public void run()179 {180 boolean done = false;181182 try {183183 control.display( "Player " +184 ( number == 0 ? 'X' : 'O' ) + " connected" );185 output.writeChar( mark );186 output.writeUTF( "Player " +187 ( number == 0 ? "X connected\n" :188 "O connected, please wait\n" ) );189190191 // wait for another player to arrive192 if ( mark == 'X' ) {193 output.writeUTF( "Waiting for another player" );194195 try {196196 synchronized( this ) {

Server displays connected client. Mark (X or O) sent to client.

Player X waits (so Player O can connect). Once Player O connects, X can move.

8.5 Loop for input

8.6 validMove

227 e.printStackTrace();

228 System.exit( 1 );

229 }

230 }

231}

209 // Play game

210 while ( !done ) {

211 int location = input.readInt();

212

213213 if ( control.validMove( location, number ) ) {

214 control.display( "loc: " + location );

215 output.writeUTF( "Valid move." );

216 }

217 else

218 output.writeUTF( "Invalid move, try again" );

219

220 if ( control.gameOver() )

221 done = true;

222 }

223

224 connection.close();

225 }

226 catch( IOException e ) {

Loop and get input. Check validity, and inform server and client.

Program Output

Client/Server Tic-Tac-Toe Using a Multithreaded Server

• Client– Creates GUI

• Uses nine Square objects (extend JPanel)

– start method• Connects to server

• Gets I/O streams

Client/Server Tic-Tac-Toe Using a Multithreaded Server

– Implements interface Runnable, so separate thread can execute read input

• Executes run method, which loops and reads input

85 outputThread = new Thread( this );

86 outputThread.start();

11public class TicTacToeClient extends JApplet

12 implements Runnable {

Client/Server Tic-Tac-Toe Using a Multithreaded Server

– Method run handles input• Sets player's mark

• Loops, gets input, calls processMessage

107 while ( true ) {109 String s = input.readUTF();

110 processMessage( s );

114 }

94 public void run()

95 {98 myMark = input.readChar();

Client/Server Tic-Tac-Toe Using a Multithreaded Server

– Method processMessage• Perform actions depending on String received

– Listen for MouseEvents• If Square clicked, setCurrentSquare

119 public void processMessage( String s )

121 if ( s.equals( "Valid move." ) ) {

126 else if ( s.equals( "Invalid move, try again" ) ) {130 else if ( s.equals( "Opponent moved" ) ) {

121 if ( s.equals( "Valid move." ) ) {

122 display.append( "Valid move, please wait.\n" );

123 currentSquare.setMark( myMark );

124 currentSquare.repaint();

125 }

1. implements Runnable

1.1 Declarations

1.2 GUI

1 // Fig. 21.8: TicTacToeClient.java2 // Client for the TicTacToe program3 import java.awt.*;4 import java.awt.event.*;5 import java.net.*;6 import java.io.*;7 import javax.swing.*;89 // Client class to let a user play Tic-Tac-Toe with10 // another user across a network.11 public class TicTacToeClient extends JApplet12 implements Runnable {13 private JTextField id;14 private JTextArea display;15 private JPanel boardPanel, panel2;16 private Square board[][], currentSquare;17 private Socket connection;18 private DataInputStream input;19 private DataOutputStream output;20 private Thread outputThread;21 private char myMark;22 private boolean myTurn;2324 // Set up user-interface and board25 public void init()26 {27 display = new JTextArea( 4, 30 );28 display.setEditable( false );29 getContentPane().add( new JScrollPane( display ),30 BorderLayout.SOUTH );

Allows applet to create a thread, used to get input.

1.3 GUI

1.4 Event handlers

34 boardPanel.setLayout( layout );353637 board = new Square[ 3 ][ 3 ];3839 // When creating a Square, the location argument to the40 // constructor is a value from 0 to 8 indicating the41 // position of the Square on the board. Values 0, 1,42 // and 2 are the first row, values 3, 4, and 5 are the43 // second row. Values 6, 7, and 8 are the third row.44 for ( int row = 0; row < board.length; row++ )45 {46 for ( int col = 0;47 col < board[ row ].length; col++ ) {48 board[ row ][ col ] =49 new Square( ' ', row * 3 + col );

5050 board[ row ][ col ].addMouseListener(51 new SquareListener(52 this, board[ row ][ col ] ) );5354 boardPanel.add( board[ row ][ col ] ); 55 }56 }5758 id = new JTextField();59 id.setEditable( false );60

3132 boardPanel = new JPanel();33 GridLayout layout = new GridLayout( 3, 3, 0, 0 );

Register event handlers for each Square.

2. start

2.1 Socket

2.2 Thread

6768 // Make connection to server and get associated streams.69 // Start separate thread to allow this applet to70 // continually update its output in text area display.71 public void start()72 {73 try {74 connection = new Socket(7575 InetAddress.getByName( "127.0.0.1" ), 5000 );76 input = new DataInputStream(77 connection.getInputStream() );78 output = new DataOutputStream(79 connection.getOutputStream() );80 }81 catch ( IOException e ) {82 e.printStackTrace(); 83 }848585 outputThread = new Thread( this );86 outputThread.start();87 }88899091

61 getContentPane().add( id, BorderLayout.NORTH );62 63 panel2 = new JPanel();64 panel2.add( boardPanel, BorderLayout.CENTER );65 getContentPane().add( panel2, BorderLayout.CENTER );66 }

Get connection to server.

Create new thread, which executes method run.

3. run

3.1 Get mark

3.2 Loop for input100 myTurn = ( myMark == 'X' ? true : false );

101 }

102 catch ( IOException e ) {

103 e.printStackTrace();

104 }

105

106 // Receive messages sent to client

107 while ( true ) {

108 try {

109 String s = input.readUTF();

110 processMessage( s );

111 }

112 catch ( IOException e ) {

113 e.printStackTrace();

114 }

115 }

116 }

117

92 // Control thread that allows continuous update of the

93 // text area display.

94 public void run()

95 {

96 // First get player's mark (X or O)

97 try {

9898 myMark = input.readChar();

99 id.setText( "You are player \"" + myMark + "\"" );

Get player's mark (first data sent) then loop for more input.

4. processMessage

4.1 setMark

133

134 board[ loc / 3 ][ loc % 3 ].setMark(

135 ( myMark == 'X' ? 'O' : 'X' ) );

136 board[ loc / 3 ][ loc % 3 ].repaint();

137

138 display.append(

139 "Opponent moved. Your turn.\n" );

140 myTurn = true;

141 }

142

143 catch ( IOException e ) {

144 e.printStackTrace();

145 }

146 }

118 // Process messages sent to client

119 public void processMessage( String s )

120 {

121 if ( s.equals( "Valid move." ) ) {

122 display.append( "Valid move, please wait.\n" );

123123 currentSquare.setMark( myMark );

124 currentSquare.repaint();

125 }

126 else if ( s.equals( "Invalid move, try again" ) ) {

127 display.append( s + "\n" );

128 myTurn = true;

129 }

130 else if ( s.equals( "Opponent moved" ) ) {

131 try {

132 int loc = input.readInt();

Process string. If valid move, update current square with mark. If opponent moved, update appropriate square (in board array).

5. sendClickedSquare

6. setCurrentSquare

7. Class Square

165166 public void setCurrentSquare( Square s )167 {168 currentSquare = s;169 }170}171172// Maintains one square on the board173class Square extends JPanel {174 private char mark;175 private int location;176

147 else148 display.append( s + "\n" );149150 display.setCaretPosition(151 display.getText().length() );152 }153154 public void sendClickedSquare( int loc )155 {156 if ( myTurn )157 try {158 output.writeInt( loc );159 myTurn = false;160 }161 catch ( IOException ie ) {162 ie.printStackTrace(); 163 }164 }

7. Class Square

197

198 public void paintComponent( Graphics g )

199 {

200 super.paintComponent( g );

201 g.drawRect( 0, 0, 29, 29 );

202 g.drawString( String.valueOf( mark ), 11, 20 );

203 }

204}

177 public Square( char m, int loc)

178 {

179 mark = m;

180 location = loc;

181 setSize ( 30, 30 );

182

183 setVisible(true);

184 }

185

186 public Dimension getPreferredSize() {

187 return ( new Dimension( 30, 30 ) );

188 }

189

190 public Dimension getMinimumSize() {

191 return ( getPreferredSize() );

192 }

193

194 public void setMark( char c ) { mark = c; }

195

196 public int getSquareLocation() { return location; }

8. Event handler

205

206class SquareListener extends MouseAdapter {

207 private TicTacToeClient applet;

208 private Square square;

209

210 public SquareListener( TicTacToeClient t, Square s )

211 {

212 applet = t;

213 square = s;

214 }

215

216 public void mouseReleased( MouseEvent e )

217 {

218 applet.setCurrentSquare( square );

219 applet.sendClickedSquare( square.getSquareLocation() );

220 }

221}

ProgramOutput

ProgramOutput

Security and the Network

• Security– Many Web browsers prevent file processing by applets (by

default)• Malicious applets could be a security risk

• Applets can usually only talk with the machine that downloaded it

• Trusted source– Browsers can determine if applet came from trusted source

– If so, can be given more access

Recommended