CS 580 Client-Server Spring Semester, 2004 Server Intro |
||
---|---|---|
© 2004, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 19-Feb-04 |
Reading AssignmentJava Java Network Programming, Harold
Basic Network Concepts, Chapter 2
What is a Server?
Server
while (true) { Wait for an incoming request; Perform whatever actions are requested; }
Example - Echo Server
| server | server := SocketAccessor newTCPserverAtPort: 9009. server listenFor: 5. [ | acceptedSocket | "wait for a new connection" acceptedSocket := server accept. "fork off processing of the new stream socket" [ | stream char | stream := acceptedSocket readAppendStream. stream lineEndTransparent. [ (char := stream next) isNil ] whileFalse: [ stream nextPut: char; commit ]. stream close. ] forkAt: Processor userSchedulingPriority -1. ] repeat.
Some Basic Server Issues
Sockets
Streams verses Buffers
Both Java & Smalltalk provide access to socket data via
Java TCP Sockets
Main Classes ServerSocket
public ServerSocket(int port) //port = 0 gives random port public ServerSocket(int port, int backlog) public ServerSocket(int port, int backlog, InetAddress bindAddress)public Socket accept() throws IOException
public InputStream getInputStream() throws IOException public OutputStream getOutputStream() throws IOException
A Simple Date Server
public class DateServer { private static Logger log = Logger.getLogger("dateLogger"); public static void main (String args[]) throws IOException { ProgramProperties flags = new ProgramProperties( args); int port = flags.getInt( "port" , 8765); new DateServer().run(port); } public void run(int port) throws IOException { ServerSocket input = new ServerSocket( port ); log.info("Server running on port " + input.getLocalPort()); while (true) { Socket client = input.accept(); log.info("Request from " + client.getInetAddress()); processRequest( client.getInputStream(), client.getOutputStream()); client.close(); } }
Processing Client Request
void processRequest(InputStream in,OutputStream out) throws IOException { BufferedReader parsedInput = new BufferedReader(new InputStreamReader(in)); boolean autoflushOn = true; PrintWriter parsedOutput = new PrintWriter(out,autoflushOn); String inputLine = parsedInput.readLine(); if (inputLine.startsWith("date")) { Date now = new Date(); parsedOutput.println(now.toString()); } } }
Note: This server is just a first example. It needs a lot of work. We will be working on improving it in later lectures.
Running the Server
Sample run of DateServer.
(I typed everything appearing in bold font here.)
rohan
16->
java
-jar DateServer.jar
Feb 19, 2004 10:56:59 AM DateServer run INFO: Server running on port 8765 |
|
||
|
Al
13->
telnet
rohan.sdsu.edu 8765
Trying 130.191.3.100... Connected to rohan.sdsu.edu. Escape character is '^]'. |
||
Feb
19, 2004 10:57:34 AM DateServer run
INFO: Request from /68.7.92.191 |
|
||
|
date Thu Feb 19 10:57:39 PST 2004 Connection closed by foreign host. |
Warning About telnet Usage
Using telnet to interact with a server is
Smalltalk TCP Sockets
Main Classes
IPSocketAddress
newTCP “selects random port” newTCPserverAtPort: portNumber
accept Wait for a client connection and return it acceptNonBlock return any waiting client connection, return nil if no waiting client connections readAppendStream readStream writeStream Return a stream of the given type on the conection
A Simple Date Server
Smalltalk defineClass: #SimpleDateServer superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: 'serverSocket ' classInstanceVariableNames: '' imports: '' category: 'SimpleServer'
SimpleDateServer class methodsFor: 'instance creation'
port: anInteger ^super new setPort: anInteger
SimpleDateServer instance methods setPort: anInteger serverSocket := SocketAccessor newTCPserverAtPort: anInteger. serverSocket listenFor: 4; soReuseaddr: true
run | childSocket clientConnection clientIOStream | [childSocket := serverSocket accept. clientIOStream := childSocket readAppendStream. clientIOStream lineEndTransparent. self processRequestOn: clientIOStream.] repeat
processRequestOn: anReadAppendStream | clientRequest | clientRequest := anReadAppendStream through: Character cr. (clientRequest startsWith: 'date') ifTrue: [anReadAppendStream nextPutAll: Time dateAndTimeNow printString]. anReadAppendStream closeRunning the Server
server := SimpleDateServer port: 5556. serverProcess := [server run] fork
Simple Server Issues
Client A builds connection to server, Client A goes to lunch Client B builds connection to server and ... :-(
Backlog
TCP accepts connections before the server is ready
TCP keeps a backlog queue of connections server has not accepted
Java ServerSocket constructor
SocketAccessor>>listenFor: aNumber
Multi-homed Machines
Some machines have two or more physical network interface
public ServerSocket(int port)
public ServerSocket(int port, int backlog, InetAddress bindAddress)
Reusing a Port
Closing TCP connections can remain for several minutes
TCP may block use of the port until the connection is gone
This can be annoying in development
SocketAccessor>> soReuseaddr: true
ServerSocket method setReuseAddress(boolean on)
End of Line
Platform |
End
of Line Convention
|
Unix |
Line
Feed (LF)
|
Macintosh |
Carriage
return (CR)
|
Windows |
CR-LF |
End of Line & Smalltalk
Java and Smalltalk programs run on all major platforms
Smalltalk assumes files use platform’s end of line convention
Smalltalk input streams convert platforms end of line to CR
Smalltalk output streams convert CR to platform’s end of line
This makes writing cross platform programs easier
Don’t want this to happen socket streams
BufferedExternalStream>> lineEndTransparent
End of File
On a stream connected to a socket
End of file indicates that the connection has been closed!
Don’t use end of file to determine when other end is done talking!
End of Message
How do we know when we are at the end of a message?
BufferedReader parsedInput = new BufferedReader(new InputStreamReader(in));
char[] message = new char[500]; int sizeRead = parsedInput.read(message, 0, 500);If
End of Message
A good client-server protocol specifies
Buffers
Java & Smalltalk streams are buffered
TCP buffers output before sending
A server cannot read bytes left in a client’s buffer
ExternalStream>>commit
PrintWriter flush();