Java 網路程式設計範例
The materials in this web page are collected from Java Network Programming and Distributed Computing written by David Reilly and Michael Reilly and the Internet. They are solely used for educational purposes. Hopefully, I am not violating any copyright issue here. If so, please do email me.Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu
請勿轉貼
看其他教材
目錄
- java.net.InetAddress
- Data Streams
- User Datagram Protocol
- Transmission Control Protocol
- 執行緒:Multi-Threading
- Some application protocols
- Java Multicasting
java.net.InetAddress
- Example 1.
import java.net.*; public class TestInet1 { public static void main(String argv[]) { try { InetAddress myip = InetAddress.getLocalHost(); System.out.println(myip.getHostName()); System.out.println(myip.getHostAddress()); } catch (UnknownHostException e) { System.out.println("Error: unable to resolve localhost"); } } }
- 練習題: 請將 /etc/hosts 的內容作修正,例如在 localhost 之後加上一個你喜歡的名稱,再將以上的程式執行一次,並看看他的結果。
- Example 2.
import java.net.*; public class TestInet2 { public static void main(String argv[]) throws UnknownHostException { // obtain an InetAddress of a hostname or IP address string // an IP address may be associated with many hostname // you can also check out this example by using nslookup InetAddress[] myip1 = InetAddress.getAllByName("java.sun.com"); // print out its IP address System.out.println("java.sun.com:"); for(int i=0; i<myip1.length; i++) System.out.println(myip1[i].getHostAddress()); // NOTE: there is a bug for J2SE 1.4.0_00-b05 on Solaris // if an address of java.sun.com was entered, it returns // no hostname. // Please try out the other three IP addresses InetAddress[] myip2 = InetAddress.getAllByName("128.11.159.83"); System.out.println("128.11.159.83"); // if hostname is null, the loopback is returned //InetAddress[] myip2 = InetAddress.getAllByName(null); //System.out.println("null (or loopback):"); for(int i=0; i<myip2.length; i++) { System.out.println(myip2[i].getHostName()); System.out.println(myip2[i].getHostAddress()); } } }
- 練習題: 請利用 JOptionPane 寫一個簡易型的 nslookup 的工具.
Data Streams
- java.io.InputStream
- Example 1
import java.io.*; // Chapter 4, Listing 1 public class FileInputStreamDemo { public static void main(String args[]) { if (args.length != 1) { System.err.println ("Syntax - FileInputStreamDemo file"); return; } // Caution: what are the exceptions needs to be handled? try { // Create an input stream, reading from the specified file InputStream fileInput = new FileInputStream ( args[0] ); // Read the first byte of data int data = fileInput.read(); // Repeat : until end of file (EOF) reached while (data != -1) { // Send byte to standard output System.out.write ( data ); // Read next byte data = fileInput.read(); } // Close the file fileInput.close(); } catch (IOException ioe) { System.err.println ("I/O error - " + ioe); } } }
- 練習題: 請利用 int read() 以及 int read(byte[] byteArray) 來讀取一個檔案。
- 練習題: 執行程式的時候如果發生錯誤,如何判斷是開檔的時候錯誤 還是讀取檔案的時候出錯?
- Example 2: read data from users by using System.in.
// Interactively communicating with the user import java.io.*; public class PersonalHello { public static void main( String argv[] ) { byte name[] = new byte[100]; int nr_read = 0; // System.out is a PrintStream object System.out.print("What is your name? "); try { // System.in is an InputStream object nr_read = System.in.read(name); System.out.print("\nHello "); System.out.write(name, 0, nr_read); } // for jdk 1.1.x, if you input nothing, an IOException will be // thrown. For jdk 1.3.x and up, it will not. catch (IOException e) { System.out.println("I'm sorry. I didn't catch your name."); } } }
- Example 1
- java.io.OutputStream
- Example 1
import java.io.*; // Chapter 4, Listing 2 public class FileOutputStreamDemo { public static void main(String args[]) { // Two parameters are required, the source and destination if (args.length != 2) { System.err.println ("Syntax - FileOutputStreamDemo src dest"); return; } String source = args[0]; String destination = args[1]; try { // Open source file for input InputStream input = new FileInputStream( source ); System.out.println ("Opened " + source + " for reading."); // Ouput output file for output OutputStream output = new FileOutputStream ( destination ); // NOTE 1: To append data to the existing file, we use //OutputStream output = new FileOutputStream( destination, true ); // NOTE 2: If the file exists but is a directory rather than a // regular file, does not exist but cannot be created, or cannot // be opened for any other reason then a FileNotFoundException is // thrown. System.out.println ("Opened " + destination + " for writing."); int data = input.read(); while ( data != -1) { // Write byte of data to our file // Note that only one byte is written to // the output stream. The byte to be written is the eight // low-order bits of the argument b. The 24 high-order bits of b // are ignored. output.write (data); // Read next byte data=input.read(); } // Close both streams input.close(); output.close(); System.out.println ("I/O streams closed"); } catch (IOException ioe) { System.err.println ("I/O error - " + ioe); } } }
- 練習題: 請更改以上的範例使得使用者可以知道究竟讀檔的時候 出錯或者是寫檔的時候出錯。
- Example 1
- Filter Streams
- Example 1
import java.io.*; public class TestFilter1 { public static void main(String args[]) { if (args.length != 2) { System.err.println ("Syntax - TestFilter1 src dest"); return; } String source = args[0]; String destination = args[1]; try { // Open source file for input InputStream input = new FileInputStream(source); // chain input to filter DataInputStream to use readLine() // note that readLine() is deprecated DataInputStream din = new DataInputStream(input); // NOTE: if the object input will not be used later, we can // DataInputStream din = new DataInputStream( // new FileInputStream(source)); System.out.println ("Opened " + source + " for reading."); // Ouput output file for output OutputStream output = new FileOutputStream ( destination ); // chain output to filter PrintStream to use println() PrintStream pout = new PrintStream(output); System.out.println ("Opened " + destination + " for writing."); // readLine() is deprecated since v1.1. It was used only for // demonstration purpose. Also, the encoding is not converted // correctly. String line = din.readLine(); // when EOF is read, readLine() returns null while ( line != null) { pout.println (line); // Read next line line=din.readLine(); } // Close all streams din.close(); pout.close(); input.close(); output.close(); System.out.println ("I/O streams closed"); } catch (IOException ioe) { System.err.println ("I/O error - " + ioe); } } }
- 練習題: 請利用 java.io.InputStream 以及 java.io.BufferedInputStream 來讀取一個大型的檔案,並比較它們效率的差異。(你可以把一個檔案重複 append 多次來完成一個大的檔案)
- Example 2
import java.io.*; public class TestDataInput { public static void main( String[] argv ) { try { // connect to one filter stream and one low-level stream // is it all right to remove BufferedOutputStream? DataOutputStream out = new DataOutputStream( new BufferedOutputStream( new FileOutputStream("Data.txt"))); out.writeDouble(3.14159); out.writeUTF("That was pi"); out.writeDouble(1.41413); out.writeUTF("開根號之後的值"); out.close(); // check out the file Data.txt. DataInputStream in = new DataInputStream( new BufferedInputStream( new FileInputStream("Data.txt"))); // Must use DataInputStream for data: System.out.println(in.readDouble()); // Only readUTF() will recover the // Java-UTF String properly: System.out.println(in.readUTF()); // Read the following double and String: System.out.println(in.readDouble()); System.out.println(in.readUTF()); } catch(EOFException e) { throw new RuntimeException(e); } catch(IOException e) { System.out.println("I/O 錯誤"); } } }
- Example 3
import java.io.*; public class TestPushBack { public static void main( String[] argv ) { try { // declare a pushback input stream and a buffer of size 2 PushbackInputStream in = new PushbackInputStream( new FileInputStream("Data.txt"), 2); byte data[] = new byte[2]; // read the first two bytes in.read(data); System.out.println("Read: " + data[0] + " and " + data[1]); // push the data back in.unread(data); // re-read data. in.read(data); System.out.println("Re-read: " + data[0] + " and " + data[1]); System.out.println("Both byte should be the same!"); } catch(IOException e) { System.out.println("I/O 錯誤"); } } }
- Example 1
- Readers and Writers
- Example 1
import java.io.*; public class TestStringReader { public static void main( String[] argv ) { String msg = "Hello 老呂"; try { StringReader in = new StringReader(msg); // check to see if mark/reset is supported if (in.markSupported()) System.out.println("StringReader supports mark/reset"); // skip 6 chars in.skip(6); // read next char and print it out System.out.println("next character is " + (char) in.read()); // move the pointer back the first char in.reset(); System.out.println("1st character is " + (char) in.read()); } catch(IOException e) { System.out.println("I/O 錯誤"); } } }
- Example 2: read users' input from BufferedReader
import java.io.*; // Chapter 4, Listing 3 // Combining Streams and Readers public class InputStreamToReaderDemo { public static void main(String args[]) { try { System.out.print ("Please enter your name : "); // Get the input stream representing standard input InputStream input = System.in; // Create an InputStreamReader InputStreamReader reader = new InputStreamReader ( input ); // Connect to a buffered reader, to use the readLine() method BufferedReader bufReader = new BufferedReader ( reader ); String name = bufReader.readLine(); System.out.println ("Pleased to meet you, " + name); } catch (IOException ioe) { System.err.println ("I/O error : " + ioe); } } }
- Example 1
Object Persistence and Serialization
- Example 1
import java.io.*; import java.util.*; // Chapter 4, Listing 5 public class SerializationDemo { public static void main(String args[]) { try { // Vector is Serializable Vector list; // Create a buffered reader for easy input BufferedReader reader = new BufferedReader ( new InputStreamReader ( System.in ) ); System.out.println ("Checking for previous serialized list"); // Check to see if serialized list exists // NOTE: nested try statements try { // after executing the program, check out list.out FileInputStream fin = new FileInputStream("list.out"); // Connect an object input stream to the list ObjectInputStream oin = new ObjectInputStream(fin); try { // Read the vector back from the list Object obj = oin.readObject(); // Cast back to a vector list = (Vector) obj; } catch (ClassCastException cce) { // Can't cast it, create a blank one list = new Vector(); } catch (ClassNotFoundException cnfe) { // Can't read it, create a blank one list = new Vector(); } fin.close(); } catch (FileNotFoundException fnfe) { // Create a blank vector list = new Vector(); } // Repeat indefinitely for (;;) { // Now, display menu System.out.println ("Menu :-"); System.out.println ("1.. Add item"); System.out.println ("2.. Delete item"); System.out.println ("3.. List items"); System.out.println ("4.. Save and quit"); System.out.print ("Choice : "); // Read choice String response = reader.readLine(); // Convert to an int int choice = Integer.parseInt (response); switch (choice) { case 1 : // Add the item to list System.out.print ("Enter item : "); String item = reader.readLine(); list.addElement(item); break; case 2 : // Delete the item from list System.out.print ("Enter item : "); String deadItem = reader.readLine(); list.removeElement(deadItem); break; case 3 : // List the elements of the list for (Enumeration e = list.elements(); e.hasMoreElements();) System.out.println (e.nextElement()); break; case 4 : // Save list and terminate System.out.println ("Saving list"); FileOutputStream fout = new FileOutputStream("list.out"); // Construct an object output stream ObjectOutputStream oout = new ObjectOutputStream(fout); // Write the object to the stream oout.writeObject (list); fout.close(); System.exit(0); } } } catch (IOException ioe) { System.err.println ("I/O error"); } } }
- Example 2
//: c12:Worm.java // Demonstrates object serialization. // {Clean: worm.out} import java.io.*; import java.util.*; class Data implements Serializable { private int n; public Data(int n) { this.n = n; } public String toString() { return Integer.toString(n); } } public class Worm implements Serializable { private static Random rand = new Random(); private Data[] d = { new Data(rand.nextInt(10)), new Data(rand.nextInt(10)), new Data(rand.nextInt(10)) }; // to create a link list // the last Worm segment is initialized to null. private Worm next; private char c; // Value of i == number of segments public Worm(int i, char x) { System.out.println("Worm constructor: " + i); c = x; if(--i > 0) next = new Worm(i, (char)(x + 1)); } // this is the default argument which is a must public Worm() { System.out.println("Default constructor"); } public String toString() { String s = ":" + c + "("; for(int i = 0; i < d.length; i++) s += d[i]; s += ")"; if(next != null) s += next; // identical to s += next.toString() return s; } // Throw exceptions to console: public static void main(String[] args) throws ClassNotFoundException, IOException { // instatiate a Worm and serialize it to worm.out Worm w = new Worm(6, 'a'); System.out.println("w = " + w); ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("worm.out")); out.writeObject("Worm storage\n"); out.writeObject(w); out.close(); // Also flushes output // deserialize the worm from worm.out ObjectInputStream in = new ObjectInputStream( new FileInputStream("worm.out")); String s = (String)in.readObject(); Worm w2 = (Worm)in.readObject(); System.out.println(s + "w2 = " + w2); // You can read and write an object using serialization to any // DataInputStream or DataOutputStream. In the followings, we use // ByteArrayOutputStream as example. ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream out2 = new ObjectOutputStream(bout); out2.writeObject("Worm storage\n"); out2.writeObject(w); out2.flush(); ObjectInputStream in2 = new ObjectInputStream( new ByteArrayInputStream(bout.toByteArray())); s = (String)in2.readObject(); Worm w3 = (Worm)in2.readObject(); System.out.println(s + "w3 = " + w3); } }
- Example 3: the transient keyword
//: c12:Logon.java // Demonstrates the "transient" keyword. // {Clean: Logon.out} import java.io.*; import java.util.*; public class Logon implements Serializable { private Date date = new Date(); private String username; private transient String password; // NOTE that there is no default constructor public Logon(String name, String pwd) { username = name; password = pwd; } public String toString() { String pwd = (password == null) ? "(n/a)" : password; return "logon info: \n username: " + username + "\n date: " + date + "\n password: " + pwd; } public static void main(String[] args) throws Exception { Logon a = new Logon("Hulk", "myLittlePony"); System.out.println( "logon a = " + a); ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream("Logon.out")); o.writeObject(a); o.close(); Thread.sleep(1000); // Delay for 1 second // Now get them back: ObjectInputStream in = new ObjectInputStream( new FileInputStream("Logon.out")); System.out.println("Recovering object at "+new Date()); a = (Logon)in.readObject(); System.out.println("logon a = " + a); } }
User Datagram Protocol
- Example 1
- PacketReceiveDemo.java
import java.net.*; import java.io.*; // Chapter 5, Listing 1 public class PacketReceiveDemo { public static void main (String args[]) { try { System.out.println ("Binding to local port 2000"); // Create a datagram socket, bound to the specific port 2000 DatagramSocket socket = new DatagramSocket(2000); System.out.println ("Bound to local port " + socket.getLocalPort()); // Create a datagram packet, containing a maximum buffer of 256 bytes byte[] buf = new byte[256]; DatagramPacket packet = new DatagramPacket( new byte[256], 256 ); // Receive a packet - remember by default this is a blocking operation socket.receive(packet); System.out.println ("Packet received!"); // Display packet information InetAddress remote_addr = packet.getAddress(); System.out.println ("Sent by : " + remote_addr.getHostAddress() ); System.out.println ("Send from: " + packet.getPort()); // Or, 你只需要 //System.out.println(new String(buf)); // Display packet contents, by reading from byte array ByteArrayInputStream bin = new ByteArrayInputStream (packet.getData()); // Display only up to the length of the original UDP packet for (int i=0; i < packet.getLength(); i++) { int data = bin.read(); if (data == -1) break; else System.out.print ( (char) data) ; } socket.close(); } catch (IOException ioe) { System.err.println ("Error - " + ioe); } } }
- PacketSendDemo.java
import java.net.*; import java.io.*; // Chapter 5, Listing 2 // If the corresponding receive process is not running, the message // will be discarded at the destination. public class PacketSendDemo { public static void main(String args[]) { int argc = args.length; if(argc != 1) { System.out.println("Syntax:"); System.out.println("java PacketSendDemo hostname"); return; } String hostname = args[0]; try { System.out.println("Binding to a local port"); // Create a datagram socket, bound to nay available local port DatagramSocket socket = new DatagramSocket(); System.out.println("Bound to local port " + socket.getLocalPort()); // Create a message to send using a UDP packet ByteArrayOutputStream bout = new ByteArrayOutputStream(); PrintStream pout = new PrintStream(bout); pout.print("Greetings 大家"); // Get the contents of our message as an array of bytes byte[] barray = bout.toByteArray(); // Or, 你只需要 //byte[] barray = "Greetings 大家".getBytes(); // 注意,要能顯示中文,你必須確定你的系統能支援,例如 // 在 Solaris,server 端要設定 // setenv LANG="zh_TW.BIG5" // setenv LC_CTYPE="zh_TW.BIG5" // Create a datagram packet DatagramPacket packet = new DatagramPacket(barray, barray.length); // Or, you can //DatagramPacket packet = new DatagramPacket(barray, barray.length, // InetAddress.getByName(hostname), 2000); System.out.println("Looking up hostname " + hostname); // Looking up the specified hostname and get InetAddress InetAddress remote = InetAddress.getByName(hostname); System.out.println("Hostname resolved as " + remote.getHostAddress()); // Address packet to sender // NOTE: it is the DatagramPacket which requires to know its // destination. packet.setAddress(remote); // set port number to 2000 packet.setPort(2000); // send the packet socket.send(packet); System.out.println("Packet sent!"); } catch (UnknownHostException e) { System.err.println("Cannot find host " + hostname); } catch (IOException e) { System.err.println("Error - " + e); } } }
- 練習題: What if the size of the sending messages is larger than the size specified in the receiving end?
- 練習題: Since the size for each IP packet is 1500, try to send a message of size larger than 1500 and see what happened?
- PacketReceiveDemo.java
- Example: echo service
- EchoServer.java
import java.net.*; import java.io.*; // Chapter 5, Listing 3 public class EchoServer { // UDP port to which service is bound public static final int SERVICE_PORT = 2007; // Max size of packet, large enough for almost any client public static final int BUFSIZE = 4096; // Socket used for reading and writing UDP packets private DatagramSocket socket; public EchoServer() { try { // Bind to the specified UDP port, to listen // for incoming data packets socket = new DatagramSocket( SERVICE_PORT ); System.out.println ("Server active on port " + socket.getLocalPort() ); } catch (Exception e) { System.err.println ("Unable to bind port"); } } public void serviceClients() { // Create a buffer large enough for incoming packets byte[] buffer = new byte[BUFSIZE]; for (;;) { try { // Create a DatagramPacket for reading UDP packets DatagramPacket packet = new DatagramPacket ( buffer, BUFSIZE ); // Receive incoming packets socket.receive(packet); System.out.println ("Packet received from " + packet.getAddress() + ":" + packet.getPort() + " of length " + packet.getLength() ); // added for ensuring data is received System.out.println(new String(packet.getData(), 0, packet.getLength())); // the following is not appropriate for printing. Why? //System.out.println(new String(packet.getData())); // Echo the packet back - address and port // are already set for us ! socket.send(packet); } catch (IOException ioe) { System.err.println ("Error : " + ioe); } } } public static void main(String args[]) { EchoServer server = new EchoServer(); server.serviceClients(); } }
- EchoClient.java
import java.net.*; import java.io.*; // Chapter 5, Listing 4 // 由於 udp 支援一對多,所以同一個 server 可以對多個 client 作 echo public class EchoClient { // UDP port to which service is bound public static final int SERVICE_PORT = 2007; // Max size of packet public static final int BUFSIZE = 256; public static void main(String args[]) { if (args.length != 1) { System.err.println ("Syntax - java EchoClient hostname"); return; } String hostname = args[0]; // Get an InetAddress for the specified hostname InetAddress addr = null; try { // Resolve the hostname to an InetAddr addr = InetAddress.getByName(hostname); } catch (UnknownHostException uhe) { System.err.println ("Unable to resolve host"); return; } try { // Bind to any free port DatagramSocket socket = new DatagramSocket(); // Set a timeout value of two seconds // setSoTimeout() in milliseconds // the number of ms a read operation will block before throwing // exception. socket.setSoTimeout (2 * 1000); String message; for (int i = 1 ; i <= 10; i++) { // Copy some data to our packet message = "封包編號 " + i ; byte[] sendbuf = message.getBytes(); // the followings can also be used to convert string to byte array // but Big5 message cannot be convertted correctly. // char[] cArray = message.toCharArray(); // byte[] sendbuf = new byte[cArray.length]; // for (int offset = 0; offset < cArray.length ; offset++) { // sendbuf[offset] = (byte) cArray[offset]; // } // Create a packet to send to the UDP server DatagramPacket sendPacket = new DatagramPacket(sendbuf, sendbuf.length, addr, SERVICE_PORT); // cArray.length, addr, SERVICE_PORT); System.out.println ("Sending packet to " + hostname); // Send the packet socket.send (sendPacket); System.out.print ("Waiting for packet.... "); // Create a small packet for receiving UDP packets byte[] recbuf = new byte[BUFSIZE]; DatagramPacket receivePacket = new DatagramPacket(recbuf, BUFSIZE); // Declare a timeout flag boolean timeout = false; // Catch any InterruptedIOException that is thrown // while waiting to receive a UDP packet try { socket.receive (receivePacket); } catch (InterruptedIOException ioe) { timeout = true; } if (!timeout) { System.out.println ("packet received!"); System.out.println ("Details : " + receivePacket.getAddress() ); // Obtain a byte input stream to read the UDP packet ByteArrayInputStream bin = new ByteArrayInputStream ( receivePacket.getData(), 0, receivePacket.getLength() ); // Connect a reader for easier access BufferedReader reader = new BufferedReader ( new InputStreamReader ( bin ) ); // Loop indefinitely String line; for (;;) { line = reader.readLine(); // Check for end of data if (line == null) break; else System.out.println (line); } } else { System.out.println ("packet lost!"); } // Sleep for a second, to allow user to see packet try { Thread.sleep(1000); } catch (InterruptedException ie) {} } } catch (IOException ioe) { System.err.println ("Socket error " + ioe); } } }
- 練習題: (1) 請嘗試把多個 client 對同一個 server 作傳送的動作, 並觀察封包到達的順序以及情形。(2) 經過 Internet 的傳送,看看有沒有掉封包的 情形。
- 練習題: Please provide a Time service that returns time and date String like 民國 93 年 10 月 18 日上午 11 點 23 分。
- EchoServer.java
- Example 3
- DataRecv.java
import java.net.*; import java.io.*; public class DataRecv { // UDP port to which service is bound public static final int SERVICE_PORT = 2007; // Max size of packet, large enough for almost any client public static final int BUFSIZE = 4096; // Socket used for reading and writing UDP packets private DatagramSocket socket; // Received Buffer private String recvbuf[] = new String[10]; public DataRecv() { try { // Bind to the specified UDP port, to listen // for incoming data packets socket = new DatagramSocket( SERVICE_PORT ); // set timeout value to 10 seconds. // try out with different timeout values: 10 vs. 2 (for example) socket.setSoTimeout(10 * 1000); System.out.println ("Server active on port " + socket.getLocalPort() ); } catch (Exception e) { System.err.println ("Unable to bind port"); } } public void serviceClients() { // Create a buffer large enough for incoming packets byte[] buffer = new byte[BUFSIZE]; String m = null; int count = 0; for (;;) { try { // Create a DatagramPacket for reading UDP packets DatagramPacket packet = new DatagramPacket ( buffer, BUFSIZE ); // Receive incoming packets socket.receive(packet); System.out.println ("Packet received from " + packet.getAddress() + ":" + packet.getPort() + " of length " + packet.getLength() ); m = new String(packet.getData(), 0, packet.getLength()); count = Integer.parseInt(String.valueOf(m.charAt(0))); recvbuf[count] = new String(m); } catch (SocketException e) { System.err.println("Timeout exceed!"); } catch (IOException ioe) { System.err.println ("Error : " + ioe); } // print out what we have received for(int i=0; i<recvbuf.length; i++) if(recvbuf[i] != null) System.out.println(recvbuf[i]); } } public static void main(String args[]) { DataRecv server = new DataRecv(); server.serviceClients(); } }
- DataSent.java
import java.net.*; import java.io.*; public class DataSent { // UDP port to which service is bound public static final int SERVICE_PORT = 2007; // Max size of packet public static final int BUFSIZE = 256; // Initializa messages, which can be read from a file // the arriving order of packets can be observed when it hits 50 // with the connection between penguin and dns. private static String[] messages = {"0 I love Java!", "1 I love programming.", "2 I love networking.", "3 I love network programming.", "4 I love Java network programming.", "5 我愛 Java!", "6 我愛 programming.", "7 我愛 networking.", "8 我愛 network programming.", "9 我愛 Java network programming.", "10 I love Java!", "11 I love programming.", "12 I love networking.", "13 I love network programming.", "14 I love Java network programming.", "15 我愛 Java!", "16 我愛 programming.", "17 我愛 networking.", "18 我愛 network programming.", "19 我愛 Java network programming.", "20 I love Java!", "21 I love programming.", "22 I love networking.", "23 I love network programming.", "24 I love Java network programming.", "25 我愛 Java!", "26 我愛 programming.", "27 我愛 networking.", "28 我愛 network programming.", "29 我愛 Java network programming.", "30 I love Java!", "31 I love programming.", "32 I love networking.", "33 I love network programming.", "34 I love Java network programming.", "35 我愛 Java!", "36 我愛 programming.", "37 我愛 networking.", "38 我愛 network programming.", "39 我愛 Java network programming.", "40 I love Java!", "41 I love programming.", "42 I love networking.", "43 I love network programming.", "44 I love Java network programming.", "45 我愛 Java!", "46 我愛 programming.", "47 我愛 networking.", "48 我愛 network programming.", "49 我愛 Java network programming."}; public static void main(String args[]) { if (args.length != 1) { System.err.println ("Syntax - java EchoClient hostname"); return; } String hostname = args[0]; // Get an InetAddress for the specified hostname InetAddress addr = null; try { // Resolve the hostname to an InetAddr addr = InetAddress.getByName(hostname); } catch (UnknownHostException uhe) { System.err.println ("Unable to resolve host"); return; } try { // Bind to any free port DatagramSocket socket = new DatagramSocket(); // Set a timeout value of two seconds socket.setSoTimeout (2 * 1000); String message = null; for (int i = 0 ; i < messages.length; i++) { // Copy some data to our packet message = messages[i]; byte[] sendbuf = message.getBytes(); // Create a packet to send to the UDP server DatagramPacket sendPacket = new DatagramPacket(sendbuf, sendbuf.length, addr, SERVICE_PORT); // Send the packet which is non-blocking socket.send (sendPacket); System.out.println("Sending packet " + i + "..."); // Sleep for a second, to allow user to see packet // try { // Thread.sleep(1000); // } catch (InterruptedException ie) {} } } catch (IOException ioe) { System.err.println ("Socket error " + ioe); } } }
- DataRecv.java
Transmission Control Protocol
- Example 1
- DaytimeServer.java
import java.net.*; import java.io.*; // Chapter 6, Listing 2 public class DaytimeServer { public static final int SERVICE_PORT = 2013; public static void main(String args[]) { try { // Bind to the service port, to grant clients access to // the TCP daytime service ServerSocket server = new ServerSocket (SERVICE_PORT); System.out.println ("Daytime service started"); // Loop indefinitely, accepting clients for (;;) { // Get the next TCP client Socket nextClient = server.accept(); // Display connection details System.out.println ("Received request from " + nextClient.getInetAddress() + ":" + nextClient.getPort() ); // Don't read, just write the message OutputStream out = nextClient.getOutputStream(); PrintStream pout = new PrintStream (out); // Write the current date out to the user pout.print( new java.util.Date() ); // Flush unsent bytes out.flush(); // Close the connection nextClient.close(); } } catch (BindException be) { System.err.println ("Service already running on port " + SERVICE_PORT ); } catch (IOException ioe) { System.err.println ("I/O error - " + ioe); } } }
- DaytimeClient.java
import java.net.*; import java.io.*; // Chapter 6, Listing 1 public class DaytimeClient { public static final int SERVICE_PORT = 2013; public static void main(String args[]) { // Check for hostname parameter if (args.length != 1) { System.out.println ("Syntax - DaytimeClient host"); return; } // Get the hostname of server String hostname = args[0]; try { // Get a socket to the daytime service Socket daytime = new Socket (hostname, SERVICE_PORT); System.out.println ("Connection established"); // Set the socket option just in case server stalls daytime.setSoTimeout ( 2000 ); // Read from the server BufferedReader reader = new BufferedReader ( new InputStreamReader(daytime.getInputStream())); System.out.println ("Results : " + reader.readLine()); // Close the connection daytime.close(); } catch (IOException ioe) { System.err.println ("Error " + ioe); } } }
- DaytimeServer.java
- Example 2: an on-line chatting
- Server.java
// Fig. 18.4: Server.java // by Deitel & Deitel // Set up a Server that will receive a connection from a client, send // a string to the client, and close the connection. import java.io.*; import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Server extends JFrame { private JTextField enterField; private JTextArea displayArea; private ObjectOutputStream output; private ObjectInputStream input; private ServerSocket server; private Socket connection; private int counter = 1; // set up GUI public Server() { super( "Server" ); Container container = getContentPane(); // create enterField and register listener enterField = new JTextField(); enterField.setEditable( false ); enterField.addActionListener( new ActionListener() { // send message to client public void actionPerformed( ActionEvent event ) { sendData( event.getActionCommand() ); enterField.setText( "" ); }} ); container.add( enterField, BorderLayout.NORTH ); // create displayArea displayArea = new JTextArea(); container.add(new JScrollPane( displayArea ), BorderLayout.CENTER ); setSize( 300, 150 ); setVisible( true ); } // end Server constructor // set up and run server public void runServer() { // set up server to receive connections; process connections try { // Step 1: Create a ServerSocket. server = new ServerSocket(12345); while ( true ) { try { waitForConnection(); // Step 2: Wait for a connection. getStreams(); // Step 3: Get input & output streams. processConnection(); // Step 4: Process connection. } // process EOFException when client closes connection catch ( EOFException eofException ) { System.err.println( "Server terminated connection" ); } finally { closeConnection(); // Step 5: Close connection. ++counter; } } // end while } // end try // process problems with I/O catch ( IOException ioException ) { ioException.printStackTrace(); } } // end method runServer // wait for connection to arrive, then display connection info private void waitForConnection() throws IOException { displayMessage( "Waiting for connection\n" ); connection = server.accept(); // allow server to accept connection displayMessage( "Connection " + counter + " received from: " + connection.getInetAddress().getHostName() ); } // get streams to send and receive data private void getStreams() throws IOException { // set up output stream for objects output = new ObjectOutputStream( connection.getOutputStream() ); output.flush(); // flush output buffer to send header information // set up input stream for objects input = new ObjectInputStream( connection.getInputStream() ); displayMessage( "\nGot I/O streams\n" ); } // process connection with client private void processConnection() throws IOException { // send connection successful message to client String message = "Connection successful"; sendData( message ); // enable enterField so server user can send messages enterField.setEditable( true ); do { // process messages sent from client // read message and display it try { message = ( String ) input.readObject(); displayMessage( "\n" + message ); } // catch problems reading from client catch ( ClassNotFoundException classNotFoundException ) { displayMessage( "\nUnknown object type received" ); } } while ( !message.equals( "CLIENT>>> TERMINATE" ) ); } // end method processConnection // close streams and socket private void closeConnection() { displayMessage( "\nTerminating connection\n" ); enterField.setEditable( false ); // disable enterField try { output.close(); input.close(); connection.close(); } catch( IOException ioException ) { ioException.printStackTrace(); } } // send message to client private void sendData( String message ) { // send object to client try { output.writeObject( "SERVER>>> " + message ); output.flush(); displayMessage( "\nSERVER>>> " + message ); } // process problems sending object catch ( IOException ioException ) { displayArea.append( "\nError writing object" ); } } private void displayMessage( final String messageToDisplay ) { displayArea.append( messageToDisplay ); displayArea.setCaretPosition(displayArea.getText().length() ); } public static void main( String args[] ) { Server application = new Server(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.runServer(); } }
- Client.java
// Fig. 18.5: Client.java // by Deitel & Deitel // Client that reads and displays information sent from a Server. import java.io.*; import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Client extends JFrame { private JTextField enterField; private JTextArea displayArea; private ObjectOutputStream output; private ObjectInputStream input; private String message = ""; private String chatServer; private Socket client; // initialize chatServer and set up GUI public Client( String host ) { super( "Client" ); chatServer = host; // set server to which this client connects Container container = getContentPane(); // create enterField and register listener enterField = new JTextField(); enterField.setEditable( false ); enterField.addActionListener( new ActionListener() { // send message to server public void actionPerformed( ActionEvent event ) { sendData( event.getActionCommand() ); enterField.setText( "" ); } } ); container.add( enterField, BorderLayout.NORTH ); // create displayArea displayArea = new JTextArea(); container.add(new JScrollPane(displayArea), BorderLayout.CENTER); setSize( 300, 150 ); setVisible( true ); } // end Client constructor // connect to server and process messages from server private void runClient() { // connect to server, get streams, process connection try { connectToServer(); // Step 1: Create a Socket to make connection getStreams(); // Step 2: Get the input and output streams processConnection(); // Step 3: Process connection } // server closed connection catch ( EOFException eofException ) { System.err.println( "Client terminated connection" ); } // process problems communicating with server catch ( IOException ioException ) { ioException.printStackTrace(); } finally { closeConnection(); // Step 4: Close connection } } // connect to server private void connectToServer() throws IOException { displayMessage( "Attempting connection\n" ); // create Socket to make connection to server client = new Socket( InetAddress.getByName( chatServer ), 12345 ); // display connection information displayMessage( "Connected to: " + client.getInetAddress().getHostName() ); } // get streams to send and receive data private void getStreams() throws IOException { // set up output stream for objects output = new ObjectOutputStream( client.getOutputStream() ); output.flush(); // flush output buffer to send header information // set up input stream for objects input = new ObjectInputStream( client.getInputStream() ); displayMessage( "\nGot I/O streams\n" ); } // process connection with server private void processConnection() throws IOException { // enable enterField so client user can send messages enterField.setEditable( true ); do { // process messages sent from server // read message and display it try { message = ( String ) input.readObject(); displayMessage( "\n" + message ); } // catch problems reading from server catch ( ClassNotFoundException classNotFoundException ) { displayMessage( "\nUnknown object type received" ); } } while ( !message.equals( "SERVER>>> TERMINATE" ) ); } // end method processConnection // close streams and socket private void closeConnection() { displayMessage( "\nClosing connection" ); enterField.setEditable( false ); // disable enterField try { output.close(); input.close(); client.close(); } catch( IOException ioException ) { ioException.printStackTrace(); } } // send message to server private void sendData( String message ) { // send object to server try { output.writeObject( "CLIENT>>> " + message ); output.flush(); displayMessage( "\nCLIENT>>> " + message ); } // process problems sending object catch ( IOException ioException ) { displayArea.append( "\nError writing object" ); } } private void displayMessage( final String messageToDisplay ) { displayArea.append( messageToDisplay ); displayArea.setCaretPosition(displayArea.getText().length() ); } public static void main( String args[] ) { Client application; if ( args.length == 0 ) application = new Client( "127.0.0.1" ); else application = new Client( args[ 0 ] ); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.runClient(); } }
- Server.java
Some Application Protocols
We'll discuss three simple application protocols which include SMTP, POP3, and HTTP/1.0. The details of these protocols can be found at IETF's Request for Comment where you can enter the RFC number to search for the documents. Otherwise, you can use RFC Index Search Engine to search documents by using names.- SMTP Client
The Simple Mail Transfer Protocol is used to send messages of various types between users over a TCP/IP network. The following program is a basic SMTP client which establishes a single connection to a mail server using a TCP socket, followed by a series of short protocol commands that specify the details of the email to be sent. The details is described in RFC 2821. For richer functionality of a SMTP client, please use JavaMail API.
import java.io.*; import java.net.*; import java.util.*; // Chapter 8, Listing 1 public class SMTPClientDemo { protected int port = 25; protected String hostname = "localhost"; protected String from = ""; protected String to = ""; protected String subject = ""; protected String body = ""; protected Socket socket; protected BufferedReader br; protected PrintWriter pw; // Constructs a new instance of the SMTP Client public SMTPClientDemo() throws Exception { try { getInput(); sendEmail(); } catch (Exception e) { System.out.println ("Error sending message - " + e); } } public static void main(String[] args) throws Exception { // Start the SMTP client, so it can send messages SMTPClientDemo client = new SMTPClientDemo(); } // Check the SMTP response code for an error message protected int readResponseCode() throws Exception { String line = br.readLine(); System.out.println("< "+line); line = line.substring(0,line.indexOf(" ")); return Integer.parseInt(line); } // Write a protocol message both to the network socket and to the screen protected void writeMsg(String msg) throws Exception { pw.println(msg); pw.flush(); System.out.println("> "+msg); } // Close all readers, streams and sockets protected void closeConnection() throws Exception { pw.flush(); pw.close(); br.close(); socket.close(); } // Send the QUIT protocol message, and terminate connection protected void sendQuit() throws Exception { System.out.println("Sending QUIT"); writeMsg("QUIT"); readResponseCode(); System.out.println("Closing Connection"); closeConnection(); } // Send an email message via SMTP, adhering to the protocol known as RFC 2821 protected void sendEmail() throws Exception { System.out.println("Sending message now: Debug below"); System.out.println("---------------------------------" + "-----------------------------"); System.out.println("Opening Socket"); socket = new Socket(this.hostname,this.port); System.out.println("Creating Reader & Writer"); br = new BufferedReader(new InputStreamReader(socket.getInputStream())); pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); System.out.println("Reading first line"); int code = readResponseCode(); if(code != 220) { socket.close(); throw new Exception("Invalid SMTP Server"); } System.out.println("Sending helo command"); writeMsg("HELO "+InetAddress.getLocalHost().getHostName()); code = readResponseCode(); if(code != 250) { sendQuit(); throw new Exception("Invalid SMTP Server"); } System.out.println("Sending mail from command"); writeMsg("MAIL FROM:<"+this.from+">"); code = readResponseCode(); if(code != 250) { sendQuit(); throw new Exception("Invalid from address"); } System.out.println("Sending rcpt to command"); writeMsg("RCPT TO:<"+this.to+">"); code = readResponseCode(); if(code != 250) { sendQuit(); throw new Exception("Invalid to address"); } System.out.println("Sending data command"); writeMsg("DATA"); code = readResponseCode(); if(code != 354) { sendQuit(); throw new Exception("Data entry not accepted"); } System.out.println("Sending message"); writeMsg("Subject: "+this.subject); writeMsg("To: "+this.to); writeMsg("From: "+this.from); writeMsg(""); writeMsg(body); code = readResponseCode(); sendQuit(); if(code != 250) throw new Exception("Message may not have been sent correctly"); else System.out.println("Message sent"); } // Obtain input from the user protected void getInput() throws Exception { // Read input from user console String data=null; BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // Request hostname for SMTP server System.out.print("Please enter SMTP server hostname: "); data = br.readLine(); if (data == null || data.equals("")) hostname="localhost"; else hostname=data; // Request the sender's email address System.out.print("Please enter FROM email address: "); data = br.readLine(); from = data; // Request the recipient's email address System.out.print("Please enter TO email address :"); data = br.readLine(); if(!(data == null || data.equals(""))) to=data; System.out.print("Please enter subject: "); data = br.readLine(); subject=data; System.out.println("Please enter plain-text message ('.' character" + "on a blank line signals end of message):"); StringBuffer buffer = new StringBuffer(); // Read until user enters a . on a blank line String line = br.readLine(); while(line != null) { // Check for a '.', and only a '.', on a line if(line.equalsIgnoreCase(".")) { break; } buffer.append(line); buffer.append("\n"); line = br.readLine(); } buffer.append(".\n"); body = buffer.toString(); } }
D:\Test\Java\ch8>java SMTPClientDemo Please enter SMTP server hostname: msa.hinet.net Please enter FROM email address: jlu@linux.csie.ncue.edu.tw Please enter TO email address :jlu@cc.ncue.edu.tw Please enter subject: Test From Home Please enter plain-text message ('.' character on a blank line signals end of me ssage): this is a test 訊息 . Sending message now: Debug below -------------------------------------------------------------- Opening Socket Creating Reader & Writer Reading first line < 220 msr61.hinet.net ESMTP Sendmail V8; Wed, 8 Dec 2004 12:05:18 +0800 (CST) Sending helo command > HELO win < 250 msr61.hinet.net Hello 220-134-107-112.HINET-IP.hinet.net [220.134.107.112], pleased to meet you Sending mail from command > MAIL FROM:<jlu@linux.csie.ncue.edu.tw> < 250 <jlu@linux.csie.ncue.edu.tw>... Sender ok Sending rcpt to command > RCPT TO:<jlu@cc.ncue.edu.tw> < 250 <jlu@cc.ncue.edu.tw>... Recipient ok Sending data command > DATA < 354 Enter mail, end with "." on a line by itself Sending message > Subject: Test From Home > To: jlu@cc.ncue.edu.tw > From: jlu@linux.csie.ncue.edu.tw > > this is a test 訊息 . < 250 MAA00065 Message accepted for delivery Sending QUIT > QUIT < 221 msr61.hinet.net closing connection Closing Connection Message sent
- POP3 Client
The Post Office Protocol version 3 is one of the most popular protocol to receive emails. The following example will retrieve emails from a POP3 server. The POP3 protocol is a RFC 1939 document.import java.io.*; import java.net.*; import java.util.*; public class Pop3ClientDemo { protected int port = 110; protected String hostname = "localhost"; protected String username = ""; protected String password = ""; protected Socket socket; protected BufferedReader br; protected PrintWriter pw; // Constructs a new instance of the POP3 client public Pop3ClientDemo() throws Exception { try { // Get user input getInput(); // Get mail messages displayEmails(); } catch(Exception e) { System.err.println ("Error occured - details follow"); e.printStackTrace(); System.out.println(e.getMessage()); } } // Returns TRUE if POP response indicates success, FALSE if failure protected boolean responseIsOk() throws Exception { String line = br.readLine(); System.out.println("< "+line); // 和 SMTP 不同的地方,POP3 的回覆不再是一個 number 而是 // +OK 來代表要求成功。失敗則以 -ERR 來代表。 return line.toUpperCase().startsWith("+OK"); } // Reads a line from the POP server, and displays it to screen protected String readLine(boolean debug) throws Exception { String line = br.readLine(); // Append a < character to indicate this is a server protocol response if (debug) System.out.println("< "+line); else System.out.println(line); return line; } // Writes a line to the POP server, and displays it to the screen protected void writeMsg(String msg) throws Exception { pw.println(msg); pw.flush(); System.out.println("> "+msg); } // Close all writers, streams and sockets protected void closeConnection() throws Exception { pw.flush(); pw.close(); br.close(); socket.close(); } // Send the QUIT command, and close connection protected void sendQuit() throws Exception { System.out.println("Sending QUIT"); writeMsg("QUIT"); readLine(true); System.out.println("Closing Connection"); closeConnection(); } // Display emails in a message protected void displayEmails() throws Exception { BufferedReader userinput = new BufferedReader( new InputStreamReader (System.in) ); System.out.println("Displaying mailbox with protocol commands" + "and responses below"); System.out.println("-----------------------------------------" + "---------------------"); // Open a connection to POP3 server System.out.println("Opening Socket"); socket = new Socket(this.hostname, this.port); br = new BufferedReader(new InputStreamReader(socket.getInputStream())); pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); // If response from server is not okay if(! responseIsOk()) { socket.close(); throw new Exception("Invalid POP3 Server"); } // Login by sending USER and PASS commands System.out.println("Sending username"); writeMsg("USER "+this.username); if(!responseIsOk()) { sendQuit(); throw new Exception("Invalid username"); } System.out.println("Sending password"); writeMsg("PASS "+this.password); if(!responseIsOk()) { sendQuit(); throw new Exception("Invalid password"); } // Get mail count from server .... System.out.println("Checking mail"); writeMsg("STAT"); // ... and parse for number of messages String line = readLine(true); StringTokenizer tokens = new StringTokenizer(line," "); // +OK tokens.nextToken(); // number of messages int messages = Integer.parseInt(tokens.nextToken()); // size of all messages int maxsize = Integer.parseInt(tokens.nextToken()); if (messages == 0) { System.out.println ("There are no messages."); sendQuit(); return; } System.out.println ("There are " + messages + " messages."); System.out.println("Press enter to continue."); userinput.readLine(); for(int i = 1; i <= messages ; i++) { System.out.println("Retrieving message number "+i); writeMsg("RETR "+i); System.out.println("--------------------"); line = readLine(false); while(line != null && !line.equals(".")) { line = readLine(false); } System.out.println("--------------------"); System.out.println("Press enter to continue. To stop, " + "type Q then enter"); String response = userinput.readLine(); if (response.toUpperCase().startsWith("Q")) break; } sendQuit(); } public static void main(String[] args) throws Exception { Pop3ClientDemo client = new Pop3ClientDemo(); } // Read user input protected void getInput() throws Exception { String data=null; BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Please enter POP3 server hostname:"); data = br.readLine(); if(data == null || data.equals("")) hostname="localhost"; else hostname=data; System.out.print("Please enter mailbox username:"); data = br.readLine(); if(!(data == null || data.equals(""))) username=data; System.out.print("Please enter mailbox password:"); data = br.readLine(); if(!(data == null || data.equals(""))) password=data; } }
D:\Test\Java\ch8>java Pop3ClientDemo Please enter POP3 server hostname:mail.e88.com.tw Please enter mailbox username:***** Please enter mailbox password:***** Displaying mailbox with protocol commands and responses below -------------------------------------------------------------- Opening Socket < +OK POP3 mail.e88.com.tw v2001.78rh server ready Sending username > USER ***** < +OK User name accepted, password please Sending password > PASS ***** < +OK Mailbox open, 1 messages Checking mail > STAT < +OK 1 1080 There are 1 messages. Press enter to continue. Retrieving message number 1 > RETR 1 -------------------- +OK 1080 octets Return-Path:
Received: (from root@localhost) by mail.e88.com.tw (8.11.6/8.11.6) id iB896Qg19645 for ejlu2003@mail.e88.com.tw; Wed, 8 Dec 2004 17:06:26 +0800 Received: from penguin.im.cyut.edu.tw (penguin.im.cyut.edu.tw [163.17.9.2]) by mail.e88.com.tw (8.11.6/8.11.6) with ESMTP id iB896DR19528 for ; Wed, 8 Dec 2004 17:06:14 +0800 From: jlu@penguin.im.cyut.edu.tw Received: by penguin.im.cyut.edu.tw (Postfix, from userid 514) id 3B1BE190208; Wed, 8 Dec 2004 17:06:28 +0800 (CST) Date: Wed, 8 Dec 2004 17:06:28 +0800 To: ejlu2003@mail.e88.com.tw Subject: Test Message-ID: <20041208090628 data-blogger-escaped-.ga30803=".ga30803" data-blogger-escaped-penguin.im.cyut.edu.tw="penguin.im.cyut.edu.tw"> Mime-Version: 1.0 Content-Type: text/plain; charset=big5 Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.4.1i X-Spam-Checker-Version: SpamAssassin 2.63 (2004-01-11) on mail.e88.com.tw X-Spam-Status: No, hits=1.4 required=7.0 tests=NO_REAL_NAME,RCVD_IN_DSBL autolearn=no version=2.63 X-Spam-Level: * Status: this is a test 訊息 . -------------------- Press enter to continue. To stop, type Q then enter Sending QUIT > QUIT < +OK Sayonara Closing Connection - HTTP/1.0 Server
The HyperText Transfer Protocol originated as a means of sharing documents across the Internet. The first of HTTP is known as HTTP/1.0 (RFC 1945). The most recent version is HTTP/1.1 (RFC 2616). The following example is a simple web server which supplies text files and directories.
import java.io.*; import java.net.*; import java.util.*; public class WebServerDemo { // Directory of HTML pages and other files private String docroot; // Port number of web server private int port; // Socket for the web server private ServerSocket ss; // Handler for a HTTP request // You do not have to make Handler as an inner class. class Handler extends Thread { private Socket socket; private PrintWriter pw; private BufferedOutputStream bos; private BufferedReader br; private File docroot; public Handler(Socket _socket, String _docroot) throws Exception { socket=_socket; // Get the absolute directory of the filepath docroot=new File(_docroot).getCanonicalFile(); } public void run() { try { // Prepare our readers and writers br = new BufferedReader(new InputStreamReader(socket.getInputStream())); bos = new BufferedOutputStream(socket.getOutputStream()); pw = new PrintWriter(new OutputStreamWriter(bos)); // Read HTTP request from user (hopefully GET /file...... ) String line = br.readLine(); // Places the input stream for this socket at "end of stream". Any // data sent to the input stream side of the socket is acknowledged // and then silently discarded. If you read from a socket input stream // after invoking shutdownInput() on the socket, the stream will // return EOF. socket.shutdownInput(); if(line == null) { socket.close(); return; } // let's take a look at what the server received System.out.println(line); if(line.toUpperCase().startsWith("GET")) { // Eliminate any trailing ? data, such as for a CGI GET request StringTokenizer tokens = new StringTokenizer(line," ?"); tokens.nextToken(); String req = tokens.nextToken(); // If a path character / or \ is not present, add it to the // document root // and then add the file request, to form a full filename String name; if(req.startsWith("/") || req.startsWith("\\")) name = docroot + req; else name = docroot + File.separator + req; // Get absolute file path File file = new File(name).getCanonicalFile(); // Check to see if request doesn't start with our document root .... if(!file.getAbsolutePath().startsWith(docroot.getAbsolutePath())) { pw.println("HTTP/1.0 403 Forbidden"); pw.println(); } // ... if it's missing ..... else if(!file.exists()) { pw.println("HTTP/1.0 404 File Not Found"); pw.println(); } // ... if it can't be read for security reasons .... else if(!file.canRead()) { pw.println("HTTP/1.0 403 Forbidden"); pw.println(); } // ... if its actually a directory, and not a file .... else if(file.isDirectory()) { sendDir(bos,pw,file,req); } // ... or if it's really a file else { sendFile(bos, pw, file.getAbsolutePath()); } } // If not a GET request, the server will not support it else { pw.println("HTTP/1.0 501 Not Implemented"); pw.println(); } pw.flush(); bos.flush(); } catch(Exception e) { e.printStackTrace(); } try { socket.close(); } catch(Exception e) { e.printStackTrace(); } } protected void sendFile(BufferedOutputStream bos, PrintWriter pw, String filename) throws Exception { try { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename)); byte[] data = new byte[10*1024]; int read = bis.read(data); pw.println("HTTP/1.0 200 Okay"); pw.println(); pw.flush(); bos.flush(); while(read != -1) { bos.write(data,0,read); read = bis.read(data); } bos.flush(); } catch(Exception e) { pw.flush(); bos.flush(); } } protected void sendDir(BufferedOutputStream bos, PrintWriter pw, File dir, String req) throws Exception { try { pw.println("HTTP/1.0 200 Okay"); pw.println(); pw.flush(); pw.print("<html><head><title>Directory of "); pw.print(req); pw.print("</title></head><body><h1>Directory of "); pw.print(req); pw.println("</h1><table border=\"0\">"); File[] contents=dir.listFiles(); for(int i=0;i<contents.length;i++) { pw.print("<tr>"); pw.print("<td><a href=\""); pw.print(req); pw.print(contents[i].getName()); if(contents[i].isDirectory()) pw.print("/"); pw.print("\">"); if(contents[i].isDirectory()) pw.print("Dir -> "); pw.print(contents[i].getName()); pw.print("</a></td>"); pw.println("</tr>"); } pw.println("</table></body></html>"); pw.flush(); } catch(Exception e) { pw.flush(); bos.flush(); } } } // Check that a filepath has been specified and a port number protected void parseParams(String[] args) throws Exception { switch(args.length) { case 1: case 0: System.err.println ("Syntax: <jvm> "+this.getClass().getName()+ " docroot port"); System.exit(0); default: this.docroot = args[0]; this.port = Integer.parseInt(args[1]); break; } } public WebServerDemo(String[] args) throws Exception { System.out.println ("Checking for paramters"); // Check for command line parameters parseParams(args); System.out.print ("Starting web server...... "); // Create a new server socket ss = new ServerSocket(port); System.out.println ("OK"); for (;;) { // Accept a new socket connection from our server socket Socket accept = ss.accept(); // Start a new handler instance to process the request new Handler(accept, docroot).start(); } } // Start an instance of the web server running public static void main(String[] args) throws Exception { WebServerDemo webServerDemo = new WebServerDemo(args); } }
- Simple HTTP Client
- Parsing with the URL class
import java.net.*; // Chapter 9, Listing 1 public class URLParser { public static void main(String args[]) { int argc = args.length; // Check for valid number of parameters if (argc != 1) { System.out.println ("Syntax :"); System.out.println ("java URLParser url"); return; } // Catch any thrown exceptions try { // Create an instance of java.net.URL java.net.URL myURL = new URL ( args[0] ); System.out.println ("Protocol : " + myURL.getProtocol() ); System.out.println ("Hostname : " + myURL.getHost() ); System.out.println ("Port : " + myURL.getPort() ); System.out.println ("Filename : " + myURL.getFile() ); System.out.println ("Reference: " + myURL.getRef() ); } // MalformedURLException indicates parsing error catch (MalformedURLException mue) { System.err.println ("Unable to parse URL!"); return; } } }
- Retrieving a Resource with the URL class
import java.net.*; import java.io.*; // Chapter 9, Listing 2 public class FetchURL { public static void main(String args[]) throws Exception { int argc = args.length; // Check for valid number of parameters if (argc != 1) { System.out.println ("Syntax :"); System.out.println ("java FetchURL url"); return; } // Catch any thrown exceptions try { // Create an instance of java.net.URL java.net.URL myURL = new URL ( args[0] ); // Fetch the content, and read from an InputStream InputStream in = myURL.openStream(); // Buffer the stream, for better performance BufferedInputStream bufIn = new BufferedInputStream(in); // Repeat until end of file for (;;) { int data = bufIn.read(); // Check for EOF if (data == -1) break; else System.out.print ( (char) data); } // Pause for user System.out.println (); System.out.println ("Hit enter to continue"); System.in.read(); } // MalformedURLException indicates parsing error catch (MalformedURLException mue) { System.err.println ("Unable to parse URL!"); return; } // IOException indicates network or I/O error catch (IOException ioe) { System.err.println ("I/O Error : " + ioe); return; } } }
- Retrieving a Resource with the URLConnection class: The URLConnection class allows a program to connect a resource, set request header fields, read response header fields, and read the contents of the resource.
import java.net.*; import java.io.*; import java.util.*; // Chapter 9, Listing 3 public class FetchURLConnection { public static void main(String args[]) throws Exception { int argc = args.length; // Check for valid number of parameters if (argc != 1) { System.out.println ("Syntax :"); System.out.println ("java FetchURLConnection url"); return; } // Catch any thrown exceptions try { // Create an instance of java.net.URL java.net.URL myURL = new URL ( args[0] ); // Create a URLConnection object, for this URL // NOTE : no connection has yet been established URLConnection connection = myURL.openConnection(); // Now open a connection connection.connect(); // Display the MIME content-type of the resource (e.g. text/html) String MIME = connection.getContentType(); System.out.println ("Content-type: " + MIME); // Display, if available, the content length int contentLength = connection.getContentLength(); if (contentLength != -1) { System.out.println ("Content-length: " + contentLength); } // Display the "Date" field: web server's date info long date = connection.getDate(); if (date != 0) System.out.println("Date: " + new Date(date).toString()); long modified = connection.getLastModified(); if (modified != 0) System.out.println("Last Modified: " + new Date(modified)); // Pause for user System.out.println ("Hit enter to continue"); System.in.read(); // Read the contents of the resource from the connection InputStream in = connection.getInputStream(); // Buffer the stream, for better performance BufferedInputStream bufIn = new BufferedInputStream(in); // Repeat until end of file for (;;) { int data = bufIn.read(); // Check for EOF if (data == -1) break; else System.out.print ( (char) data); } } // MalformedURLException indicates parsing error catch (MalformedURLException mue) { System.err.println ("Unable to parse URL!"); return; } // IOException indicates network or I/O error catch (IOException ioe) { System.err.println ("I/O Error : " + ioe); return; } } }
- Modifying and Examining Header Fields with URLConnection:如果配合修改之前的 web server,就可以非常清楚的看出 HTTP Protocol 的 request/reply 的一些訊息。
import java.net.*; import java.io.*; // Chapter 9, Listing 4 public class HTTPHeaders { public static void main(String args[]) throws Exception { int argc = args.length; // Check for valid number of parameters if (argc != 1) { System.out.println ("Syntax :"); System.out.println ("java HTTPHeaders url"); return; } // Catch any thrown exceptions try { // Create an instance of java.net.URL java.net.URL myURL = new URL ( args[0] ); // Create a URLConnection object, for this URL // NOTE : no connection has yet been established URLConnection connection = myURL.openConnection(); // Set some basic request fields // Set user agent, to identify the application as Netscape compatible connection.setRequestProperty ("User-Agent", "Mozilla/4.0 (compatible; JavaApp)"); // Set our referer field - set to any URL you'd like connection.setRequestProperty ("Referer", "http://www.davidreilly.com/"); // Set use-caches field, to prevent caching connection.setUseCaches(false); // Now open a connection connection.connect(); // Examine request properties, to verify their settings System.out.println ("Request properties...."); System.out.println(); System.out.println ("User-Agent: " + connection.getRequestProperty("User-Agent")); System.out.println ("Referer: " + connection.getRequestProperty("Referer")); System.out.println (); System.out.println (); // Examine response properties, to see their settings System.out.println ("Response properties...."); System.out.println(); // Search through each header field, until no more exist int i = 1; while ( connection.getHeaderField ( i ) != null ) { // Get the name of this header field String headerName = connection.getHeaderFieldKey(i); // Get the name of this header field String headerValue = connection.getHeaderField(i); // Output header field key, and header field value System.out.println ( headerName + ": " + headerValue); // Goto the next element in the set of header fields i++; } // Pause for user System.out.println ("Hit enter to continue"); System.in.read(); } // MalformedURLException indicates parsing error catch (MalformedURLException mue) { System.err.println ("Unable to parse URL!"); return; } // IOException indicates network or I/O error catch (IOException ioe) { System.err.println ("I/O Error : " + ioe); return; } } }
- Parsing with the URL class
Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu
沒有留言:
張貼留言