tanszek:oktatas:iss_t:java_example_for_blocking_and_non-blocking_socket
Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| tanszek:oktatas:iss_t:java_example_for_blocking_and_non-blocking_socket [2023/03/05 16:35] – létrehozva knehez | tanszek:oktatas:iss_t:java_example_for_blocking_and_non-blocking_socket [2024/03/04 08:00] (current) – [Blocking UDP sockets in Java] knehez | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ==== Blocking TCP based sockets in Java ==== | + | ==== Blocking TCP sockets in Java ==== |
| - | === Socket server source code === | + | === Blocking |
| - | <code java> | + | <sxh java> |
| + | package org.ait; | ||
| import java.io.IOException; | import java.io.IOException; | ||
| import java.io.ObjectInputStream; | import java.io.ObjectInputStream; | ||
| Line 22: | Line 23: | ||
| try { | try { | ||
| // 1. create a socket server listening to port 8080 | // 1. create a socket server listening to port 8080 | ||
| - | providerSocket = new ServerSocket(8080, 10); | + | providerSocket = new ServerSocket(8080); |
| // 2. waiting for the connection (here we are waiting until next connection) | // 2. waiting for the connection (here we are waiting until next connection) | ||
| connection = providerSocket.accept(); | connection = providerSocket.accept(); | ||
| Line 71: | Line 72: | ||
| } | } | ||
| } | } | ||
| - | </code> | + | </sxh> |
| - | === Socket client source === | + | === Blocking |
| - | <code java> | + | <sxh java> |
| + | package org.ait; | ||
| import java.io.IOException; | import java.io.IOException; | ||
| import java.io.ObjectInputStream; | import java.io.ObjectInputStream; | ||
| Line 137: | Line 139: | ||
| } | } | ||
| } | } | ||
| - | </code> | + | </sxh> |
| - | ==== Non-blocking TCP based sockets in Java ==== | + | ==== Blocking UDP sockets in Java ==== |
| The following Agent sends a message and waits for a response on port 8080, also with UDP. Older versions of the Eclipse IDE, the text you type on the console can be sent by pressing ctrl+z | The following Agent sends a message and waits for a response on port 8080, also with UDP. Older versions of the Eclipse IDE, the text you type on the console can be sent by pressing ctrl+z | ||
| - | <code java> | + | <sxh java> |
| - | package org.ait; | + | package org.ait; |
| + | |||
| + | import java.io.BufferedReader; | ||
| + | import java.io.InputStreamReader; | ||
| + | import java.net.DatagramPacket; | ||
| + | import java.net.DatagramSocket; | ||
| + | import java.net.InetAddress; | ||
| + | |||
| + | public class UDPClient { | ||
| + | public static void main(String args[]) throws Exception { | ||
| + | BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); | ||
| + | DatagramSocket clientSocket = new DatagramSocket(); | ||
| + | InetAddress IPAddress = InetAddress.getByName(" | ||
| + | |||
| + | byte[] sendData = new byte[1024]; | ||
| + | byte[] receiveData = new byte[1024]; | ||
| + | |||
| + | String sentence = inFromUser.readLine(); | ||
| + | sendData = sentence.getBytes(); | ||
| + | |||
| + | DatagramPacket sendPacket = new DatagramPacket(sendData, | ||
| + | clientSocket.send(sendPacket); | ||
| + | |||
| + | DatagramPacket receivePacket = new DatagramPacket(receiveData, | ||
| + | clientSocket.receive(receivePacket); | ||
| + | String modifiedSentence = new String(receivePacket.getData()); | ||
| + | |||
| + | System.out.println(" | ||
| + | clientSocket.close(); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | The UDP server waits for the agents messages on port 8080 and converts them to uppercase letters and sends them back to the client UDP socket. | ||
| + | |||
| + | <sxh java> | ||
| + | package org.ait; | ||
| + | |||
| + | import java.net.DatagramPacket; | ||
| + | import java.net.DatagramSocket; | ||
| + | import java.net.InetAddress; | ||
| + | |||
| + | public class UDPServer { | ||
| + | public static void main(String args[]) throws Exception { | ||
| + | |||
| + | DatagramSocket serverSocket = new DatagramSocket(8080); | ||
| + | |||
| + | byte[] bytesReceived = new byte[1024]; | ||
| + | byte[] bytesSent = new byte[1024]; | ||
| + | |||
| + | DatagramPacket receivePacket = new DatagramPacket(bytesReceived, | ||
| + | // here we are waiting for the packets | ||
| + | serverSocket.receive(receivePacket); | ||
| + | |||
| + | String textMessage = new String(receivePacket.getData()); | ||
| + | |||
| + | System.out.println(" | ||
| + | |||
| + | InetAddress IPAddress = receivePacket.getAddress(); | ||
| + | int port = receivePacket.getPort(); | ||
| + | |||
| + | String upperCaseText = textMessage.toUpperCase(); | ||
| + | bytesSent = upperCaseText.getBytes(); | ||
| + | |||
| + | // send back | ||
| + | DatagramPacket sendPacket = new DatagramPacket(bytesSent, | ||
| + | serverSocket.send(sendPacket); | ||
| + | serverSocket.close(); | ||
| + | |||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== Non-blocking TCP sockets in Java ==== | ||
| + | {{: | ||
| + | |||
| + | Reading: | ||
| + | |||
| + | * http:// | ||
| + | * http:// | ||
| + | |||
| + | |||
| + | {{tanszek: | ||
| + | |||
| + | |||
| + | ===== Non-blocking loop ===== | ||
| + | <sxh java> | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | SocketChannel socketChannel = serverSocketChannel.accept(); | ||
| + | |||
| + | if(socketChannel != null){ | ||
| + | // the connection is accepted | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== Non-blocking Java client example ===== | ||
| + | |||
| + | <sxh java> | ||
| + | import java.io.IOException; | ||
| + | import java.io.InputStream; | ||
| + | import java.io.OutputStream; | ||
| + | import java.net.Socket; | ||
| + | import java.util.Random; | ||
| | | ||
| - | | + | |
| - | import java.io.InputStreamReader; | + | private String host; |
| - | import java.net.DatagramPacket; | + | private int port; |
| - | | + | |
| - | | + | |
| | | ||
| - | public class UDPClient { | + | // Bounds on how much we write per cycle |
| - | public | + | private |
| - | BufferedReader inFromUser | + | private static final int maxWriteSize = 65536; |
| - | DatagramSocket clientSocket | + | |
| - | InetAddress IPAddress = InetAddress.getByName(" | + | // Bounds on how long we wait between cycles |
| - | + | private static final int minPause | |
| - | byte[] sendData = new byte[1024]; | + | private static final int maxPause |
| - | byte[] receiveData | + | |
| - | + | // Random number generator | |
| - | String sentence = inFromUser.readLine(); | + | Random rand = new Random(); |
| - | sendData = sentence.getBytes(); | + | |
| - | + | public Client(String host, int port, int numThreads) { | |
| - | DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 8080); | + | this.host = host; |
| - | clientSocket.send(sendPacket); | + | this.port |
| - | + | | |
| - | DatagramPacket receivePacket | + | for (int i = 0; i < numThreads; ++i) { |
| - | clientSocket.receive(receivePacket); | + | new Thread(this).start(); |
| - | String modifiedSentence = new String(receivePacket.getData()); | + | } |
| - | + | ||
| - | System.out.println(" | + | |
| - | clientSocket.close(); | + | |
| } | } | ||
| + | | ||
| + | public void run() { | ||
| + | byte buffer[] = new byte[maxWriteSize]; | ||
| + | try { | ||
| + | Socket s = new Socket(host, | ||
| + | InputStream in = s.getInputStream(); | ||
| + | OutputStream out = s.getOutputStream(); | ||
| + | | ||
| + | while (true) { | ||
| + | int numToWrite = minWriteSize | ||
| + | + (int) (rand.nextDouble() * (maxWriteSize - minWriteSize)); | ||
| + | for (int i = 0; i < numToWrite; ++i) { | ||
| + | buffer[i] = (byte) rand.nextInt(256); | ||
| + | } | ||
| + | out.write(buffer, | ||
| + | int sofar = 0; | ||
| + | while (sofar < numToWrite) { | ||
| + | sofar += in.read(buffer, | ||
| + | } | ||
| + | System.out.println(Thread.currentThread() + " wrote " + numToWrite); | ||
| + | | ||
| + | int pause = minPause + (int) (rand.nextDouble() * (maxPause - minPause)); | ||
| + | try { | ||
| + | Thread.sleep(pause); | ||
| + | } catch (InterruptedException ie) { | ||
| + | } | ||
| + | } | ||
| + | } catch (IOException ie) { | ||
| + | ie.printStackTrace(); | ||
| + | } | ||
| } | } | ||
| - | </ | + | |
| + | static public void main(String args[]) throws Exception { | ||
| + | new Client(" | ||
| + | } | ||
| + | } | ||
| - | The UDP server waits for the agents messages on port 8080 and converts them to uppercase letters and sends them back to the client UDP socket. | + | </ |
| - | <code java> | + | |
| - | | + | ===== Non-blocking Java server example ===== |
| - | + | <sxh java> | |
| - | | + | |
| - | | + | // The port we will listen on |
| - | | + | private int port; |
| - | + | // A pre-allocated buffer for encrypting data | |
| - | | + | private final ByteBuffer buffer = ByteBuffer.allocate(16384); |
| - | public static void main(String args[]) throws Exception | + | public Server(int port) { |
| - | + | this.port = port; | |
| - | DatagramSocket serverSocket | + | new Thread(this).start(); |
| - | + | } | |
| - | byte[] bytesReceived | + | public void run() { |
| - | byte[] bytesSent | + | try { |
| - | + | // Instead of creating a ServerSocket, | |
| - | + | // create a ServerSocketChannel | |
| - | DatagramPacket receivePacket | + | ServerSocketChannel ssc = ServerSocketChannel.open(); |
| - | // here we are waiting | + | // Set it to non-blocking, |
| - | serverSocket.receive(receivePacket); | + | ssc.configureBlocking(false); |
| - | + | // Get the Socket connected to this channel, and bind it | |
| - | String textMessage | + | // to the listening port |
| - | + | ServerSocket ss = ssc.socket(); | |
| - | System.out.println(" | + | InetSocketAddress isa = new InetSocketAddress(port); |
| - | + | ss.bind(isa); | |
| - | InetAddress IPAddress = receivePacket.getAddress(); | + | // Create a new Selector for selecting |
| - | int port = receivePacket.getPort(); | + | Selector selector = Selector.open(); |
| - | + | // Register the ServerSocketChannel, | |
| - | String upperCaseText = textMessage.toUpperCase(); | + | // listen for incoming connections |
| - | bytesSent = upperCaseText.getBytes(); | + | ssc.register(selector, |
| - | + | System.out.println(" | |
| - | // send back | + | while (true) |
| - | DatagramPacket sendPacket | + | // See if we've had any activity -- either |
| - | serverSocket.send(sendPacket); | + | // an incoming connection, or incoming data on an |
| - | serverSocket.close(); | + | // existing connection |
| - | + | int num = selector.select(); | |
| + | // If we don't have any activity, loop around and wait | ||
| + | // again | ||
| + | if (num == 0) { | ||
| + | continue; | ||
| + | } | ||
| + | // Get the keys corresponding to the activity | ||
| + | // that has been detected, and process them | ||
| + | // one by one | ||
| + | Set keys = selector.selectedKeys(); | ||
| + | Iterator it = keys.iterator(); | ||
| + | while (it.hasNext()) { | ||
| + | // Get a key representing one of bits of I/O | ||
| + | // activity | ||
| + | SelectionKey key = (SelectionKey) it.next(); | ||
| + | // What kind of activity is it? | ||
| + | if ((key.readyOps() & SelectionKey.OP_ACCEPT) | ||
| + | System.out.println(" | ||
| + | // It's an incoming connection. | ||
| + | // Register this socket with the Selector | ||
| + | // so we can listen for input on it | ||
| + | Socket s = ss.accept(); | ||
| + | System.out.println(" | ||
| + | // Make sure to make it non-blocking, | ||
| + | // use a selector on it. | ||
| + | SocketChannel sc = s.getChannel(); | ||
| + | sc.configureBlocking(false); | ||
| + | // Register it with the selector, | ||
| + | sc.register(selector, | ||
| + | } else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) { | ||
| + | SocketChannel sc = null; | ||
| + | try { | ||
| + | // It's incoming data on a connection, so | ||
| + | // process it | ||
| + | sc = (SocketChannel) key.channel(); | ||
| + | boolean ok = processInput(sc); | ||
| + | // If the connection is dead, then remove it | ||
| + | // from the selector and close it | ||
| + | if (!ok) { | ||
| + | key.cancel(); | ||
| + | Socket s = null; | ||
| + | try { | ||
| + | s | ||
| + | s.close(); | ||
| + | } catch (IOException ie) { | ||
| + | System.err.println(" | ||
| + | + s + ": " + ie); | ||
| + | } | ||
| + | } | ||
| + | } catch (IOException ie) { | ||
| + | // On exception, remove this channel from the | ||
| + | // selector | ||
| + | key.cancel(); | ||
| + | try { | ||
| + | sc.close(); | ||
| + | } catch (IOException ie2) { | ||
| + | System.out.println(ie2); | ||
| + | } | ||
| + | System.out.println(" | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | // We remove the selected keys, because we've dealt | ||
| + | // with them. | ||
| + | keys.clear(); | ||
| + | } | ||
| + | } catch (IOException ie) { | ||
| + | System.err.println(ie); | ||
| + | } | ||
| + | } | ||
| + | // Do some cheesy encryption on the incoming data, | ||
| + | // and send it back out | ||
| + | private boolean processInput(SocketChannel sc) throws IOException { | ||
| + | buffer.clear(); | ||
| + | sc.read(buffer); | ||
| + | buffer.flip(); | ||
| + | // If no data, close the connection | ||
| + | if (buffer.limit() == 0) { | ||
| + | return false; | ||
| + | } | ||
| + | // Simple rot-13 encryption | ||
| + | for (int i = 0; i < buffer.limit(); ++i) { | ||
| + | byte b = buffer.get(i); | ||
| + | if ((b >= ' | ||
| + | b += 13; | ||
| + | } else if ((b >= ' | ||
| + | b -= 13; | ||
| + | } | ||
| + | buffer.put(i, b); | ||
| + | } | ||
| + | sc.write(buffer); | ||
| + | System.out.println(" | ||
| + | return true; | ||
| + | } | ||
| + | static public void main(String args[]) throws Exception { | ||
| + | new Server(4444); | ||
| } | } | ||
| } | } | ||
| - | </code> | + | </sxh> |
tanszek/oktatas/iss_t/java_example_for_blocking_and_non-blocking_socket.1678034158.txt.gz · Last modified: 2023/03/05 16:35 by knehez
