java networking - ut · link internet network layers transport application this is as low as java...

Post on 27-Apr-2020

25 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

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 jf@zeroturnaround.com

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/

top related