Introduction
The Client-Server Model
Server Methods
Client Methods
Sending and Receiving Data
Client and Server Code Example
Drivers for the Client and Server Code Example
Next Topic: Not Ready Yet
There are restrictions as far as what you can do from inside of an applet.
A client applet can only establish communication with a server running on the
host that the applet was loaded from.
There is no such restriction on an application.
Communication requests to a server are distinguished by a port number.
A port is just an integer (usually a small one, but in Java, an int is used
for a port number).
Certain port numbers are reserved.
For example, 21 is used by ftp and 2049 is reserved for nfs.
On a given machine, at most one process can act as a server for a given port, but any number of clients can use that port number.
ServerSocket s = new ServerSocket(port,queueLength);
This does the same thing as the UICI u_open or the socket calls
socket, bind and listen.
A server waits for a connection using:
Socket connection = s.accept();
This blocks until a connection request comes in from a client.
It is the similar to the UICI u_listen or the socket accept.
A server that return from the accept can then create a thread to handle the connection while it does another accept.
Each of these server methods can throw an IOException.
DataInputStream input; DataOutputStream output; input = new DataInputStream(connection.getInputStream()); output = new DataOutputStream(connection.getOutputStream());Each of these can throw an IOException so you should enclose these in a try catch.
A DataInputStream or DataOutputStream represents Unicode strings. They allow for the transfer of information in a machine-independent way.
Here are some of the methods that can be used with a dataOutputStream
public final void writeBoolean(boolean v); public final void writeByte(int v); public final void writeBytes(String s); public final void writeChar(int v); public final void writeChars(String s); public final void writeDouble(double v); public final void writeInt(int v); public final void writeLong(long v); public final void WriteShort(int v); public void write(int b); public void write(byte b[], int off, int len); public void flush();All of these can throw an IOException.
There are corresponding methods for reading from a DataInputStream.
public final boolean readBoolean(); public final byte readByte(); public final char readChar(); public final double ReadDouble(); public final int readInt(); public final long readLong(); public final short readShort(); public final int read(byte b[]); public final int read(byte b[], int off, int len);
It uses a TextReceiver interface which looks like this:
public interface TextReceiver { public boolean ReceiveText(String str); }This is used to receive strings. The ClientServer class implements this and strings which come in are set out over the network.
The ClientServer class creates a SocketReceiver thread to wait for input from the network. This thread sends the network input to another TextReceiver which was passed to ClientServer in its constructor.
import java.net.*; import java.io.*; public class SocketReceiver extends Thread { private final int BUFSIZE = 1024; private DataInputStream input; private TextReceiver tr; public SocketReceiver(Socket connection, TextReceiver tr) { this.tr = tr; try { input = new DataInputStream(connection.getInputStream()); start(); } catch (IOException e) {} } public void run() { byte[] buffer; int bytesread; buffer = new byte[BUFSIZE]; for ( ; ; ) { try { bytesread = input.read(buffer); } catch (IOException e) { try { input.close(); } catch (IOException e1) {} return; } if (bytesread > 0) tr.ReceiveText(new String(buffer,0,bytesread)); } } }
import java.net.*; import java.io.*; public class ClientServer implements TextReceiver { private TextReceiver tr; private DataOutputStream output; private Socket connection; // This is the server constructor public ClientServer(int port, TextReceiver tr) { this.tr = tr; ServerSocket s; try { s = new ServerSocket(port,5); connection = s.accept(); System.out.println("A connection has been made to the server"); setup(connection); } catch (IOException e) { tr.ReceiveText("An IO error occurred in the server"); } } // This is the client constructor public ClientServer(String host, int port, TextReceiver tr) { this.tr = tr; try { connection = new Socket(host,port); System.out.println("A connection has been made by the client"); setup(connection); } catch (IOException e) { tr.ReceiveText("An IO error occurred in the client"); } } private void setup(Socket connection) { try { new SocketReceiver(connection,tr); output = new DataOutputStream(connection.getOutputStream()); } catch (IOException e) { tr.ReceiveText("An IO error occurred setting up the output stream"); } } public String GetHostName() { InetAddress inet; String remote; inet = connection.getInetAddress(); remote = inet.getHostName(); return remote; } public boolean ReceiveText(String str) { try { output.writeBytes(str); } catch (IOException e) { try { output.close(); } catch (IOException e1) {} return false; } return true; } }
They each put up a frame which allows the user to input data to be sent to the network and contain text areas for displaying data sent and received. The frame is not specific to network communication.
import java.awt.*; import java.awt.event.*; public class IOFrame extends Frame implements TextReceiver, ActionListener { private TextReceiver tr; private TextField input; private TextArea sent; private TextArea received; private Label ReceivedLabel; private Label SentLabel; private int bytes_received = 0; private int bytes_sent = 0; private int lines_received = 0; private int lines_sent = 0; public IOFrame(String title, int w, int h, TextReceiver tr) { super(title); setSize(w,h); this.tr = tr; setup_layout(); setVisible(true); } private void setup_layout() { Panel p; Panel ReceivedPanel; Panel SentPanel; ReceivedLabel = new Label("Received:"); SentLabel = new Label("Sent:"); setLayout(new BorderLayout()); add(input = new TextField(),BorderLayout.SOUTH); ReceivedPanel = new Panel(); ReceivedPanel.setLayout(new BorderLayout()); ReceivedPanel.add(ReceivedLabel,BorderLayout.NORTH); SentPanel = new Panel(); SentPanel.setLayout(new BorderLayout()); SentPanel.add(SentLabel,BorderLayout.NORTH); p = new Panel(); p.setLayout(new GridLayout(2,1)); ReceivedPanel.add(received = new TextArea(),BorderLayout.CENTER); SentPanel.add(sent = new TextArea(),BorderLayout.CENTER); p.add(ReceivedPanel); p.add(SentPanel); received.setEditable(false); sent.setEditable(false); add(p,BorderLayout.CENTER); input.addActionListener(this); validate(); } private void set_received_label() { ReceivedLabel.setText("Received bytes: "+bytes_received+ " Received lines: "+lines_received); } private void set_sent_label() { SentLabel.setText("Sent bytes: "+bytes_sent+ " Sent lines: "+lines_sent); } private int count_lines(String str) { int count = 0; for (int i=0;i < str.length();i++) if (str.charAt(i)=='\n') count++; return count; } public void SetReceiver(TextReceiver tr) { this.tr = tr; } public void SetBackgrounds(Color c1, Color c2) { sent.setBackground(c1); received.setBackground(c2); } public boolean ReceiveText(String str) { received.append(str); bytes_received += str.length(); lines_received += count_lines(str); set_received_label(); return true; } public void actionPerformed (ActionEvent e) { String str; str = input.getText() + "\n"; input.setText(""); sent.append(str); bytes_sent += str.length(); lines_sent += count_lines(str); set_sent_label(); if (tr != null) tr.ReceiveText(str); } }
Here is the server application:
import java.awt.*; class ServerMain { public static void main(String args[]) { int port; IOFrame io; ClientServer server; if (args.length != 1) { System.out.println("Usage: ServerMain portnumber"); return; } port = Integer.parseInt(args[0]); System.out.println("Using port number "+port); io = new IOFrame("Server waiting on port "+port,400,400,null); io.SetBackgrounds(Color.cyan,Color.yellow); server = new ClientServer(port,io); io.SetReceiver(server); io.setTitle("Server connected to "+server.GetHostName()+" on port "+port); } }
Here is the client application:
import java.awt.*; class ClientMain { public static void main(String args[]) { int port; IOFrame io; ClientServer client; if (args.length != 2) { System.out.println("Usage: ServerMain host portnumber"); return; } port = Integer.parseInt(args[1]); System.out.println("Using port number "+port); io = new IOFrame("Client",400,400,null); io.SetBackgrounds(Color.yellow,Color.cyan); client = new ClientServer(args[0],port,io); io.SetReceiver(client); io.setTitle("Client connected to "+args[0]+" on port "+args[1]); } }
import java.awt.*; import java.applet.*; import java.awt.event.*; public class ClientApplet extends Applet implements ActionListener { String host; TextField tf; IOFrame io; public void init() { setLayout(new GridLayout(2,1)); host = getCodeBase().getHost(); add(new Label("Enter Port Number for Connection to "+host)); add(tf = new TextField()); tf.addActionListener(this); validate(); } public void stop() { if (io != null) io.setVisible(false); } public void actionPerformed (ActionEvent e) { String str; int port; ClientServer client; port = Integer.parseInt(tf.getText()); System.out.println("Connecting to host "+host+" on port "+port); io = new IOFrame("Client",400,400,null); io.SetBackgrounds(Color.yellow,Color.cyan); client = new ClientServer(host,port,io); io.SetReceiver(client); io.setTitle("Client connected to "+host+" on port "+port); } }