690 likes | 713 Views
Intro to Java C/S. TCP/IP Sockets in Java Practical guide for programmers Kenneth and Michael. outline. 1. Basic Java operation 2. Java Socket Introduction. JAVA Implementation. Java program. Java program. Java program. Java program. Java Cmds. Java Cmds. Java Cmds. VM. VM. VM.
E N D
Intro to Java C/S TCP/IP Sockets in Java Practical guide for programmers Kenneth and Michael
outline • 1. Basic Java operation • 2. Java Socket Introduction
JAVA Implementation Java program Java program Java program Java program Java Cmds Java Cmds Java Cmds VM VM VM SPARC PowerPC Intel
Operations Environments • Applications program (~DOS window) • supports file access • Applet (browser) – no longer generally supported • supports Internet linkages.
Building Java Applications Using Java Development Kit • Get a copy of the JDK (www.oracle.com, etc.) • Install the development kit (tools and classes) • Create MyApp.java source file • text editor (notepad, etc.) • winedit, Café, etc. • Compile .java file to create .class file • javac MyApp.java • Run application (.class file) through java VM • java MyApp
Building Java Applications Using Java IDEs • NetBeans • Available from netbeans.org • Eclipse • Available from www.eclipse.org • jCreator le • available from jcreator.com • jcreator pro – academic license $35 • jDeveloper • available from www.oracle.com/technetwork/developer-tools/jdev • many others
Sample Java App G:\Data\Java\MyHelloApp>type MyHelloApp.java class MyHelloApp { public static void main (String argv[]) { String message[] = new String[2]; message[0] = "Welcome to CS423"; message[1] = "The subject is JAVA!"; System.out.println (message[0]); System.out.println (message[1]); } }
MyHelloApp Implementation MyHelloApp.java Java compiler MyHelloApp.class MyHelloApp.class Java byte code VM machine code
Sample Java App G:\Data\Java\MyHelloApp>javac MyHelloApp.java G:\Data\Java\MyHelloApp>java MyHelloApp Welcome to CS423 The subject is JAVA! G:\Data\Java\MyHelloApp>
Get Input from User import java.io.*; class InputApp { InputApp () { DataInputStream dis = new DataInputStream (System.in); String sIn = " "; String sOut = " "; File fIn; File fOut; FileInputStream fis; FileOutputStream fos; int iNumBytesRead; byte[] ab;
Get Input from User System.out.println ("*-------------------------------------------*"); System.out.print ("Enter Source File Name Here: "); System.out.flush (); try {sIn = dis.readLine ();} catch (Exception e) {System.out.println ("Exception on input file name" + e);} System.out.print("Enter Destination File Name Here: "); System.out.flush (); try {sOut = dis.readLine ();} catch (Exception e) {System.out.println ("Exception on output file name" + e);}
Get Input from User try { fIn = new File (sIn); fis = new FileInputStream (fIn); fOut = new File (sOut); fos = new FileOutputStream (fOut); ab = new byte[2048]; while ((iNumBytesRead = fis.read (ab)) != -1) { fos.write (ab, 0, iNumBytesRead); } fis.close (); fos.close (); } catch (Exception e) {System.out.println ("Exception during copy: " + e); }
Get Input from User System.out.println ("Data copied from " + sIn + " to " + sOut); System.out.println ("*-------------------------------------------*"); } public static void main (String args[]) { new InputApp (); } }
Get Input from User G:\Data\Java\InputApp>java InputApp *-------------------------------------------* Enter Source File Name Here: books_db.txt Enter Destination File Name Here: My_list.txt Data copied from books_db.txt to My_list.txt *-------------------------------------------* G:\Data\Java\InputApp>
Passing Data to Programs publicclassParmApplication { publicstaticvoid main(String argv[]){ for (inti=0; i < argv.length; i++){ System.out.println(i + ": " + argv[i]); } } } $ javac ParmApplication.java $ java ParmApplication 1 2 3 0: 1 1: 2 2: 3
Client / Server in Java • Primary communications is through sockets. • (Web type access also available through URL class) • Browser security limits the access that a program can have when run as an applet. Lots of security problems.. So.. applets are no longer supported in HTML5. • Graphical applications supported with new methods and IDEs. • “Default” socket is stream (TCP). • Socket classes implemented in java.net package
Basic Sockets Classes • Socket • ServerSocket • SocketAddress • InetAddress • Datagram Socket • Datagram Packet • Multicast Socket • URL
Socket Client/Server in Java • Typically client used to be applet, but can be graphical application or command line • Server is written as java application or even in some other language (c, c++, etc.). • Where client access is through the Web , the server must be running on the web server machine.
Find your IP address • InetAddress abstraction represents a network destination, including domain names and numerical address info. • Inet4Address • Inet6Address
InetAddressExample import java.util.Enumeration; import java.net.*; public class InetAddressExample { public static void main(String[] args) { Enumeration<NetworkInterface> interfaceList = NetworkInterface.getNetworkInterfaces(); while (interfaceList.hasMoreElements()) { NetworkInterface iface = interfaceList.nextElement(); System.out.println("Interface " + iface.getName() + ":"); Enumeration<InetAddress> addrList = iface.getInetAddresses(); if (!addrList.hasMoreElements()) { System.out.println("\t(No addresses for this interface)"); } while (addrList.hasMoreElements()) { InetAddress address = addrList.nextElement(); System.out.print("\tAddress " + ((address instanceof Inet4Address ? "(v4)" : (address instanceof Inet6Address ? "(v6)" : "(?)")))); System.out.println(": " + address.getHostAddress()); } }
InetAddressExample // Get name(s)/address(es) of hosts given on command line for (String host : args) { try { System.out.println(host + ":"); InetAddress[] addressList = InetAddress.getAllByName(host); for (InetAddress address : addressList) { System.out.println("\t" + address.getHostName() + "/" + address.getHostAddress()); } } catch (UnknownHostException e) { System.out.println("\tUnable to find address for " + host); } } } }
InetAddressExample Interface awdl0: Address (v6): fe80:0:0:0:10b0:4dff:fef0:85d0%8 Interface vboxnet0: Address (v4): 192.168.56.1 Interface en0: Address (v6): 2605:6000:3814:8000:7d14:414:7e03:49a8 Address (v6): 2605:6000:3814:8000:62f8:1dff:feab:9414 Address (v6): fe80:0:0:0:62f8:1dff:feab:9414%4 Address (v4): 10.0.1.23 Interface lo0: Address (v6): fe80:0:0:0:0:0:0:1%1 Address (v6): 0:0:0:0:0:0:0:1 Address (v4): 127.0.0.1 www.umkc.edu: www.umkc.edu/134.193.116.82 www.umkc.edu/2610:e0:a040:64a2:0:0:0:52
More about InetAddress • Static InetAddress[] getAllbyName(String host) • Static InetAddressgetByName(String host) • Static InetAddressgetLocalHost()
TCP Socket • Java provides two classes for TCP • Socket for client • ServerSocket for server • //headers import java.net.Socket; import java.net.SocketException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;
TCP Client • Construct a Socket • A connected Socket contains an InputStream and OutputStream that can be just for data input and output • Close()
A TCPEchoClient Example public class TCPEchoClient { 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>]"); String server = args[0]; // Server name or IP address // Convert argument String to bytes using the default character encoding byte[] data = args[1].getBytes(); int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7; // Create socket that is connected to server on specified port Socket socket = new Socket(server, servPort); System.out.println("Connected to server...sending echo string"); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); out.write(data); // Send the encoded string to the server // Receive the same string back from the server int totalBytesRcvd = 0; // Total bytes received so far int bytesRcvd; // Bytes received in last read while (totalBytesRcvd < data.length) { if ((bytesRcvd = in.read(data, totalBytesRcvd, data.length - totalBytesRcvd)) == -1) throw new SocketException("Connection closed prematurely"); totalBytesRcvd += bytesRcvd; } // data array is full System.out.println("Received: " + new String(data)); socket.close(); // Close the socket and its streams } }
Socket() constructors • Socket(InetAddress remoteAddr, int remotePort) • Socket(String remoteHost, int RemotePort) • Socket(InetAddress remoteAddr, int remotePort, InetAddress LocalAddress, int Localport) • Socket(String remoteHost, int remotePort, InetAddress localAddress, int localport) • Socket() • Then you can to call connect()
TCP Server • ServerSocket() • accpet() • A connected Socket contains an InputStream and OutputStream that can be just for data input and output • Close()
A TCPEchoServer Example import java.net.*; // for Socket, ServerSocket, and InetAddress import java.io.*; // for IOException and Input/OutputStream public class TCPEchoServer { private static final int BUFSIZE = 32; // Size of receive buffer public static void main(String[] args) throws IOException { if (args.length != 1) // Test for correct # of args throw new IllegalArgumentException("Parameter(s): <Port>"); int servPort = Integer.parseInt(args[0]); // Create a server socket to accept client connection requests ServerSocket servSock = new ServerSocket(servPort); int recvMsgSize; // Size of received message byte[] receiveBuf = new byte[BUFSIZE]; // Receive buffer while (true) { // Run forever, accepting and servicing connections Socket clntSock = servSock.accept(); // Get client connection SocketAddress clientAddress = clntSock.getRemoteSocketAddress(); System.out.println("Handling client at " + clientAddress); //ip and port number InputStream in = clntSock.getInputStream(); OutputStream out = clntSock.getOutputStream(); // Receive until client closes connection, indicated by -1 return while ((recvMsgSize = in.read(receiveBuf)) != -1) { out.write(receiveBuf, 0, recvMsgSize); } clntSock.close(); // Close the socket. We are done with this client! } /* NOT REACHED */ } }
TCP ServerSocket() constructor • ServerSocket(Int localPort) • ServerSocket(int localport, int queueLimit) • ServerSocket(int localPort, int queueLimit, InetAddress LocalAddress) • ServerSocket() • Then you have to call bind() • void bind(int port)
Java TCP Socket Input and output Stream • OutputStream/Send void write(int data) void write(byte[] data) void write(byte[] data, int offset, int length) void flush() void close() • InputStream/recv int read(byte[] data) int read(byte[] data, int offset, int length)
UDP DatagramPacketUDP data send/recv • DatagramPacket(byte[] buf, int length) • DatagramPacket(byte[] buf, int length, InetAddress address, int port) • DatagramPacket(byte[] buf, int offset, int length) • DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) • DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) • DatagramPacket(byte[] buf, int length, SocketAddress address)
UDP Socket • DatagramSocket • send/receive • close
A UDP Client import java.net.DatagramSocket; import java.net.DatagramPacket; import java.net.InetAddress; import java.io.IOException; import java.io.InterruptedIOException; public class UDPEchoClientTimeout { private static final int TIMEOUT = 3000; // Resend timeout (milliseconds) private static final int MAXTRIES = 5; // Maximum retransmissions 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 the argument String to bytes using the default 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); int tries = 0; // Packets may be lost, so we have to keep trying boolean receivedResponse = false;
A UDP Client 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(); } }
UDP DatagramSocket() constructor • DatagramSocket() • DatagramSocket(int localport) • DatagramSocket(int localport, InetAddress localaddress) • Connect() • void connect(InetAddress remoteAddr, int remotePort)
A UDP Server import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class UDPEchoServer { private static final int ECHOMAX = 255; // Maximum size of echo datagram 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); while (true) { // 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 */ } }
Java multitasking • Iterative server • concurrent server • thread per client
Java Threads import java.util.concurrent.TimeUnit; public class ThreadExample implements Runnable { private String greeting; // Message to print to console public ThreadExample(String greeting) { this.greeting = greeting; } public void run() { while (true) { System.out.println(Thread.currentThread().getName() + ": " + greeting); try { // Sleep 0 to 100 milliseconds TimeUnit.MILLISECONDS.sleep(((long) Math.random() * 100)); } catch (InterruptedException e) { } // Should not happen } } public static void main(String[] args) { new Thread(new ThreadExample("Hello")).start(); new Thread(new ThreadExample("Aloha")).start(); new Thread(new ThreadExample("Ciao")).start(); } }
A Concurrent TCP Server import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.logging.Logger; public class TCPEchoServerThread { public static void main(String[] args) throws IOException { if (args.length != 1) { // Test for correct # of args throw new IllegalArgumentException("Parameter(s): <Port>"); } int echoServPort = Integer.parseInt(args[0]); // Server port // Create a server socket to accept client connection requests ServerSocket servSock = new ServerSocket(echoServPort); // Run forever, accepting and spawning a thread for each connection while (true) { Socket clntSock = servSock.accept(); // Block waiting for connection // Spawn thread to handle new connection Thread thread = new Thread(new ThreadExample(clntSock); thread.start(); } /* NOT REACHED */ } }
NIO – Advanced Java socket programming • New I/O packages • java.nio.channels • Selector • Channel • java.nio • The single-thread approach • Channels: a socket file descriptor, a file or a device • Select():allows you to check “who” is ready to be served • Buffers are another feature of NIO that allows you to access the underlying data from reads and writes to avoid the overhead of copying data into new arrays.
Why NIO? • Make Socket functions Non-blocking • A regular Socket • is a blocking input/output device • A SocketChannel • is a non-blocking way to read from sockets, • use select() method
A TCP Non-blocking Client import java.net.InetSocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; public class TCPEchoClientNonblocking { public static void main(String args[]) throws Exception { if ((args.length < 2) || (args.length > 3)) // Test for correct # of args throw new IllegalArgumentException("Parameter(s): <Server> <Word> [<Port>]"); String server = args[0]; // Server name or IP address // Convert input String to bytes using the default charset byte[] argument = args[1].getBytes(); int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7; // Create channel and set to nonblocking SocketChannel clntChan = SocketChannel.open(); clntChan.configureBlocking(false);
A TCP Non-blocking Client // Initiate connection to server and repeatedly poll until complete if (!clntChan.connect(new InetSocketAddress(server, servPort))) { while (!clntChan.finishConnect()) { System.out.print("."); // Do something else } } ByteBuffer writeBuf = ByteBuffer.wrap(argument); ByteBuffer readBuf = ByteBuffer.allocate(argument.length); int totalBytesRcvd = 0; // Total bytes received so far int bytesRcvd; // Bytes received in last read while (totalBytesRcvd < argument.length) { if (writeBuf.hasRemaining()) { clntChan.write(writeBuf); } if ((bytesRcvd = clntChan.read(readBuf)) == -1) { throw new SocketException("Connection closed prematurely"); } totalBytesRcvd += bytesRcvd; System.out.print("."); // Do something else } System.out.println("Received: " + // convert to String per default charset new String(readBuf.array(), 0, totalBytesRcvd)); clntChan.close(); } }
A TCP Server using Select() import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.util.Iterator; public class TCPServerSelector { private static final int BUFSIZE = 256; // Buffer size (bytes) private static final int TIMEOUT = 3000; // Wait timeout (milliseconds) public static void main(String[] args) throws IOException { if (args.length < 1) { // Test for correct # of args throw new IllegalArgumentException("Parameter(s): <Port> ..."); } // Create a selector to multiplex listening sockets and connections Selector selector = Selector.open(); // Create listening socket channel for each port and register selector for (String arg : args) { ServerSocketChannel listnChannel = ServerSocketChannel.open(); listnChannel.socket().bind(new InetSocketAddress(Integer.parseInt(arg))); listnChannel.configureBlocking(false); // must be nonblocking to register // Register selector with channel. The returned key is ignored listnChannel.register(selector, SelectionKey.OP_ACCEPT); }
A TCP Server using Select() while (true) { // Run forever, processing available I/O operations // Wait for some channel to be ready (or timeout) if (selector.select(TIMEOUT) == 0) { // returns # of ready chans System.out.print("."); continue; } // Get iterator on set of keys with I/O to process Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator(); while (keyIter.hasNext()) { SelectionKey key = keyIter.next(); // Key is bit mask // Server socket channel has pending connection requests? if (key.isAcceptable()) { //accpet new connection; } // Client socket channel has pending data? if (key.isReadable()) { //ready to read; } // Client socket channel is available for writing and // key is valid (i.e., channel not closed)? if (key.isValid() && key.isWritable()) { //ready to write } keyIter.remove(); // remove from set of selected keys } } } }
TCP and Buffering • You should never assume any correspondence (return value) between write/send and read/receive • It depends on the buffer and the timing of the transfer of data over the network from sender side TCP implementation to the receiver side of implementation
Sender buffer byte[] buffer0 = new byte[1000]; byte[] buffer1 = new byte[2000]; byte[] buffer2 = new byte[5000]; Socket s = new Socket(destAddr, destPort); OutputStream out = s.getOutputStream(); ... out.write(buffer0); out.write(buffer1); out.write(buffer2);
receiver buffer byte[] buffer0 = new byte[1500]; byte[] buffer1 = new byte[2000]; byte[] buffer2 = new byte[4000]; byte[] buffer3 = new byte[500]; Socket s = new Socket(destAddr, destPort); InputStream in = s.getInputStream(); ... in.read(buffer0); in.read(buffer1); in.read(buffer2); in.read(buffer3);