Client/server
Download
Report
Transcript Client/server
Client/server
The (simple) Client/Server
Connection using Stream Sockets:
The Server
5 steps to building the server
1. Create a ServerSocket object registers an
available TCP/IP port and a maximum queue
length :
ServerSocket server=new ServerSocket(port#,queuelen);
This is called the handshake point. If the queue is
full the connection is refused. The process is
known as “binding a server to a port”. Only
one application at a time can be bound to a
particular port.
Simple Server continued: Step 2
2. The server listens, or “blocks” for a client
connection:
Socket connection =server.accept();
The socket connection makes possible interaction
with the client via I/O streams. The server
interacts with a client at a different port than
the handshake point, which makes possible
multi-threaded servers (ie.,after connection is
established, the server can spawn a thread to
process this client and go on listening for
another.
Simple Server continued: Step 3
3. The server gets I/O connections
associated with the client socket. I/O
across the connection is not really much
different than other java i/o.
ObjectInputStream input = new
ObjectInputStream(connection.getInputStream());
ObjectOutputStream output = new
ObjectOutputStream(connection.getOutputStream());
The server’s output stream is the client’s
input stream, and visa versa.
Simple Server continued
4. Process the connection – this phase is
application-specific and might involve a
single message being sent, complicated
objects being exchanged, a loop,
whatever.
5. Close the connection by invoking close()
method on the streams.
The (simple) Client/Server
Connection using Stream Sockets:
The Client
4 steps to building the client:
1. Establish a connection to the server:
Socket connection =new Socket(serverIP,port#);
A connection is returned if this step is
successful, otherwise an IOException is
thrown. Notice, the client needs to know
where the server is (the server’s IP)
while the server doesn’t know in advance
the client’s address.
Simple Client continued: Step 2
3. The client gets I/O connections
associated with the socket.
ObjectInputStream input = new
ObjectInputStream(connection.getInputStream());
ObjectOutputStream output = new
ObjectOutputStream(connection.getOutputStream());
Other stream types can be used to wrap
around these for manipulation different
object types. Any serializable object can
be passed via the IO connection.
Simple Client continued
3. Processing phase
4. Close the connection by invoking close()
method on the streams. This is
application specific- the client needs to
know when the server is done so as to
avoid an IOException (EOFException)
trying to read past EOF mark.
server code (in slide notes)
• http://employees.oneonta.edu/higgindm/int
ernet programming/Server.html
Client code
• http://employees.oneonta.edu/higgindm/int
ernet%20programming/Client.html
ServerTest app:
• http://employees.oneonta.edu/higgindm/internet%20programming/S
erverTest.html
•
import javax.swing.JFrame;
public class ServerTest
{
public static void main( String args[] )
{
Server application = new Server(); // create server
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
application.runServer(); // run server application
} // end main
} // end class ServerTest
Clienttest.java app feeds a url:
http://employees.oneonta.edu/higgindm/internet%20programmin
g/ClientTest.html
import javax.swing.JFrame;
public class ClientTest
{ public static void main( String args[] )
{
Client application; // declare client application
// if no command line args
if ( args.length == 0 )
application = new Client( "137.141.19.2" ); // connect to localhost
else
application = new Client( args[ 0 ] ); // use args to connect
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
application.runClient(); // run client application
} // end main
}
Compile and run
• Compile 4 java files. Run ServerTest, then
ClientTest
• Exercise: modify clienttest code so a url is
entered on the command line.
• Run the client and server on different machines
• Hint: You can use
c:\ipconfig \all
to show a machine’s ip, if you can get to the
command prompt
• Loop back URL is 127.0.0.1
Server window
Client window
Some communication
Client closes connection
Connectionless Client/server
communication via datagrams
• While the connection-based client/server model
is similar to the telephone, the datagram model
is more like the post office.
• The message is posted in sequential numbered
packets and re-assembled at the target location.
• Messages may arrive jumbled, or not at all.
• This example uses the UserDatagramProtocol
(UDP) between client and server.
Server structure in datagram communication
DatagramSocket socket;//use this datatype
…
try{
socket= new DatagramSocket(5000);// specify port#
…}catch(SocketException se){…}
Wait for packets:
Byte data[]=new byte[100];
while(true){//forever loop
try{
Datagram receivepacket=new
DatagramPacket(data,data.length);
socket.recieve(receivepacket);
…
}catch(IOException e){}
Datagram server continued
//Send packet to client…also inside try catch for ioexception:
Datagram sendpacket=new
DatagramPacket(receivepacket.getData(),receivepacket.getLength()
,receivepacket.getAddress(),receivepacket.getPort());
socket.send(sendpacket);
Datagram (packet) server
• The server uses two DatagramPackets – one to send
and one to receive packets.
• This application uses java.net classes:
java.net.DatagramPacket and java.net.DatagramSocket
DatagramSocket is created in a try block where the server
is bound to a port. Processing on the serverside involves
an infinite loop waiting for packets. Clients must specify
the server port when sending packets.
Datagram method receive() blocks until a packet is
received then stores the packet info in its Datagram
argument.
Methods are called to display sender’s IP, port, message
length and the message itself.
Packets: 4 files
• http://employees.oneonta.edu/higgindm/internet
%20programming/PacketServer.html
• http://employees.oneonta.edu/higgindm/internet
%20programming/PacketClient.html
• http://employees.oneonta.edu/higgindm/internet
%20programming/PacketServerTest.html
• http://employees.oneonta.edu/higgindm/internet
%20programming/PacketClientTest.html
PacketClient frame
PacketServer frame
Threaded client/server
• Some background
– LockSwingUtilities.invokeLater()
– Scanner
– Executor for threads
– Synchronization using Locks
Scanner
• Scanner is “replacing” StringTokenizer. It
is similar, versatile and easy to use.
• Deitel pg 59 has an example.
import java.util.Scanner;
…
Scanner input=new Scanner(System.in);
int x;
x=input.nextInt();
SwingUtilities.invokeLater()
• Having multiple threads manipulate GUI content may not give
expected results. Better to have the event-dispatching thread queue
requests to display answers, change colors, and so on, and handle
them in order. Here is a method to do it:
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
…thread does stuff to GUI
}});
Executor service for running
threads
• Recommended thread construction in jdk1.5 is
public class mythread extends Runnable{
public void run(){
//loop or whatever
try{
Thread.sleep(sometime);
…the rest of it
}catch(InterruptedException e){…}
}
…}
Executor service for running
threads
• Executor Service example Deitel’s text pg 1059
import java.util.concurrent.*;
Thread a= new Thread(…);//not recommended
//should be
RunnableThingy a= new RunnableThingy();
Thread b= new Thread(…);//as above
ExecutorService threadEx=Executors.newFixedThreadPool(2);
//can run just two threads
threadEx.execute(a);
threadEx.execute(b);
…
theadEx.shutdown();
Executor service for running
threads
• Runnables are managed and executed by a
class that implements Executor interface. This
has one method, (execute).
• An executor manages a thread pool.
• Executor assigns each runnable object to a
thread in the pool. If there are none it may make
a new thread (newCachedThreadPool) or queue
the runnable for the next available thread as in
the fixed thread pool.
Synchronization using Lock
• Example in Deitel text pg 1071
• This is fairly similar to providing
synchronized methods.
• import java.util.concurrent.locks.*
Synchronization using Lock
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
public class SynchronizedBuffer implements Buffer
{ // Lock to control synchronization with this buffer
private Lock accessLock = new ReentrantLock();
// conditions to control reading and writing
private Condition canWrite = accessLock.newCondition();
private Condition canRead = accessLock.newCondition();
private int buffer = -1; // shared by producer and
consumer threads
private boolean occupied = false;
Synchronization using Lock: set
public void set( int value )
{
accessLock.lock(); // lock this object
try
{
while ( occupied ) {
System.out.println( "Producer tries to write." );
displayState( "Buffer full. Producer waits." );
canWrite.await();// wait until buffer is empty
} // end while
buffer = value; // set new buffer value
// producer cannot store new value until consumer retrieves current value
occupied = true;
displayState( "Producer writes " + buffer );
// signal thread waiting to read from buffer
canRead.signal();
} // end try
catch ( InterruptedException exception )
{
exception.printStackTrace();
} // end catch
finally
{
accessLock.unlock(); // unlock this object
} // end finally
} // end method set
•
Synchronization using Lock: get
public int get()
{
int readValue = 0; // initialize value read from buffer
accessLock.lock(); // lock this object
// output thread information and buffer information, then wait
try
{
// while no data to read, place thread in waiting state
while ( !occupied )
{
System.out.println( "Consumer tries to read." );
displayState( "Buffer empty. Consumer waits." );
canRead.await(); // wait until buffer is full
} // end while
// indicate that producer can store another value
// because consumer just retrieved buffer value
occupied = false;
readValue = buffer; // retrieve value from buffer
displayState( "Consumer reads " + readValue );
// signal thread waiting for buffer to be empty
canWrite.signal();
} // end try
// if waiting thread interrupted, print stack trace
catch ( InterruptedException exception )
{
exception.printStackTrace();
} // end catch
finally
{
accessLock.unlock(); // unlock this object
} // end finally
return readValue;
} // end method get
// display current operation and buffer state
} // end class SynchronizedBuffer
Threaded client/server
code links below and in slide notes
• http://employees.oneonta.edu/higgindm/internet%20programming/Ti
cTacToeServerTest.html
• http://employees.oneonta.edu/higgindm/internet%20programming/Ti
cTacToeServer.html
• http://employees.oneonta.edu/higgindm/internet%20programming/Ti
cTacToeClient.html
• http://employees.oneonta.edu/higgindm/internet%20programming/Ti
cTacToeClientTest.html
TicTacToeServer
• In notes
TicTacToe client
Compile & run
• Compile the 4 files. Run
TicTacToeServerTest first. You need to run
2 clients (players).
• A window opens for the server and a
board appears for each client.
Client boards after play
Exercises
• Modify the client to connect to a server on
another machine.
• “Fix” the server so it can tell when the
game ends.
Socket project
• Modify the threaded client server to play your
choice:
• Hexapawn on 4X4 or larger board
• Dominoes
• Othello
• A simple card game War, or maybe “21”
First option may be easiest. Othello also isn’t too
hard. Make sure the server recognizes whose
move it is, allows only correct moves, and knows
when the game is over (or when a client
terminates).