Document 7230775

Download Report

Transcript Document 7230775

•
What happens when many clients
want to contact the server at the
The iterative approach consist
in “enqueuing”
the
requests (this is done
same
time
?
automatically by the system) and serving them one by one :
– Accept the next connection and build the socket
– Read request
– Process request (send the response)
• This will inevitably mean that if there is a client with a small request (for
example, a small file request) will have to wait until the large requests are
over
• If more than the allowed number of clients at socket queue request a
service during this time they are rejected !!!
• There may be also some delays in attending clients by waiting some
information (client are asked to type in something)
• There are many Disk I/O operations in a file serving scenario which are
normally “slow”and do not require network traffic or CPU
• So there is a lot of resources standing idle with this schema
A sequential (iterative) server
attending more than a client
A CLIENT
A SERVER
A CLIENT
4444
A CLIENT
During the transfer of the file the
server cannot hear at the port 4444
for requests
A CLIENT
A SERVER
A CLIENT
4444
A CLIENT
Only after the transmition is over
the server can attend another
request
A CLIENT
A SERVER
A CLIENT
4444
A CLIENT
This may involve some delay
(typing, transmitting large files)
A CLIENT
A SERVER
A CLIENT
4444
A CLIENT
Sometimes a large waiting time for
the client may mean a timeot for the
connection
A CLIENT
A SERVER
Timeout
4444
A CLIENT
A CLIENT
The Concurrent Server
• A concurrent server can attend many clients at the
same time
• While transferring a file, it can still keep listening
for requests
• Every time a request comes, a new parallel line of
statements execution is started for attending this
request. After this the server can “hear” again at
the server socket for further requests
• Different approaches have been developed to
implement parallel lines of executions within a
program
• The operative system plays an important role
In concurrent servers there is a main
program which listens for client
requests
A CLIENT
A SERVER
4444
A CLIENT
A CLIENT
After a client is contacted, a new line
of execution is created which will
attend the request in parallel.
A CLIENT
A SERVER
4444
A CLIENT
A CLIENT
The main program will return to the
listening loop while the first client is
being attended, so it can accept
another request
A CLIENT
A SERVER
4444
A CLIENT
A CLIENT
… and create another parallel
line of execution for attending
the client
A CLIENT
A SERVER
4444
A CLIENT
A CLIENT
… so a request of a third client
can be immediately be accepted
A CLIENT
A SERVER
4444
A CLIENT
A CLIENT
… thus having the three clients
being attended in parallel
A CLIENT
A SERVER
4444
A CLIENT
A CLIENT
The Concurrent Server
Algorithm
Master program of
the server
1. Create a server socket
2. Wait for and accept a client’s request
3. Create a parallel line of execution to attend the
requirement of the new client
4. Goto 2.
Slave (parallel) process :
1. Receive the parameters of the communication
established by the master (socket or input/output
data streams)
2. Attend client’s request (read filename, transfer
data)
3. Return (disappear !)
Parallel Lines of execution
• If there is only 1 CPU, why create parallel processes?
– It often makes server programming easier.
– Because there are more CPU involved !!!!!
• The concept of parallel processes implemented at the S.O
level appeared with UNIX and C.
• In C a new process can be created by executing the fork()
statement
• int i = fork() creates an exact copy of the running process.
Both continue executing the same program with the same
variables.
• For the “father” the value of i will be the id of the created
process. For the child process this value will be 0
• When programming concurrent servers the father will be the
main process accepting requests and the child will process
the client’s request
A simplified example of the use
of for for implementing
concurrent servers
main() {
int pid, msock, ssock;
msock = passivesock(port, “tcp”, qlen);
/* see chapter 10.4 from Internetworking with tcp/ip from Douglas
Commer for the implementation */
while(1) {
ssock = accept(msock, &fsin, &alen);
pid = fork();
if (pid == 0) {
process client’s request;
return;
}
}
Problems with fork() in UNIX
• The creation of a new process is a time costly procedure
– In some texts it is suggested to create a set of
processes at the beginning which will be activated
later by the main program. When a client arrives the
parameters of the communication are passed vi pipes
to child.
• The new created process duplicates all the variables !!!
• It is not easy to manage the processes which ended in an
abnormal way. They keep the resources !!!.
• Sometimes is preferred to use the “select” statement: it
basically selects from an array of sockets the first one which
has available data to read.
In JAVA is better to use Threads
• A thread is a sequence or a flow of instructions which are
executed in parallel to the main sequence of the program. It
has a start and an end.
• A thread can only be created and lives inside an already
running process. A process can start as many threads as
necessary.
• Because of this, the main program has a better control of the
threads it started. They can be created, started, suspended, or
reactivated by the program.
• Threads are implemented as methods of a certain class.
When this method (normally called run) is activated, it starts
to run in parallel to the method that called it.
• As any other method, it can define its own set of variables
Using threads to implement
concurrent servers
Main (master) program:
Create ServerSocket ss;
While(true) {
Socket s = ss.accept();
Create new thread with the socket s as parameter;
start executing thread;
}
Define a thread class with a parallel method (run) which
implements the processing of the clients request
Implementation of Threads
• One way (perhaps the most clear one) is to define a new
class which is an extension of the Thread class and
overwrite its run() method.
– Thread is an existing class
– This thread class has a run method (originally with no statements)
which will be executed in parallel when activated.
– In order to execute this method a program must create an object of
the extended class and apply the start() method to it.
• The definition of the new Thread class should look like
this:
– public class MyThread extends Thread {
• And somewhere should appear:
– public void run() {
//instructions to be executed in parallel }
Example
public class SimpleThread extends Thread {
public SimpleThread(String str) {
super(str);
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
this.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
}
}
• The this.sleep(miliseconds) must appear in a try and catch
block
Use of this new class
public class TwoThreadsTest {
public static void main (String[] args) {
SimpleThread t1,t2;
t1 = SimpleThread("Jamaica");
t2 = SimpleThread("Fiji");
t1.start(); t2.start()
}
}
• The start() triggers the execution of the run
method of the thread. There are other methods
which can be applied to a thread: suspend(),
resume(), stop(). These are however deprecated
because their use can easily lead to deadlocks
•
Sometimes you cannot program the
server as an extension of a thread
For example, if the server has to implement a graphical
interface it should be declared as an extension of a Frame,
if it is programmed as an Applet it must extend the Applet
class
• The we can use the interface Runnable, which means the
Server will also be seen as a Runnable class and has to
implement the run method run().
• To initiate a parallel execution of the run method a Thread
object must be created. In the creation a pointer to the
server object (this) should be passed as parameter. With
this, the Thread object will have access to the run method.
• The run method implemented in the server class will be
executed by performing start() on the new created Thread
object.
Example with interface Runnable
• See and execute the program
NoSincron.java
• Note that the Threads created in this way
will have access to all resources of the
master.
• With the other form of creating threads,
resources from the master object can be
made available by passing a point to itself
on creation of the thread
Critical regions and semaphores in
Java
• Java provides basically two methods for
controlling concurrent access to resources
– You can declare a whole method as a critical region
(see sincron1)
– You can use the semaphore of any object (see
sincron2)
– Another way to use semaphores in java is with wait()
and notify()
Implementing a concurrent file
server (as an extension of Thread)
• Define a new Class as an extension of the Thread class which has a
socket as Object variable.
• Program a constructor which receives a socket as parameter.
• Program the run methods to attend the client connected at the other
extreme of the socket.
• Program a main method which consists of an infinite while. Inside
the while program the acceptance of a new client, the creation of a
new thread with the socket obtained, and the starting of the thread
execution.
• The client does not change, in fact, it does not know if it is being
served concurrently or in parallel
• See: MultiArchServidorThread.java &MultiArchServidor.java
Broadcasting a text to many clients
Hello
Hello
Hello
Hello
Hello
Hello
The server: receiving a new client
4444
Client contacts server at 4444
The server: receiving a new client
4444
A new socket is placed and the
output channel is opened
They are kept in an array
The server: Broadcasting a message
Type a message
When a message is entered
the server will distribute it to
the connected clients
BraodcastServerNF
BroadcastCliente
It is now easy to extend this to a
chat system
Hello
Hello
Hello
Hello
Hello
Conditions for implementing a
chat system
 Server must be listening to requests of new clients AND to
messages which are sent by already connected
 Client must be listening to messages from the server AND
to the keyboard for messages the user wants to transmit.
 There are many approaches for implementing this in
TCP/IP
 No one is the “absolute correct” solution, all them have
their advantages and drawbacks
 Normally (like everywhere in computers) “faster”
solutions will use more memory
 The server:
Solution 1
1.
A thread listens to new clients trying to join the chat party
2.
When a new clients connects, a PrintWriter and a
BufferedReader for that client are created. The print Writer is
kept in a vector
3.
A thread is created and receives a pointer to the PrintWriters’
vector and the BufferedReader. It reads the input from the client
and writes it to all PrintWriters (clients)
 The client
1.
Graphical interface for reading lines from the keyboard (there is a
thread which triggers the execution of the actionPerformed
method) and sends it to the server
2.
A thread will read input from the server and display it on a text
area
 See: Chat1Server.java, Chat1ClientThread.java & Chat1Client
Solution 1 Schema
New Client
Client3
Client1
Thread
PrintWriter
Client2
BufferedReader
 The server:
Solution 2
1.
The server has only one thread listening at one port for attending
all the requests of the clients.
2.
The clients contact the server for registering (reg), sending a
message (msg) or logging out (des)
3.
The server keeps a PrintWiter vector to keep track about which
clients participate in the chat party. Additionally, it keeps a vector
with the nicknames of the clients
 The client
1.
Graphical interface for reading lines from the keyboard (there is a
thread which triggers the execution of the actionPerformed
method) and sends it to the server. It also shows the nicknames of
the participants
2.
A thread will read input from the server. This can be a message
(msg) or a refreshment of the login list
 See: CICChat.java & CICServer.java
Solution 2 Schema
New Client
Client1
Client2
Solution 2
Client3
Client1
Client2
Peer-to-peer solution for TCP/IP
• Every program should be client and server at the
same time
• When a new member wants to join the party,
he/she shoud contact anyone of the group and ask
for the list of contacts
• After retrieving the list of contacts (hostnames or
addresses) he/she should open an input and output
channel with everyone (including the one who
provided the list)
Peer-to-peer solution: a user starts a chat party
by listening on a port for others wanting to join
A user wanting to join contacts the initiator.
An InputStream and an OutputStream is
opened on each
A third user may contact anyone and recover
the list of participants, in this case each one
has the address of the other in the list
Then contacts all of them opening Input/Output
sreams. All them now have two entries on their
participant list
Particularities of this implementation
• The program is written in the ChatPtP.java file
• In order to allow testing in one computer, it is necessary to
give the port number at which the program will listen for
newcomers
• java ChatPtP localport starts a new Chat party
• java ChatPtP remotehost remoteport localport joins an
existing party (on remotehost at remoteport a program is
waiting for new members)
• The is one thread for listening to newcomers
• Another listens for input on keyboard and sends it to all
connected participants
• There is one thread listening for input for each of the other
participants
• Not very easy, isn’t it ?
Problems of this implementation
• What happens if one user leaves the chat party ?
• What happens if during the second connection
phase (retrieving the list and contacting the
participants) another newcomer joins the party by
asking a third one for the list ?
• This is a very critical problem which has been
more or less addressed in some (sometimes hard to
understand) papers.
Hausaufgabe 1: ftp client und server
(ArchClientRobust & ArchServerRobust ergänzen)
• Der Client kann Dateien hoch oder
runterladen
– PUT filename
– GET filename
– Die Dateien werden durch einen neuen socket
geschickt/empfangen
• Kann auch die liste der Dateien anfordern
– DIR
Hausaufgabe 2: Erweitrn des Peer-topeer TCP/IP Chat programs um:
(ChatPtP.java)
• Das Programm soll eine graphische
Benutzerschnittstelle haben wie beim CICChat
• Diese Schnittstelle muss auch zeigen, die
“Nocknames” aller Teilnehmern
• Ein Teilnehmer muss sich von der Gruppe
“verabschieden” bevor er die Gruppe verlässt (das
will noch längst nicht alle Probleme lösen aber
einige schon)
A concurrent web server
• This will be implemented only for HTML files and classes (like servlets),
but it is easily extensible for attending different types of requirements
• For each client a new thread is created
• The process is according to the type of the request
Httpd (server)
HttpProcessor
processRequest()
thread
browser
HttpOutputStream
HttpFile
HttpInputStream
HttpClass
Echo
HttpClassProcessor
HttpException
Implementing state in a web
server
• The server must keep tracking of the
different users that contact it
• The client must submit this information
• The Echo2 class keeps track of a “shopping
cart” for different users
• The client must submit a request like:
user=username&product=productcode&qtty=number
Architecture of a generic file
server
Aplication
Directory service
Client
Module
Flat file service
Components
• Flat File Service: Implements the operations which
work directly on the files. It uses a Unique File Identifier
(UFID). A new one is generated for each new file
• Directory Services: is a FFS client , provides a
mapping between the UFID and the textual names of the
files. It also porvides the necessary functions for managing
directories and obtain UFID.Directories are stored as plain
files.
• Client module: Runs in every clinet computer,
integrates and extends the FFS and DS operations in an
interface application used by programmers. Contains
information for localizing files over the network. Provides
efficiency by implementing a caché
A model for an FFS interface
• read(FileId, i, n) : attempts to read up to n bytes from a file
starting from the byte in the position i.
• write(FileId, i, Datos): writes a data sequence starting from
the position i into the specified file
• create() : creates a new file (empty) and returns its UFID
• delete(FileId) : deletes the file
• getAttributes(FileId) : returns a structure containing the file
attributes
• setAttributes(FileId, attr) : sets the file attributes according
to what is stored in the structure
Access Controls
• On a local file system it is necessary check the access rights
of the file user only when it is opened and the rights are kept
until the file is closed
• On a distributed system the checking are made at the server
side. There are two strategies used in order to keep the
server stateless:
– The checking is done when the filename is converted to the UFID
and the result is packed as a “capacity” which is returned to the
client. The client uses this capacity for each further access.
– The checking of the user’s rights is made every time the file is
accessed.
• The second one is the most used (in NFS & AFS) because
its simplicity
Model for the interface
• Lookup(Dir, File) localises the name of the file in the
directory UFID
• AddName(Dir, Name, File) If Name was not in the
directory, the pair(Name,File) is added modifying the
corresponding file
• UnName(Dir, Name) the pair (Name, file) is deleted from
the directory
• getNames(Dir) turns the list of names in the directory
The NFS
Application
Virtual System
Virtual System
Sist
Local
Client
NFS
Server
NFS
Sist
Local
Caracteristics of the NFS
• Communication is implemented over RPC and is open.
Resides in the server’s kernel
• The identification of the files is by file handlers containing
following information:
• Filesystem identifier
• i-node number or file
• i-node generation number
• The “state” is kept in the client in a v-node
• Client authentication is done in every access.Client
provides ID and group ID
• Flat file & directory services are integrated
• The mount service provides a link to a remote system
Cache in NFS
• Unix provides standard Cache mechanisms: buffer cache,
read ahead, delayed write
• NFS Cache on Client’s side: data for writing are stored in the
cache memory and are written when a commit takes place (buffer
full or closing the file)
• NFS Cache on server’s side: results form read, write, getattr,
lookup and readdir are stored locally. This can introduce some
inconsistencies with the versions stored at the different clients’
machines because writings in one client are not distributed at the
moment to the others. Clients are responsible for maintaining
their caches updated. This is done with the help of timestamps:
– Tc= time of last synchronization of the cache,
– Tm= time of modification
– At a certain time T the cache will be still valid if (T - Tc < t) o (Tmcliente =
Tmserver). Normally t will be 3-30 secs for files and 30-60 for directories
The AFS
• Aims to a better performance in situations of
scalability
• Principles
– Whole-file serving: the content of the whole file is transferred
to the client (even if the client has requested a small part of it)
– Whole-file caching: The file transferred are stored in the local
cache memory. The cache is almost permanent.
• Procedure
– When the client opens a remote file, the whole content is
ttransferred if it was not there already
– Read/write operation are done locally
– With a close, a copy of the file is transmitted to the server
The AFS Architecture
Application
Unix Kernel
Vice
Local
Sist
Venus
Unix Kernel
Consistency of the Cache
• Every time a file is transmitted from the server to a client a
callback promise is provided which guarantees that if other client
modifies the file, this one will be notified
• The callback status can be either valid or cancelled
• When the file is transferred to the client the callback is put on
valid. When a callback is received from the server (another client
did modify the file) the callback promise is put on cancelled
• Every time the client wants to open a file, it searches it first in the
cache. It if is there the callback promise status is looked, if it is
still valid, the cache is used by the client, if it is not there or the
callback is cancelled, a new version is transferred from te server
• If the client’s computer reboots,it asks for a timestamp for every
file in the cache to the server. If it is consistent with the local
timestamp the callback is put on valid, if not on cancelled
Transmitting Objects via TCP
• Transmission: marshalling, delivery &
unmarshalling.
• The key for this is the Object Serialization:
convert the into a representation which can be
transmitted across the net (String)
• All native Java Objects are serializables.
• For user defined objects it is necessary to write
implements Serializable in their definition (this
does not include static variables or references to
local things such as files or sockets)
Transmitting Objects via TCP
• The classes which allows the transmit:
– ObjectInputStream readObjetct()
– ObjectOutputStream writeObject()
• The user can change the “standard”
serialization mechanism by declaring
implements Externalizable
• This means, the user must implement
– Void writeExternal(ObjectOutputStram o)
– Void readExternal(ObjectInputStream i);