360 likes | 468 Views
CS18000: Problem Solving and Object-Oriented Programming. External Communication. File I/O. Persistence of File Storage. RAM comes and goes Programs crash Systems reboot Files last (well, comparatively speaking…) Programs save data to files to
E N D
External Communication File I/O
Persistence of File Storage • RAM comes and goes • Programs crash • Systems reboot • Files last (well, comparatively speaking…) • Programs save data to files to • recover from program crashes and system reboots • provide as input to other programs • File I/O operations extend naturally to communication between programs
Files and Java • Java is (or tries to be) platform independent • Provides abstractions for files and file systems • File class • But, file name is operating system (OS) dependent • And, file directory conventions are OS-dependent (e.g., path name of user home directory) • So, there are limits to OS independence • Three layers of abstraction in Java for file I/O • Ultimately, all data stored as a stream of bytes or bits
Example: DirectoryList proxy method // proxy method to setup recursion... ArrayList<File> directoryList(File root) { ArrayList<File> list = newArrayList<File>(); returndirectoryList(list, root); } // recursive method to walk the directory tree (preorder traversal) ArrayList<File> directoryList(ArrayList<File> list, File root) { list.add(root); if (root.isDirectory()) { for (File f : root.listFiles()) { directoryList(list, f); } } returnlist; } visit node recursive call
Generic File Operations (1) • Open: • Files must be opened before they can be used • Open method indicates “for reading”, “for writing”, or “both” • May also indicate “append” mode • Allows operating system to establish “buffers” and other state information about the file being read or written • Read • Transfers data from the file (or input stream) to the user process • Specific method signatures indicate the type of data being transferred (byte, int, String, Tree, etc.) • Write • Transfers data from the user process to the file (or output stream) • Specific method signatures indicate the type of data being transferred (byte, int, String, Tree, etc.)
Generic File Operations (2) • File position • Sets the “current input position” to a specific byte address in the file • Can be used to skip over data in the file; or back up to read data again • Can be used to “rewind” the file to start reading from the beginning again • Close • Ensures that any “queued data” is “flushed” from the operating system buffers • Frees any operating system resources being dedicated to managing the file
The Importance of Buffering • Without buffering, each read or write may generate physical disk access • Can be extremely slow for large volumes of data • Buffering has OS create internal array • OS reads “more than needed” on input, keeps rest for next call to read method • OS doesn’t send output “right away” to disk drive, waits a while in case another write comes along • Important to close file (or flush buffers) when done
File I/O Layers in Java • Low-Level • “Raw” data transfer: byte-oriented • Classes: FileOutputStream, FileInputStream • High-Level • Java primitive types • Classes: DataOutputStream, DataInputStream • Object I/O • Java object types • Classes: ObjectOutputStream, ObjectInputStream Ultimately, all data stored as a sequence of bytes
Example: Low-Level I/O importjava.io.*; publicclassLowLevelIO { publicstaticvoid main(String[] args) throwsIOException { File f = new File("lowlevel"); FileOutputStreamfos = newFileOutputStream(f); fos.write(42); fos.close(); FileInputStreamfis = newFileInputStream(f); int i = fis.read(); System.out.printf("Read %d\n", i); fis.close(); } }
Example: High-Level I/O import java.io.*; publicclassHighLevelIO { publicstaticvoid main(String[] args) throwsIOException { File f = new File("highlevel"); FileOutputStreamfos = newFileOutputStream(f); DataOutputStream dos = newDataOutputStream(fos); dos.writeInt(1000); dos.close(); FileInputStreamfis = newFileInputStream(f); DataInputStream dis = newDataInputStream(fis); inti = dis.readInt(); System.out.printf("Read %d\n", i); dis.close(); } } dos builds on fos dis builds on fis
Tricky Bits • You must keep track of what you’re doing! • Data values must be read in the same order in which they were written • write int, long, long, boolean, double, float, char • read int, long, long, boolean, double, float, char • If you try to read an int, but a double is next in the stream, you’ll get garbage
Example: Object I/O (1) importjava.io.*; publicclassObjectIO { publicstaticvoid main(String[] args) throwsException { File f = new File("object"); FileOutputStreamfos = newFileOutputStream(f); ObjectOutputStreamoos = newObjectOutputStream(fos); Tree tree1 = new Tree(42, "elm"); oos.writeObject(tree1); // write the object out oos.close(); FileInputStreamfis = newFileInputStream(f); ObjectInputStreamois = newObjectInputStream(fis); Tree tree2 = (Tree) ois.readObject(); // read the object back ois.close(); System.out.printf("tree1 = %s\n", tree1); System.out.printf("tree2 = %s\n", tree2); } } oos builds on fos ois builds on fis
Example: Object I/O (2) classTree implementsSerializable { longcircumference; String species; Tree(long circumference, String species) { this.circumference = circumference; this.species = species; } public String toString() { returnString.format("%x: circumference = %d, species = %s", hashCode(), circumference, species); } }
Object I/O: Notes • Fields declared static or transient are not written out • static: logical, since doesn’t apply to specific object • transient: useful for fields that need to be regenerated anyway • Graphs of objects can be written • writing one object also writes all serializable objects connected to it • only writes one copy of each object, even when there are multiple references to it
File Content Types • Can consider file contents in two categories • Text (e.g., *.java, *.txt) • Store human-readable, character data • Mostly platform independent (except EOL) • Binary (e.g., *.class, *.exe) • Not (generally) human readable • Store any kind of data • Requires specific programs to “make sense” of it
Writing and Reading Text • Java handles translation from internal primitive format to human-readable text • Writing • Class: PrintWriter(favored, more platform independent) • Class: PrintStreamfor System.out (but out of favor) • Reading • Classes: FileReader and BufferedReader • Also, Scanner • Note: BufferedReader is more efficient than Scanner (only important for high volumes of I/O)
Example: TextIO (1) importjava.io.*; publicclassTextIO { publicstaticvoid main(String[] args) throwsIOException { File f = new File("textio"); // open FileOutputStream in append mode (true) FileOutputStreamfos = newFileOutputStream(f, true); // use PrintWriter--similar to PrintStream (like System.out)... PrintWriter pw = newPrintWriter(fos); pw.println("our old friend"); pw.close(); // continued...
Example: TextIO (2) // ... continued // read what we just wrote... FileReaderfr = newFileReader(f); BufferedReaderbfr = newBufferedReader(fr); while (true) { String s = bfr.readLine(); if (s == null) break; System.out.println(s); } bfr.close(); } }
External Communication Network Communication
Some (Simplified) Definitions • Internet Protocol (IP):Identifies hosts (servers, workstations, laptops, etc.) with a unique address (e.g., 128.10.2.21) • Domain Name System (DNS):Maps domain names (e.g., galahad.cs.purdue.edu) to IP addresses (e.g., 128.10.9.143) • Transmission Control Protocol (TCP):Identifies ports on hosts for a network connection • Socket: IP address plus TCP port • Two sockets makes a network connection
Client-Server • A Server is a process that waits for a connection • A Client is a process that connects to a server • At different times, a process may be both a client and a server • Need not be associated with a specific computer: Any computer can have both client and server processes running on it • Once connected, the client and server can both read and write data to one another asynchronously (“a bi-directional byte pipe”)
Use of Sockets • Clients and Servers communicate via Sockets • Socket: IP address plus TCP port • Think: street name plus house number • IP addresses • Identifies a computer on the Internet • Public addresses are globally unique • Represented using dotted-decimal (byte) notation: 128.10.9.143 • Some firewalls translate addresses to internal ones (e.g., PAL) • Port number • 0-65535 (16 bits) • Low-valued port numbers are reserved for privileged processes
Objects and Networking in Java • You know that Java objects can be written to and read from files • Java objects can also be exchanged over network connections • Uses ObjectOutputStream and ObjectInputStream • Tricky bits… • ObjectOutputStream generates a “header” of information that must be read • Requires “flush” to ensure ObjectInputStream reader is not blocked
ObjectStream Client-Server Timeline Client Process Server Process Server starts: opens ServerSocket and blocks (waiting for client) Client starts: opens Socket to Server Server receives connection Server opens ObjectOutputStream, sends header with flush Client opens ObjectOutputStream, sends header with flush Server receives object stream header Client receives object stream header Client and Server exchange objects in agreed upon order
Java Networking Class: Socket • Models a TCP/IP socket • Used by Client to identify Server • IP address (or DNS name) • Port number • new Socket("pc.cs.purdue.edu", 12190) • Used by Server to identify connected Client • Provides streams for communications: • getOutputStream() • getInputStream()
Java Networking Class: ServerSocket • Used by Server to wait for a Client to connect • Constructor specifies TCP port number to use: ServerSocketss = new ServerSocket(4242); • Method accept() blocks waiting for connection Socket socket = ss.accept();
Example: Object Server importjava.io.*; importjava.net.*; publicclass Server { publicstaticvoid main(String[] args) throwsIOException, ClassNotFoundException { // create socket on agreed-upon port... ServerSocketserverSocket = newServerSocket(4242); // wait for client to connect, get socket connection... Socket socket = serverSocket.accept(); // open output stream to client, flush send header, then input stream... ObjectOutputStreamoos = newObjectOutputStream(socket.getOutputStream()); oos.flush(); // ensure data is sent to the client ObjectInputStreamois = newObjectInputStream(socket.getInputStream()); // send object(s) to client... String s1 = "hello there"; oos.writeObject(s1); oos.flush(); // ensure data is sent to the client System.out.printf("sent to client: %s\n", s1); // read object(s) from client... String s2 = (String) ois.readObject(); System.out.printf("received from client: %s\n", s2); // close streams... oos.close(); ois.close(); } }
Example: Object Client importjava.io.*; importjava.net.*; publicclass Client { publicstaticvoid main(String[] args) throwsUnknownHostException, IOException,ClassNotFoundException{ // create socket on agreed upon port (and local host for this example)... Socket socket = new Socket("data.cs.purdue.edu", 4242); // open input stream first, gets header from server... ObjectInputStreamois = newObjectInputStream(socket.getInputStream()); // open output stream second, sends header to server... ObjectOutputStreamoos = newObjectOutputStream(socket.getOutputStream()); // read object(s) from server... String s1 = (String) ois.readObject(); System.out.printf("received from server: %s\n", s1); // write object(s) to server... String s2 = s1.toUpperCase(); oos.writeObject(s2); oos.flush(); // ensure data is sent to the server System.out.printf("sent to server: %s\n", s2); // close streams... oos.close(); ois.close(); } }
Client-Server with Threads • In many (most?) cases, a single server is connected to by multiple clients • Server must be able to communicate with all clients simultaneously—no blocking • Technique: server creates a separate thread to handle each client as it connects • Client and server may also each create separate thread for reading and writing
Example: Echo Server • Simple server that accepts connections from multiple clients • Spawns a thread for each client • Reads lines from the connection, logs information, echoes lines back • Useful for debugging network and code
Echo Server Timeline Client Process Server Process Server starts: opens ServerSocket and blocks (waiting for client) Client 1 starts: opens Socket to Server Server receives connection Client 2 starts: opens Socket to Server Server creates thread Client 3 starts: opens Socket to Server Client 1 sends line Server thread 1 reads/echoes line Client 1 reads line
Example: Echo Server (1) importjava.io.IOException; importjava.io.PrintWriter; importjava.net.ServerSocket; importjava.net.Socket; importjava.util.Scanner; publicclassEchoServerimplements Runnable { Socket socket; publicEchoServer(Socket socket) { this.socket = socket; } // continued…
Example: Echo Server (2) // run method for thread... publicvoid run() { System.out.printf("connection received from %s\n", socket); try { // socket open: make PrinterWriter and Scanner from it... PrintWriter pw = newPrintWriter(socket.getOutputStream()); Scanner in = new Scanner(socket.getInputStream()); // read from input, and echo output... while (in.hasNextLine()) { String line = in.nextLine(); System.out.printf("%s says: %s\n", socket, line); pw.printf("echo: %s\n", line); pw.flush(); } // inputdone, closeconnections... pw.close(); in.close(); } catch (IOException e) { e.printStackTrace(); } }
Example: Echo Server (3) // main method... publicstaticvoid main(String[] args) throwsIOException { // allocate server socket at given port... ServerSocketserverSocket = newServerSocket(4343); System.out.printf("socket open, waiting for connections on %s\n",serverSocket); // infinite server loop: accept connection, // spawn thread to handle... while (true) { Socket socket = serverSocket.accept(); EchoServer server = newEchoServer(socket); new Thread(server).start(); } } }
Network Communication in Java • Uses standard file I/O classes: low-level, high-level, object, and text • Adds abstractions to deal with network connections • ServerSocket to wait for connections • Socket abstracts a TCP socket (IP address + port) • Uses threads to improve responsiveness and avoid blocking