CSCE 515: Computer Network Programming Chin-Tser Huang huangct@cse.sc.edu University of South Carolina More on Project 1 Both username and password are casesensitive Server sends acknowledgment to client no matter the received username is good or not Make your program compilable on Unix/Linux machines Multithreaded server will get one bonus point Plagiarism will not be tolerated! 1/27/2004 2 Something on Exam 1 To be held in class on March 4, 2004 (5:30pm-7pm) No excuse will be accepted If any substitute exam is really necessary, it will be MUCH HARDER than original exam 1/27/2004 3 UDP Sockets in Java Use class DatagramPacket and class DatagramSocket Both client and server use DatagramSocket to send and receive DatagramPacket 1/27/2004 4 Class DatagramPacket Constructors DatagramPacket(byte buffer[], int length) DatagramPacket(byte buffer[], int length, InetAddress address, int port) 1/27/2004 5 Class DatagramPacket Methods void setAddress(InetAddress address) InetAddress getAddress() void setPort(int port) int getPort() void setData(byte[] buffer) byte[] getData() void setLength(int length) int getLength() 1/27/2004 6 Class DatagramSocket Constructors DatagramSocket() throws SocketException DatagramSocket(int port) throws SocketException DatagramSocket(int port, InetAddress local) throws SocketException 1/27/2004 7 Class DatagramSocket Methods void close() throws IOException void connect(InetAddress address, int port) throws SocketException void disconnect() void send(DatagramPacket packet) throws IOException void receive(DatagramPacket packet) throws IOException 1/27/2004 8 Class DatagramSocket Methods InetAddress getInetAddress() int getPort() InetAddress getLocalAddress() int getLocalPort() void setSoTimeout(int timeout) throws SocketException int getSoTimeout() throws SocketException void setSendBufferSize(int size) throws SocketException int getSendBufferSize() throws SocketException void setReceiveBufferSize(int size) throws SocketException int getReceiveBufferSize() throws SocketException 1/27/2004 9 Class DatagramSocket Exceptions IOException SecurityException 1/27/2004 10 Receiving UDP Packets DatagramSocket socket = new DatagramSocket(port); byte buffer[] = new byte[65508]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); socket.receive(packet); InetAddress fromAddress = packet.getAddress(); int fromPort = packet.getPort(); int length = packet.getLength(); byte[] data = packet.getData(); // … socket.close(); 1/27/2004 11 Sending UDP Packets DatagramSocket socket = new DatagramSocket(); DatagramPacket packet = new DatagramPacket (data, data.length, InetAddress.getByName(“www.nsa.gov”), 1728); socket.send(packet); socket.close(); 1/27/2004 12 A UDP Echo Client Example Send echo string to server Block on receive() for up to 3 seconds Retry for up to 5 times if reply is not received before timeout Terminate the client 1/27/2004 13 UDPEchoClientTimeout.java /* * TCP/IP Sockets in Java * Kenneth Calvert, Michael Donahoo * Morgan Kaufmann Publishers; ISBN 1558606858 * * http://cs.ecs.baylor.edu/~donahoo/practical/JavaSockets/textco de.html* * Copyright (c) 2002 Kenneth Calvert, Michael Donahoo ; * all rights reserved; see license.txt for details. */ import java.net.*; import java.io.*; public class UDPEchoClientTimeout { private static final int TIMEOUT = 3000; // Resend timeout private static final int MAXTRIES = 5; // Maximum retransmissions // public static void main (String args[]) … } 1/27/2004 14 Method main public static void main(String[] args) throws IOException { if ((args.length < 2) || (args.length > 3)) // Test for correct # of args throw new IllegalArgumentException("Parameter(s): <Server> <Word> [<Port>]"); InetAddress serverAddress = InetAddress.getByName(args[0]); // Server address // Convert input String to bytes using the default character encoding byte[] bytesToSend = args[1].getBytes(); int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7; DatagramSocket socket = new DatagramSocket(); socket.setSoTimeout(TIMEOUT); // Maximum receive blocking time (milliseconds) DatagramPacket sendPacket = new DatagramPacket(bytesToSend, // Sending packet bytesToSend.length, serverAddress, servPort); DatagramPacket receivePacket = // Receiving packet new DatagramPacket(new byte[bytesToSend.length], bytesToSend.length); … 1/27/2004 15 Method main (cont’d) int tries = 0; // Packets may be lost, so we have to keep trying boolean receivedResponse = false; do { socket.send(sendPacket); // Send the echo string try { socket.receive(receivePacket); // Attempt echo reply reception if (!receivePacket.getAddress().equals(serverAddress)) // Check source throw new IOException("Received packet from an unknown source"); receivedResponse = true; } catch (InterruptedIOException e) { // We did not get anything tries += 1; System.out.println("Timed out, " + (MAXTRIES-tries) + " more tries..."); } } while ((!receivedResponse) && (tries < MAXTRIES)); if (receivedResponse) System.out.println("Received: " + new String(receivePacket.getData())); else System.out.println("No response -- giving up."); } socket.close(); 1/27/2004 16 A UDP Echo Server Example Construct a DatagramSocket specifying local port and (optionally) local address Communicate with client by receiving and sending DatagramPackets Terminate server when finished 1/27/2004 17 UDPEchoServer.java /* * TCP/IP Sockets in Java * Kenneth Calvert, Michael Donahoo * Morgan Kaufmann Publishers; ISBN 1558606858 * * http://cs.ecs.baylor.edu/~donahoo/practical/JavaSockets/textco de.html* * Copyright (c) 2002 Kenneth Calvert, Michael Donahoo ; * all rights reserved; see license.txt for details. */ import java.net.*; import java.io.*; public class UDPEchoServer { private static final int ECHOMAX = 255; // Maximum size of echo datagram // public static void main (String args[]) … } 1/27/2004 18 Method main public static void main(String[] args) throws IOException { if (args.length != 1) // Test for correct argument list throw new IllegalArgumentException("Parameter(s): <Port>"); int servPort = Integer.parseInt(args[0]); DatagramSocket socket = new DatagramSocket(servPort); DatagramPacket packet = new DatagramPacket(new byte[ECHOMAX], ECHOMAX); } for (;;) { // Run forever, receiving and echoing datagrams socket.receive(packet); // Receive packet from client System.out.println("Handling client at " + packet.getAddress().getHostAddress() + " on port " + packet.getPort()); socket.send(packet); // Send the same packet back to client packet.setLength(ECHOMAX); // Reset length to avoid shrinking buffer } /* NOT REACHED */ 1/27/2004 19 Blocking Program cannot move forward until request for data is satisfied Many calls may block accept() read(), receive() write() 1/27/2004 20 Dealing with Blocking Calls Write a non-blocking server Use available() Use setSoTimeout() Write a multithreaded server 1/27/2004 21 A Non-blocking Server Example Accept two client connections Loop to echo data between two clients Use available() to simulate non-blocking 1/27/2004 22 NBServer.java /* * Java Network Programming, Second Edition * Merlin Hughes, Michael Shoffner, Derek Hamner * Manning Publications Company; ISBN 188477749X * * http://nitric.com/jnp/ * * Copyright (c) 1997-1999 Merlin Hughes, Michael Shoffner, Derek Hamner; * all rights reserved; see license.txt for details. */ import java.net.*; import java.io.*; public class NBServer { static InputStream in0, in1; static OutputStream out0, out1; } // public static void main (String[] args) throws IOException … 1/27/2004 23 Method main public static void main (String[] args) throws IOException { if (args.length != 1) throw new IllegalArgumentException ("Syntax: NBServer <port>"); try { accept (Integer.parseInt (args[0])); int x0, x1; while (((x0 = readNB (in0)) != -1) && ((x1 = readNB (in1)) != -1)) { if (x0 >= 0) out1.write (x0); if (x1 >= 0) out0.write (x1); } } finally { System.out.println ("Closing"); close (out0); close (out1); } } 1/27/2004 24 Method close static void close (OutputStream out) { if (out != null) { try { out.close (); } catch (IOException ignored) { } } } // static void accept (int port) throws IOException … // static int readNB (InputStream in) … 1/27/2004 25 Method accept static void accept (int port) throws IOException { System.out.println ("Starting on port " + port); ServerSocket server = new ServerSocket (port); try { System.out.println ("Waiting.."); Socket client0 = server.accept (); System.out.println ("Accepted from " + client0.getInetAddress ()); in0 = client0.getInputStream (); out0 = client0.getOutputStream (); out0.write ("Welcome. Please wait.\r\n".getBytes ("latin1")); System.out.println ("Waiting.."); Socket client1 = server.accept (); System.out.println ("Accepted from " + client1.getInetAddress ()); in1 = client1.getInputStream (); out1 = client1.getOutputStream (); out1.write ("Welcome.\r\n".getBytes ("latin1")); out0.write ("Proceed.\r\n".getBytes ("latin1")); } finally { server.close (); } } 1/27/2004 26 Method readNB static int readNB (InputStream in) throws IOException { if (in.available () > 0) return in.read (); else return -2; } 1/27/2004 27 Use Socket Timeout client0.setsoTimeout (10); client1.setSoTimeout (10); static int readNB (InputStream in) throws IOException { try { return in.read (); } catch (InterruptedIOException ex) { return -2; } } 1/27/2004 28 Next Class Multithreading Link layer Read JNP Ch. 16, TI Ch. 2 1/27/2004 29