java networking - ut · link internet network layers transport application this is as low as java...
TRANSCRIPT
Java Networking Java Fundamentals
2014, Tartu
Neeme Praks @nemecec
Hello world! URL url = new URL("http://www.google.com"); try (InputStream in = url.openStream()) { //read stuff (check the last lecture)}
Agenda
• Transport layer – sockets (client and server) o TCP, UDP o Encryption o Blocking vs. non-blocking
• Application layer o Client
§ Built-in HTTP client § Custom protocol handlers
o Server § Embedding HTTP server § Custom servers
Link
Internet
Network layers
Transport
Application
This is as low as Java gets TCP UDP
IPv4 IPv6
HTTP FTP SMTP DNS SSH
10101101...
Transport layer
• Java supports only TCP and UDP
• SocketInputStream SocketOutputStream o reading and writing raw bytes
• Sockets o TCP sockets – class Socket
o UDP sockets – class DatagramSocket
Sockets
• Software abstractions to networking
• Data moves between local and remote sockets
• Identified by o Transport (TCP or UDP)
o port number (0-65535)
• Up to 65 535 sockets (per transport)
• TCP 53 and UDP 53 are different ports!
Port ranges
0-1023 Publicly well-known ports 1024 - 49151 Registered ports 49152-65535 Dynamic / private ports TCP 80 HTTP TCP 443 HTTPS TCP 53 DNS UDP 53 DNS UDP 666 Doom (multiplayer game) http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
TCP
• Connection oriented – class Socket
• Stream based – socket.get*Stream()
• Easy to use! • Maintains ordering
• Retransmits lost packets
• High(ish) overhead
TCP client try ( Socket s = new Socket("google.com", 80); InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream();) { readAndWriteStuff(in, out);}
TCP server try (ServerSocket srv = new ServerSocket(80)) { while (true) { Socket s = srv.accept(); //this will block readAndWriteStuff(s); }}
TCP server Exception in thread "main" java.net.BindException: Permission denied
at java.net.PlainSocketImpl.socketBind(Native Method)at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:382)at java.net.ServerSocket.bind(ServerSocket.java:375)at java.net.ServerSocket.<init>(ServerSocket.java:237)at java.net.ServerSocket.<init>(ServerSocket.java:128)at slides.ExamplesOnSlides.tcpServer(ExamplesOnSlides.java:37)at slides.ExamplesOnSlides.main(ExamplesOnSlides.java:12)
Naïve server public NaiveServer(int port) { try (ServerSocket srv = new ServerSocket(port)) { while (true) { Socket s = srv.accept(); readAndWriteStuffInSameThread(s); } }}
Naïve client public NaiveClient(String host, int port) { try ( Socket s = new Socket(host, port); InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); ) { readAndWriteStuffOnClientInSameThread(in, out); }}
Naïve “main” method public static void main(String[] args) { int port = 8099; new NaiveClientServerV2(port); new NaiveClient("localhost", port); System.out.println("Server started!");}
Naïve server demo https://github.com/zeroturnaround/java-fundamentals
Sub-project “net” Package “naiveserver”
Threads
while (true) Socket socket = srv.accept();
• Appropriate threading model needed o Everything in one thread
o Server in a separate thread
o Separate thread per connection
§ Thread pools
Thread pool int NR_THREADS = 50;ExecutorService pool = Executors.newFixedThreadPool(NR_THREADS);//...Runnable command = new ClientHandler(socket);pool.execute(command);//...pool.shutdown();for (;;) { pool.awaitTermination(1, TimeUnit.MINUTES); System.out.println("Still waiting"); }
UDP - User Datagram Protocol
• Packet oriented (no streams)
• Sends over some bytes
• No concept of connection
• "Fire and forget”
• Multi-cast capable
FAST!
No guarantee of delivery
Packets can be out of order
Sending a datagram byte[] buf = "hello".getBytes("UTF-8");try (DatagramSocket sock = new DatagramSocket()) { DatagramPacket message = new DatagramPacket( buf, buf.length, InetAddress.getByName("localhost"), 6666); sock.send(message);}
Reading a datagram try (DatagramSocket sock = new DatagramSocket(6666)) { byte[] buf = new byte[8]; DatagramPacket message = new DatagramPacket(buf, buf.length); sock.receive(message); System.out.println(Arrays.toString(buf)); //[104, 101, 108, 108, 111, 0, 0, 0]}
WTF?
Reading a datagram byte[] result = new byte[message.getLength()];System.arraycopy(buf,0,result,0,result.length);System.out.println(Arrays.toString(result));//[104, 101, 108, 108, 111]
Datagram demo https://github.com/zeroturnaround/java-fundamentals
Sub-project “net” Package “datagram”
UDP Applicability
• Performance critical systems
• Loss of a single packet = no big deal
• DNS
• Video streaming (multi-cast!)
• VoIP
• Some multiplayer games
Secure sockets
• TCP only • Works on top of regular sockets • Between transport and application layers • Only initial setup code changes
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();Socket sock = factory.createSocket("www.gmail.com", 443);readAndWriteStuff(sock);
Socket Channels (NIO)
• Buffer-oriented • blocking and non-blocking • can handle many sockets in one thread
• Scalability!
• closer to the OS. Better performance possible
Channel 1
Channel 2
Channel 1000
Selector handler
Socket Channel types
• FileChannel o Files, only blocking mode
• DatagramChannel o UDP networking
• SocketChannel o TCP networking
• ServerSocketChannel o Listen for TCP connections -> SocketChannel
Channel <--> Buffer RandomAccessFile file = new RandomAccessFile("example.txt", "rw");FileChannel inChannel = file.getChannel();ByteBuffer buf = ByteBuffer.allocate(48);int bytesRead = inChannel.read(buf);while (bytesRead != -1) { System.out.println("Read " + bytesRead); buf.flip(); while(buf.hasRemaining()){ System.out.print((char) buf.get()); } buf.clear(); bytesRead = inChannel.read(buf);}file.close();
Socket Channels – start listen try (ServerSocketChannel server = ServerSocketChannel.open()) { server.configureBlocking(false); server.socket().bind(new InetSocketAddress(8888)); Selector selector = Selector.open(); server.register(selector, SelectionKey.OP_ACCEPT); //OP_CONNECT //OP_READ //OP_WRITE}
Socket Channels - events while (true) { selector.select(); Set<SelectionKey> keys = selector.selectedKeys(); for (SelectionKey key : keys) { if (key.isAcceptable()) handleAccept(key); else if (key.isReadable()) handleRead(key); keys.remove(key); }}
handleAccept (SelectionKey key) ServerSocketChannel srv = (ServerSocketChannel) key.channel();SocketChannel client = srv.accept();client.configureBlocking(false);client.register( key.selector(), SelectionKey.OP_READ);
handleRead (SelectionKey key) SocketChannel client = (SocketChannel) key.channel();ByteBuffer buf = ByteBuffer.allocate(10);client.read(buf); buf.flip(); CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();String msg = decoder.decode(buf).toString();
Socket channels non-blocking demo
https://github.com/zeroturnaround/java-fundamentals Sub-project “net”
Package “nonblocking”
NIO vs IO: high-level
IO • Stream oriented • Blocking IO
NIO • Buffer oriented • Blocking IO • Non-blocking IO • Selectors • More flexible • More complex
NIO vs IO: IO API interaction
Source: http://tutorials.jenkov.com/java-nio/nio-vs-io.html
Reading data from a blocking stream.
NIO vs IO: NIO API interaction
Source: http://tutorials.jenkov.com/java-nio/nio-vs-io.html
Reading data from a channel until all needed data is in buffer.
NIO vs IO: IO threading model
Source: http://tutorials.jenkov.com/java-nio/nio-vs-io.html
A classic IO server design – one connection handled by one thread.
NIO vs IO: NIO threading model
Source: http://tutorials.jenkov.com/java-nio/nio-vs-io.html
A single thread managing multiple connections.
NIO vs IO: when to use which?
Hundreds of simultaneous connections
Thousands of simultaneous connections
Low bandwidth sockets
IO / NIO NIO
High bandwidth sockets
IO Depends
Transport Layer
• Too Low level
• Gets complicated very fast
• YOU NEED A PROTOCOL
• Use existing
or
• Develop your own
Application layer
Transport level - bare sockets
Application level - a protocol !
An application Layer Protocol
• Defines message rules and formats
• Solves complex communication issues
o authentication
o authorization
o metadata
o message boundaries
o message structure
Pre-made Protocols
HTTP Web pages. And more FTP File transfer SMTP Sending e-mail IMAP Reading e-mail POP Downloading e-mail XMPP Instant messaging RTSP Video Streaming
(YouTube!!) BitTorrent Amazon S3, Diablo 3 patches
HTTP
• Started out as HyperText Transfer Protocol
• Often used for exchanging messages
• Many solutions built on top of HTTP o SOAP (can also use e-mail )
o REST
o RSS
HTTP Request GET / HTTP/1.1\r\n Host: www.neti.ee\r\n Connection: keep-alive\r\n Accept-Encoding: gzip,deflate,sdch\r\n Accept-Language: en-US,en;q=0.8\r\n Accept-Charset: ISO-8859-1,utf-8;\r\n \r\n
HTTP Response HTTP/1.1 200 OK\r\n Date: Wed, 13 Feb 2013 21:17:13 GMT\r\nContent-Type: text/html\r\nContent-Length: 7909\r\nConnection: keep-alive\r\nContent-Encoding: gzip\r\nVary: Accept-Encoding\r\nETag: "1ee5-2b3ef24d"\r\nCache-Control: s-maxage=3600, max-age=57600\r\n\r\n <!DOCTYPE html PUBLIC...
java.net.URL
• Pointer to a resource (on the web)
URL url = new URL("http://www.google.com");URL relative = new URL(url, "page?q=asdf");URL pieces = new URL( "https", "google.com", 8443, "/page?q=asdf");URL file = new URL("file:/C:/Windows");URL custom = new URL("custom:/doStuff");
java.net.URLConnection
• communications link to destination • connection = url.openConnection();
• Can set headers o connection.setRequestProperty("key", "value");
• Can read response headers o connection.getHeaderField("name");
• Open streams for reading and writing o connection.get*Stream();
Sending stuff HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("POST");conn.setDoOutput(true);try ( OutputStreamWriter out = new OutputStreamWriter( conn.getOutputStream(), "UTF-8")) { out.write("Hello World!"); out.flush();}
URL and Custom Protocols URL url = new URL("custom:/doStuff");url.openStream();CustomUrlConnection conn = (CustomUrlConnection) url.openConnection();conn.petTheKitty(true);
stuff to implement / subclass
• URLStreamHandler o openConnection(URL url)
• URLConnection o connect()
o getInputStream()
o getOutputStream()
• URLStreamHandlerFactory o createURLStreamHandler(String protocol)
• URL.setURLStreamHandlerFactory(myFactory)
Embedding HTTP server
• Client side HTTP is easy
• No built in HTTP server
Solutions
• Deploy java app to server (java EE)
• Embed http server to application
• Use an HTTP library
Embedding Jetty final int PORT=8080;Server jettySrv = new Server(PORT);jettySrv.setHandler(new MyMessageHandler());jettySrv.start();jettySrv.join();
MyMessageHandler extends AbstractHandler
public void handle( String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); response.getWriter().println("Hello world"); response.setStatus(HttpServletResponse.SC_OK);}
jetty in pom.xml <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.2.2.v20140723</version></dependency><!-- optional --><dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>9.2.2.v20140723</version></dependency>
Apache HttpComponents
• Apache HttpComponents o great for implementing HTTP endpoints
o low level (compared to embedded servers)
o high performance, minimal memory footprint
• Apache HttpComponents Client o powerful HTTP client
o more options than URLConnection
HttpComponents Client CloseableHttpClient client = HttpClientBuilder.create().build();HttpPost request = new HttpPost("http://...");request.setHeader("key", "value");request.setEntity(new ByteArrayEntity(content));HttpResponse response = client.execute(request);EntityUtils.toByteArray(response.getEntity());Header[] headers = response.getHeaders("headerName");
JAX-RS (REST services)
• JAX-RS (java EE standard)
• automatic json & xml serialization
• Usually run in server o also work in embedded mode
o servers can be embedded
• Implementations: Resteasy, Jersey
JAX-RS sample @Path("greeting")public class GreetingService { @POST @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public ComplexGreeting invoke(Salute input) { return new ComplexGreeting(input); } }
HTTP has too high overhead?
Custom protocol - considerations
• Payload overhead / serialization format • Schema evolution • Platform interoperability • Ease of debugging • Unknown field handling • etc See also http://kentonv.github.io/capnproto/next/news/2014-06-17-capnproto-flatbuffers-sbe.html
Custom protocol – frameworks
• Cap’n Proto http://kentonv.github.io/capnproto/
• FlatBuffers http://google.github.io/flatbuffers/
• SBE https://github.com/real-logic/simple-binary-encoding
• Google protobuf https://developers.google.com/protocol-buffers/ • Thrift http://thrift.apache.org/ • Avro http://avro.apache.org/
• etc
Custom servers for those protocols
• Netty (http://netty.io/) • Grizzly (https://grizzly.java.net/) • MINA (https://mina.apache.org/) • Probably more
Homework
Chat Server!
• Chat client is provided (with source)
• Implement server side
• Must work with that client
https://github.com/zeroturnaround/jf-chatclient
Requirements
• TCP socket endpoint, listen on port 8888 o ChatClient connects and prints a name
o use socket to send chat messages to clients
• HTTP endpoint, listen on port 8080 o ChatClient makes HTTP POST request
§ author's name in header "author" § message in request body
o server handles request, sends received message to all participants
Requirements
• Response messages are constructed by
author + ": " + message
• reading raw HTTP is not allowed • Possible options
o Embedded Jetty server (http://wiki.eclipse.org/Jetty) o Embedded Tomcat server (http://tomcat.apache.org) o HTTPComponents (http://hc.apache.org/) o Netty (http://netty.io/) o Some other framework or library
Requirements
Use jf-skeleton in GitHub https://github.com/zeroturnaround/jf-skeleton/
Submit zipped source code via email to [email protected]
Deadline: next Monday, 29th of September 16:00
Describe in a few sentences which endpoint was trickier to implement and why.
Thank you
• Chat client for homework https://github.com/zeroturnaround/jf-chatclient
• Skeleton project for homework https://github.com/zeroturnaround/jf-skeleton/
• Very good tutorial about “Java networking” http://tutorials.jenkov.com/java-networking/