Vous êtes sur la page 1sur 23

Sockets

When creating a socket, you pass in the hostname and port number.
The java.net.Socket constructor does the gethostbyname() and the socket() system call,
sets up the server's sockaddr_in structure, and executes the connect() call.
All you have to do is catch the errors, which are subclassed from the familiar
IOException.
You can both read and write on the same Socket.

Reading / Writing Data

Reading / Writing on the same Socket

Java allows to both read and write on the same Socket.


This requirement, copying data in both directions at more or less the same time - from the
keyboard to the remote program, and from the remote program to the screen - there are
two approaches.
Some I/O libraries in C have a function called poll() or select() that allows you to
examine a number of files to see which ones are ready for reading or writing.
Java does not support this model. The other model, which works on most platforms and is
the norm in Java, is to use two threads, one to handle the data transfer in each direction.
The class Pipe encapsulates on threads and the code for copying data in one direction;
two instances are used, one to drive each direction of transfer independently of the other.

Reading / Writing Textual Data

Construct a BufferedReader or PrintWriter object.


Both objects can be created using the socket's getInputStream() or getOutputStream()
methods.
There is no method to fetch a Reader or Writer, partly because some network services are
limited to ASCII, but mainly because the Socket class was decided on before there were
Reader and Writer classes. You can always create a Reader from an InputStream or a
Writer from an OutputStream using the conversion classes. The paradigm for the two
most common forms is:
BufferedReader is = new BufferedReader (
new InputStreamReader(sock.getInputStream()));

PrintWriter os = new PrintWriter(sock.getOutputStream(), true);


Reading / Writing Binary Data

Construct a DataInputStream or DataOutputStream object.


Both objects can be created using the socket's getInputStream() or getOutputStream()
methods.
The simplest paradigm is:
DataInputStream is = new DataInputStream(sock.getInputStream());
DataOutputStream os = new DataOutputStream(sock.getOutputStream());
If the volumne of data might be large, insert a bufferd stream for efficiency. The
paradigm is:
DataInputStream is = new DataInputStream(
new BufferedInputStream(sock.getInputStream()));

DataOutputStream os = new DataOutputStream(


new BufferedOutputStream(sock.getOutputStream()));

Server Sockets

InetAddress

The InetAddress is mainly used for looking up a host's address name or number.
It is also possible to obtain the address at the other end of a connection.
The InetAddress object represents the Internet address of a given computer or host.
There are no public constructors, you can obtain an InetAddress object by calling the
static byName method, passing in either a hostname like wwww.iDevelopment.info or a
network address as a String, like "12.4.234.11".

Creating a simple Chat Client/Server Solution

Here is an example of how to extend a very simple client-server demo program into a
fully functioning (but simple) Chat Client/Server package. There are five stages involved:
Step 1: A simple server that will accept a single client connection and display
everything the client says on the screen. If the client user types ".bye", the client and the
server will both quit.
Step 2: A server as before, but this time it will remain 'open' for additional
connection once a client has quit. The server can handle at most one connection at a time.
Step 3: A server as before, but this time it can handle multiple clients
simultaneously. The output from all connected clients will appear on the server's screen.
Step 4: A server as before, but this time it sends all text received from any of the
connected clients to all clients. This means that the server has to receive and send, and the
client has to send as well as receive
Step 5: Wrapping the client from step 4 into a very simple GUI interface but not
changing the functionality of either server or client. The client is implemented as an
Applet, but a Frame would have worked just as well (for a stand-alone program).

Step 1: Simple, one-time Server


import java.net.*;
import java.io.*;

public class ChatServer


{ private Socket socket = null;
private ServerSocket server = null;
private DataInputStream streamIn = null;

public ChatServer(int port)


{ try
{ System.out.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
System.out.println("Waiting for a client ...");
socket = server.accept();
System.out.println("Client accepted: " + socket);
open();
boolean done = false;
while (!done)
{ try
{ String line = streamIn.readUTF();
System.out.println(line);
done = line.equals(".bye");
}
catch(IOException ioe)
{ done = true;
}
}
close();
}
catch(IOException ioe)
{ System.out.println(ioe);
}
}
public void open() throws IOException
{ streamIn = new DataInputStream(new
BufferedInputStream(socket.getInputStream()));
}
public void close() throws IOException
{ if (socket != null) socket.close();
if (streamIn != null) streamIn.close();
}
public static void main(String args[])
{ ChatServer server = null;
if (args.length != 1)
System.out.println("Usage: java ChatServer port");
else
server = new ChatServer(Integer.parseInt(args[0]));
}
}

The Simple Client corresponding to the previous server (and to step 2 and step 3 servers
as well):
import java.net.*;
import java.io.*;

public class ChatClient


{ private Socket socket = null;
private DataInputStream console = null;
private DataOutputStream streamOut = null;

public ChatClient(String serverName, int serverPort)


{ System.out.println("Establishing connection. Please wait ...");
try
{ socket = new Socket(serverName, serverPort);
System.out.println("Connected: " + socket);
start();
}
catch(UnknownHostException uhe)
{ System.out.println("Host unknown: " + uhe.getMessage());
}
catch(IOException ioe)
{ System.out.println("Unexpected exception: " + ioe.getMessage());
}
String line = "";
while (!line.equals(".bye"))
{ try
{ line = console.readLine();
streamOut.writeUTF(line);
streamOut.flush();
}
catch(IOException ioe)
{ System.out.println("Sending error: " + ioe.getMessage());
}
}
}
public void start() throws IOException
{ console = new DataInputStream(System.in);
streamOut = new DataOutputStream(socket.getOutputStream());
}
public void stop()
{ try
{ if (console != null) console.close();
if (streamOut != null) streamOut.close();
if (socket != null) socket.close();
}
catch(IOException ioe)
{ System.out.println("Error closing ...");
}
}
public static void main(String args[])
{ ChatClient client = null;
if (args.length != 2)
System.out.println("Usage: java ChatClient host port");
else
client = new ChatClient(args[0], Integer.parseInt(args[1]));
}
}

Step 2: Many Time Server, One Client (Client is as before)


import java.net.*;
import java.io.*;

public class ChatServer implements Runnable


{ private Socket socket = null;
private ServerSocket server = null;
private Thread thread = null;
private DataInputStream streamIn = null;

public ChatServer(int port)


{ try
{ System.out.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
start();
}
catch(IOException ioe)
{ System.out.println(ioe);
}
}
public void run()
{ while (thread != null)
{ try
{ System.out.println("Waiting for a client ...");
socket = server.accept();
System.out.println("Client accepted: " + socket);
open();
boolean done = false;
while (!done)
{ try
{ String line = streamIn.readUTF();
System.out.println(line);
done = line.equals(".bye");
}
catch(IOException ioe)
{ done = true; }
}
close();
}
catch(IOException ie)
{ System.out.println("Acceptance Error: " + ie); }
}
}
public void start()
{ if (thread == null)
{ thread = new Thread(this);
thread.start();
}
}
public void stop()
{ if (thread != null)
{ thread.stop();
thread = null;
}
}
public void open() throws IOException
{ streamIn = new DataInputStream(new
BufferedInputStream(socket.getInputStream()));
}
public void close() throws IOException
{ if (socket != null) socket.close();
if (streamIn != null) streamIn.close();
}
public static void main(String args[])
{ ChatServer server = null;
if (args.length != 1)
System.out.println("Usage: java ChatServer port");
else
server = new ChatServer(Integer.parseInt(args[0]));
}
}
Step 3: Multi-Server handling Multi-Client (Client as before)
import java.net.*;
import java.io.*;

public class ChatServer implements Runnable


{ private ServerSocket server = null;
private Thread thread = null;
private ChatServerThread client = null;

public ChatServer(int port)


{ try
{ System.out.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
start();
}
catch(IOException ioe)
{ System.out.println(ioe); }
}
public void run()
{ while (thread != null)
{ try
{ System.out.println("Waiting for a client ...");
addThread(server.accept());
}
catch(IOException ie)
{ System.out.println("Acceptance Error: " + ie); }
}
}
public void addThread(Socket socket)
{ System.out.println("Client accepted: " + socket);
client = new ChatServerThread(this, socket);
try
{ client.open();
client.start();
}
catch(IOException ioe)
{ System.out.println("Error opening thread: " + ioe); }
}
public void start() { /* no change */ }
public void stop() { /* no change */ }
public static void main(String args[]){ /* no change */ }
}
import java.net.*;
import java.io.*;

public class ChatServerThread extends Thread


{ private Socket socket = null;
private ChatServer server = null;
private int ID = -1;
private DataInputStream streamIn = null;

public ChatServerThread(ChatServer _server, Socket _socket)


{ server = _server; socket = _socket; ID = socket.getPort();
}
public void run()
{ System.out.println("Server Thread " + ID + " running.");
while (true)
{ try
{ System.out.println(streamIn.readUTF());
}
catch(IOException ioe) { }
}
}
public void open() throws IOException
{ streamIn = new DataInputStream(new
BufferedInputStream(socket.getInputStream()));
}
public void close() throws IOException
{ if (socket != null) socket.close();
if (streamIn != null) streamIn.close();
}
}

Step 4: A Simple but functional, text based chat server/client


import java.net.*;
import java.io.*;

public class ChatServer implements Runnable


{ private ChatServerThread clients[] = new ChatServerThread[50];
private ServerSocket server = null;
private Thread thread = null;
private int clientCount = 0;

public ChatServer(int port)


{ try
{ System.out.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
start(); }
catch(IOException ioe)
{ System.out.println("Can not bind to port " + port + ": " + ioe.getMessage()); }
}
public void run()
{ while (thread != null)
{ try
{ System.out.println("Waiting for a client ...");
addThread(server.accept()); }
catch(IOException ioe)
{ System.out.println("Server accept error: " + ioe); stop(); }
}
}
public void start() { /* as before */ }
public void stop() { /* as before */ }
private int findClient(int ID)
{ for (int i = 0; i < clientCount; i++)
if (clients[i].getID() == ID)
return i;
return -1;
}
public synchronized void handle(int ID, String input)
{ if (input.equals(".bye"))
{ clients[findClient(ID)].send(".bye");
remove(ID); }
else
for (int i = 0; i < clientCount; i++)
clients[i].send(ID + ": " + input);
}
public synchronized void remove(int ID)
{ int pos = findClient(ID);
if (pos >= 0)
{ ChatServerThread toTerminate = clients[pos];
System.out.println("Removing client thread " + ID + " at " + pos);
if (pos < clientCount-1)
for (int i = pos+1; i < clientCount; i++)
clients[i-1] = clients[i];
clientCount--;
try
{ toTerminate.close(); }
catch(IOException ioe)
{ System.out.println("Error closing thread: " + ioe); }
toTerminate.stop(); }
}
private void addThread(Socket socket)
{ if (clientCount < clients.length)
{ System.out.println("Client accepted: " + socket);
clients[clientCount] = new ChatServerThread(this, socket);
try
{ clients[clientCount].open();
clients[clientCount].start();
clientCount++; }
catch(IOException ioe)
{ System.out.println("Error opening thread: " + ioe); } }
else
System.out.println("Client refused: maximum " + clients.length + " reached.");
}
public static void main(String args[]) { /* as before */ }
}
import java.net.*;
import java.io.*;

public class ChatServerThread extends Thread


{ private ChatServer server = null;
private Socket socket = null;
private int ID = -1;
private DataInputStream streamIn = null;
private DataOutputStream streamOut = null;

public ChatServerThread(ChatServer _server, Socket _socket)


{ super();
server = _server;
socket = _socket;
ID = socket.getPort();
}
public void send(String msg)
{ try
{ streamOut.writeUTF(msg);
streamOut.flush();
}
catch(IOException ioe)
{ System.out.println(ID + " ERROR sending: " + ioe.getMessage());
server.remove(ID);
stop();
}
}
public int getID()
{ return ID;
}
public void run()
{ System.out.println("Server Thread " + ID + " running.");
while (true)
{ try
{ server.handle(ID, streamIn.readUTF());
}
catch(IOException ioe)
{ System.out.println(ID + " ERROR reading: " + ioe.getMessage());
server.remove(ID);
stop();
}
}
}
public void open() throws IOException
{ streamIn = new DataInputStream(new
BufferedInputStream(socket.getInputStream()));
streamOut = new DataOutputStream(new
BufferedOutputStream(socket.getOutputStream()));
}
public void close() throws IOException
{ if (socket != null) socket.close();
if (streamIn != null) streamIn.close();
if (streamOut != null) streamOut.close();
}
}
import java.net.*;
import java.io.*;

public class ChatClient implements Runnable


{ private Socket socket = null;
private Thread thread = null;
private DataInputStream console = null;
private DataOutputStream streamOut = null;
private ChatClientThread client = null;

public ChatClient(String serverName, int serverPort)


{ System.out.println("Establishing connection. Please wait ...");
try
{ socket = new Socket(serverName, serverPort);
System.out.println("Connected: " + socket);
start();
}
catch(UnknownHostException uhe)
{ System.out.println("Host unknown: " + uhe.getMessage()); }
catch(IOException ioe)
{ System.out.println("Unexpected exception: " + ioe.getMessage()); }
}
public void run()
{ while (thread != null)
{ try
{ streamOut.writeUTF(console.readLine());
streamOut.flush();
}
catch(IOException ioe)
{ System.out.println("Sending error: " + ioe.getMessage());
stop();
}
}
}
public void handle(String msg)
{ if (msg.equals(".bye"))
{ System.out.println("Good bye. Press RETURN to exit ...");
stop();
}
else
System.out.println(msg);
}
public void start() throws IOException
{ console = new DataInputStream(System.in);
streamOut = new DataOutputStream(socket.getOutputStream());
if (thread == null)
{ client = new ChatClientThread(this, socket);
thread = new Thread(this);
thread.start();
}
}
public void stop()
{ if (thread != null)
{ thread.stop();
thread = null;
}
try
{ if (console != null) console.close();
if (streamOut != null) streamOut.close();
if (socket != null) socket.close();
}
catch(IOException ioe)
{ System.out.println("Error closing ..."); }
client.close();
client.stop();
}
public static void main(String args[])
{ ChatClient client = null;
if (args.length != 2)
System.out.println("Usage: java ChatClient host port");
else
client = new ChatClient(args[0], Integer.parseInt(args[1]));
}
}
import java.net.*;
import java.io.*;

public class ChatClientThread extends Thread


{ private Socket socket = null;
private ChatClient client = null;
private DataInputStream streamIn = null;

public ChatClientThread(ChatClient _client, Socket _socket)


{ client = _client;
socket = _socket;
open();
start();
}
public void open()
{ try
{ streamIn = new DataInputStream(socket.getInputStream());
}
catch(IOException ioe)
{ System.out.println("Error getting input stream: " + ioe);
client.stop();
}
}
public void close()
{ try
{ if (streamIn != null) streamIn.close();
}
catch(IOException ioe)
{ System.out.println("Error closing input stream: " + ioe);
}
}
public void run()
{ while (true)
{ try
{ client.handle(streamIn.readUTF());
}
catch(IOException ioe)
{ System.out.println("Listening error: " + ioe.getMessage());
client.stop();
}
}
}
}

Stage 5: Chat client moved to very simple GUI interface


import java.net.*;
import java.io.*;
import java.applet.*;
import java.awt.*;
public class ChatClient extends Applet
{ private Socket socket = null;
private DataInputStream console = null;
private DataOutputStream streamOut = null;
private ChatClientThread client = null;
private TextArea display = new TextArea();
private TextField input = new TextField();
private Button send = new Button("Send"), connect = new Button("Connect"),
quit = new Button("Bye");
private String serverName = "localhost";
private int serverPort = 4444;

public void init()


{ Panel keys = new Panel(); keys.setLayout(new GridLayout(1,2));
keys.add(quit); keys.add(connect);
Panel south = new Panel(); south.setLayout(new BorderLayout());
south.add("West", keys); south.add("Center", input); south.add("East", send);
Label title = new Label("Simple Chat Client Applet", Label.CENTER);
title.setFont(new Font("Helvetica", Font.BOLD, 14));
setLayout(new BorderLayout());
add("North", title); add("Center", display); add("South", south);
quit.disable(); send.disable(); getParameters(); }
public boolean action(Event e, Object o)
{ if (e.target == quit)
{ input.setText(".bye");
send(); quit.disable(); send.disable(); connect.enable(); }
else if (e.target == connect)
{ connect(serverName, serverPort); }
else if (e.target == send)
{ send(); input.requestFocus(); }
return true; }
public void connect(String serverName, int serverPort)
{ println("Establishing connection. Please wait ...");
try
{ socket = new Socket(serverName, serverPort);
println("Connected: " + socket);
open(); send.enable(); connect.disable(); quit.enable(); }
catch(UnknownHostException uhe)
{ println("Host unknown: " + uhe.getMessage()); }
catch(IOException ioe)
{ println("Unexpected exception: " + ioe.getMessage()); } }
private void send()
{ try
{ streamOut.writeUTF(input.getText()); streamOut.flush(); input.setText(""); }
catch(IOException ioe)
{ println("Sending error: " + ioe.getMessage()); close(); } }
public void handle(String msg)
{ if (msg.equals(".bye"))
{ println("Good bye. Press RETURN to exit ..."); close(); }
else println(msg); }
public void open()
{ try
{ streamOut = new DataOutputStream(socket.getOutputStream());
client = new ChatClientThread(this, socket); }
catch(IOException ioe)
{ println("Error opening output stream: " + ioe); } }
public void close()
{ try
{ if (streamOut != null) streamOut.close();
if (socket != null) socket.close(); }
catch(IOException ioe)
{ println("Error closing ..."); }
client.close(); client.stop(); }
private void println(String msg)
{ display.appendText(msg + "\n"); }
public void getParameters()
{ serverName = getParameter("host");
serverPort = Integer.parseInt(getParameter("port")); }
}
/*
This program is one end of a simple command-line interface
chat program. It acts as a server which waits for a
connection from the CLChatClient program. The port on
which the server listens can be specified as a command-line
argument. If it is not, then the port specified by the
constant DEFAULT_PORT is used. Note that if a port number
of zero is specified, then the server will listen on
any available port.
This program only supports one connection. As soon
as a connection is opened, the listening socket is closed
down. The two ends of the connection each send the
HANDSHAKE string to the other, so that both ends can verify
that the program on the other end is of the right type.
Then the connected programs alternate sending messages to
each other. The client always sends the first message.
The user on either end can close the connection by entering
the string "quit" when prompted for a message. Note that
the first character of any string sent over the connection
is a command, either MESSAGE or CLOSE.
*/

import java.net.*;
import java.io.*;

public class CLChatServer {

static final int DEFAULT_PORT = 1728; // Port to listen on,


// if none is specified
// on the command line.

static final String HANDSHAKE = "CLChat"; // Handshake string.


// Each end of the connection sends this string
// to the other just after the connection is
// opened. This is done to confirm that the
// program on the other side of the connection
// is a CLChat program.

static final char MESSAGE = '0'; // This character is prepended


// to every message that is sent.

static final char CLOSE = '1'; // This character is sent to


// the connected program when
// the user quits.

public static void main(String[] args) {


int port; // The port on which the server listens.

ServerSocket listener; // Listens for a connection request.


Socket connection; // For communication with the client.

TextReader incoming; // Stream for receiving data from client.


PrintWriter outgoing; // Stream for sending data to client.
String messageOut; // A message to be sent to the client.
String messageIn; // A message received from the client.

/* First, get the port number from the command line,


or use the default port if none is specified. */

if (args.length == 0)
port = DEFAULT_PORT;
else {
try {
port= Integer.parseInt(args[0]);
if (port < 0 || port > 65535)
throw new NumberFormatException();
}
catch (NumberFormatException e) {
TextIO.putln("Illegal port number, " + args[0]);
return;
}
}

/* Wait for a connection request. When it arrives, close


down the listener. Create streams for communication
and exchange the handshake. */

try {
listener = new ServerSocket(port);
TextIO.putln("Listening on port " + listener.getLocalPort());
connection = listener.accept();
listener.close();
incoming = new TextReader(connection.getInputStream());
outgoing = new PrintWriter(connection.getOutputStream());
outgoing.println(HANDSHAKE);
outgoing.flush();
messageIn = incoming.getln();
if (! messageIn.equals(HANDSHAKE) ) {
throw new IOException("Connected program is not CLChat!");
}
TextIO.putln("Connected. Waiting for the first message.\n");
}
catch (Exception e) {
TextIO.putln("An error occurred while opening connection.");
TextIO.putln(e.toString());
return;
}

/* Exchange messages with the other end of the connection


until one side or the other closes the connection.
This server program waits for the first message from
the client. After that, messages alternate strictly
back an forth. */

try {
while (true) {
TextIO.putln("WAITING...");
messageIn = incoming.getln();
if (messageIn.length() > 0) {
// The first character of the message is a command.
// If the command is CLOSE, then the connection
// is closed. Otherwise, remove the command
// character from the message and procede.
if (messageIn.charAt(0) == CLOSE) {
TextIO.putln("Connection closed at other end.");
connection.close();
break;
}
messageIn = messageIn.substring(1);
}
TextIO.putln("RECEIVED: " + messageIn);
TextIO.put("SEND: ");
messageOut = TextIO.getln();
if (messageOut.equalsIgnoreCase("quit")) {
// User wants to quit. Inform the other side
// of the connection, then close the connection.
outgoing.println(CLOSE);
outgoing.flush(); // Make sure the data is sent!
connection.close();
TextIO.putln("Connection closed.");
break;
}
outgoing.println(MESSAGE + messageOut);
outgoing.flush(); // Make sure the data is sent!
if (outgoing.checkError()) {
throw new IOException("Error occurred while transmitting message.");
}
}
}
catch (Exception e) {
TextIO.putln("Sorry, an error has occurred. Connection lost.");
TextIO.putln(e.toString());
System.exit(1);
}

} // end main()

} //end class CLChatServer


/*
This program is one end of a simple command-line interface
chat program. It acts as a client which makes a
connection to the CLChatServer program. The computer to
which the client is to connect must be specified as the
first command-line argument. The port on which the server
listens can optionally be specified as the second command-line
argument. If it is not, then the port specified by the
constant DEFAULT_PORT is used.
When the connection is opened, each side sends the
HANDSHAKE string to the other, so that both sides can verify
that the program on the other end is of the right type.
Then the connected programs alternate sending messages to
each other. The client always sends the first message.
The user on either end can close the connection by entering
the string "quit" when prompted for a message. Note that
the first character of any string sent over the connection
is a command, either MESSAGE or CLOSE.
*/

import java.net.*;
import java.io.*;

public class CLChatClient {

static final int DEFAULT_PORT = 1728; // Port where server is


// listening, if no
// port is specified
// on the command line.

static final String HANDSHAKE = "CLChat"; // Handshake string.


// Each end of the connection sends this string
// to the other just after the connection is
// opened. This is done to confirm that the
// program on the other side of the connection
// is a CLChat program.

static final char MESSAGE = '0'; // This character is prepended


// to every message that is sent.

static final char CLOSE = '1'; // This character is sent to


// the connected program when
// the user quits.

public static void main(String[] args) {


String computer; // The computer where the server is running,
// as specified on the command line. It can
// be either an IP number or a domain name.

int port; // The port on which the server listens.

Socket connection; // For communication with the server.

TextReader incoming; // Stream for receiving data from server.


PrintWriter outgoing; // Stream for sending data to server.
String messageOut; // A message to be sent to the server.
String messageIn; // A message received from the server.

/* First, get the computer from the command line.


Get the port from the command line, if one is specified,
or use the default port if none is specified. */

if (args.length == 0) {
TextIO.putln("Usage: java SimpleClient <computer-name> [<port>]");
return;
}

computer = args[0];

if (args.length == 1)
port = DEFAULT_PORT;
else {
try {
port= Integer.parseInt(args[1]);
if (port <= 0 || port > 65535)
throw new NumberFormatException();
}
catch (NumberFormatException e) {
TextIO.putln("Illegal port number, " + args[1]);
return;
}
}

/* Open a connetion to the server. Create streams for


communication and exchange the handshake. */

try {
TextIO.putln("Connecting to " + computer + " on port " + port);
connection = new Socket(computer,port);
incoming = new TextReader(connection.getInputStream());
outgoing = new PrintWriter(connection.getOutputStream());
outgoing.println(HANDSHAKE);
outgoing.flush();
messageIn = incoming.getln();
if (! messageIn.equals(HANDSHAKE) ) {
throw new IOException("Connected program is not CLChat!");
}
TextIO.putln("Connected. Enter your first message.\n");
}
catch (Exception e) {
TextIO.putln("An error occurred while opening connection.");
TextIO.putln(e.toString());
return;
}

/* Exchange messages with the other end of the connection


until one side or the other closes the connection.
This client program send the first message. After that,
messages alternate strictly back an forth. */

try {
while (true) {
TextIO.put("SEND: ");
messageOut = TextIO.getln();
if (messageOut.equalsIgnoreCase("quit")) {
// User wants to quit. Inform the other side
// of the connection, then close the connection.
outgoing.println(CLOSE);
outgoing.flush();
connection.close();
TextIO.putln("Connection closed.");
break;
}
outgoing.println(MESSAGE + messageOut);
outgoing.flush();
if (outgoing.checkError()) {
throw new IOException("Error occurred while transmitting message.");
}
TextIO.putln("WAITING...");
messageIn = incoming.getln();
if (messageIn.length() > 0) {
// The first character of the message is a command.
// If the command is CLOSE, then the connection
// is closed. Otherwise, remove the command
// character from the message and procede.
if (messageIn.charAt(0) == CLOSE) {
TextIO.putln("Connection closed at other end.");
connection.close();
break;
}
messageIn = messageIn.substring(1);
}
TextIO.putln("RECEIVED: " + messageIn);
}
}
catch (Exception e) {
TextIO.putln("Sorry, an error has occurred. Connection lost.");
TextIO.putln(e.toString());
System.exit(1);
}

} // end main()

} //end class CLChatClient