• No results found

Socket-based Network Communication in J2SE and J2ME

N/A
N/A
Protected

Academic year: 2021

Share "Socket-based Network Communication in J2SE and J2ME"

Copied!
36
0
0

Loading.... (view fulltext now)

Full text

(1)

Department of Computer Science VŠB-Technical University of Ostrava

1

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Socket-based Network

Communication in

J2SE and J2ME

(2)

Department of Computer Science VŠB-Technical University of Ostrava

2

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

C/C++ BSD Sockets in POSIX

POSIX functions allow to access network connection

in the same way as regular files:

There are special functions for opening the connections,

the connection is known in POSIX as socket and may be

used for different types of communication – inter-process

communication on the same machine, different network

protocols, etc.

Socket- and protocol-specific parameters are set and

retrieved by calling special functions

Data transfer is done by specific functions or in regular way

(read, write)

J2SE copies this approach in Object-oriented way to a

degree (methods have similar/same names as POSIX

functions).

(3)

Department of Computer Science VŠB-Technical University of Ostrava

3

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Stream Communication (TCP)

socket

bind

connect listen

accept

close

DATA send/recv

client server

(4)

Department of Computer Science VŠB-Technical University of Ostrava

4

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Datagram Communication (UDP)

socket

bind connect

close

(b) sendto/recvfrom

(a) (b)

send/recv

(a)

read/write DATA

(5)

J2SE TCP/IP Communication (1)

Network communication classes in J2SE can be found

in java.net namespace. However, many related classes

do not have a common parent other then Object:

java.net.Socket

– basic client socket for TCP connection. Used to access remote services; we usually supply destination address and port in constructor:

new Socket(host, port);

java.net.DatagramSocket

– socket for sending and receiving UDP datagrams, we supply local port in constructor when necessary:

new DatagramSocket(host, port);

java.net.MulticastSocket

DatagramSocket

used for sending multicasts (traffic to a group of computers).

java.net.DatagramPacket

– block of data to

send/receive

with

DatagramSocket.

We wrap it around a buffer in constructor and if necessary specify an

InetAddress

and port of destination

computer:

new DatagramPacket(buffer, length, [address, [port]]);

(6)

Department of Computer Science VŠB-Technical University of Ostrava

6

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

J2SE TCP/IP Communication (2)

java.net.InetAddress

– representation of IP address. Instance can be created by static methods

getByName(hostname),

getByAddress(byte[4] addr)

. Text representation of IP address can be retrieved back by

getHostAddress()

and

getHostName()

.

java.net.ServerSocket

– basic server socket for TCP connection.

We need to specify at least the local port the server will be listening at and number of queued requests:

new ServerSocket(port [, backlog]);

When we want to retrieve a queued connection, we call the

listen()

method on server socket.

java.net.URL

– class representing the URL, usually "http://...".

java.net.URLConnection

– basic abstract class for URL-based connections. Corresponding sub-class is opened using call to

new URL(url).openConnection();

(7)

Department of Computer Science VŠB-Technical University of Ostrava

7

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

J2SE Sockets – Remarks

The socket operations are blocking, i.e. the thread

execution will stop until the socket operation is finished.

Since non-blocking sockets do not exist in Java, we can

use a workaround by calling setSoTimeout(ms). In case

the timeout is reached, java.net.SocketTimeoutException

is thrown and can be caught.

Several connection/socket parameters can be

set/retrieved by calling various set*/get* methods.

Both connect and bind methods can be called, if we do

not specify the needed parameters in constructor, but

we need to specify an InetAddress + port or SocketAddress

(8)

J2SE TCP Socket Connection

try {

s=new Socket(host,port);

BufferedReader sis = new BufferedReader(new InputStreamReader(System.in));

BufferedWriter os = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

BufferedReader is = new BufferedReader(new InputStreamReader(s.getInputStream()));

String l;

do {

System.out.println("Type a line to send to server.");

l=sis.readLine();

os.write(l);

os.newLine();

os.flush();

System.out.println("Server: " + is.readLine());

} while (!l.equals("exit") && !l.equals("down"));

s.close();

} catch (IOException e) { System.out.println(e); }

The Socket allows us to connect to given port on a given host.

(9)

J2SE TCP Server

try {

ServerSocket s=new ServerSocket(port); Socket cs;

do {

cs=s.accept();

BufferedReader is = new BufferedReader

(new InputStreamReader(cs.getInputStream()));

BufferedWriter os = new BufferedWriter

(new OutputStreamWriter(cs.getOutputStream()));

do {

msg=is.readLine();

os.write(String.valueOf(msg.length()));

os.newLine(); os.flush();

} while (!msg.equals("exit") && !msg.equals("down"));

cs.close();

} while (!msg.equals("down"));

s.close();

} catch (IOException e) { System.out.println(e); }

The ServerSocket listens to traffic on given port on localhost. The accept() method returns a socket representing client side.

(10)

J2SE TCP Server – MultiThreading

public class MyApplication implements Runnable { protected Socket cs; static ServerSocket s;

static int port=8000;

public static void main(String[] args) { Socket cs;

try {

s=new ServerSocket(port);

do {cs=s.accept(); new Thread(MyApplication(cs)).start();

} while (true);

} catch (IOException e) {if(!e instanceof SocketException){System.out.println(e);}}

}

public MyApplication(Socket cs) {this.cs=cs;}

public void run() {

/* Violet bold text from previous slide */

if (msg.equals("down")) s.close(); //Closes main socket to terminate the application }

}

Since all requests in previous example must wait until the server calls accept again, the processing is delayed. The solution is to use Threads:

(11)

J2SE UDP Client

String data; //Will be set later, eg. by reading from System.in int port=8000;

String server="www.cs.vsb.cz";

try {

DatagramSocket s=new DatagramSocket();

DatagramPacket p = new DatagramPacket(data.getBytes(), data.length(),

InetAddress.getByName(server), port);

s.send(p);

s.receive(p);

reply=new String(p.getData(),0,p.getLength());

System.out.println("Reply arrived from "+ p.getAddress() +" : "+ p.getPort()+" > " + reply);

s.close();

} catch (IOException e) { System.out.println(e); }

The following example shows how we use

DatagramSocket

to send data to given server's port. Each datagram is independent and may not be delivered

(12)

J2SE UDP Server

try {

DatagramSocket s=new DatagramSocket(port);

DatagramPacket p;

String msg;

do {

p=new DatagramPacket(new byte[512], 512); // new instance each time due to buffer length s.receive(p);

msg = new String(p.getData(),0,p.getLength());

System.out.println("Datagram from " + p.getAddress() + " : " + p.getPort() + " > " + msg);

p.setData(msg.toUpperCase().getBytes());

p.setLength(msg.length());

s.send(p);

} while (!msg.equals("down"));

s.close();

} catch (IOException e) { System.out.println(e); }

We do not have a specific class for datagram servers, since it is not needed.

The following example shows how we use

DatagramSocket

on server's port.

(13)

Department of Computer Science VŠB-Technical University of Ostrava

13

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

J2ME TCP Socket Connection

String uri = "socket://" + name + ":" + port;

StreamConnection connection = (StreamConnection)

Connector.open(uri, Connector.READ_WRITE);

InputStream input = connection.openInputStream();

OutputStream output = connection.openOutputStream();

// Send a message.

String outgoing = ...

output.write(outgoing.getBytes());

// Receive a response.

byte buffer[] = new byte[SIZE];

int read = input.read(buffer);

Establish a socket connection using Connector and read/write data using associated input/output streams.

(14)

Department of Computer Science VŠB-Technical University of Ostrava

14

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

J2ME TCP Server

MIDP 1.0 – the socket is reused for incomming connection

StreamConnectionNotifier serverSocket =

(StreamConnectionNotifier) Connector.open("serversocket://:12345");

StreamConnection conn = serverSocket.acceptAndOpen();

MIDP 2.0 – a new socket is created.

ServerSocketConnection scn =

(ServerSocketConnection) Connector.open("socket://:12345");

SocketConnection sc = (SocketConnection) scn.acceptAndOpen();

Both the device and the service operator must support servers on

mobile devices to make it work (e.g. no private IP addresses!)

The Server Socket listens to traffic on given port on localhost. The MIDP implementations differ in handling of the server sockets.

(15)

Department of Computer Science VŠB-Technical University of Ostrava

15

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

J2ME Server's Request Handler

public class EchoRequestHandler extends Thread {

public void run() {

try {

InputStream input = serverSocket.getInputStream();

OutputStream output = serverSocket.getOutputStream();

int read;

byte data[] = new byte[BUFFER_SIZE];

while ((read = input.read(data)) != -1) {

output.write(data, 0, read);

output.flush();

}

}

...

In order to ensure handling of multiple clients, the request handler is executed by an independent thread of execution.

(16)

J2ME UDP Client

String data; //Will be set later, eg. by reading from System.in int port=8000; String server="www.cs.vsb.cz";

try {

DatagramConnection dc = (DatagramConnection)

Connector.open("datagram://" + server + ":" + port);

Datagram dg = dc.newDatagram(100);

byte[] bytes = message.getBytes();

dc.send(dc.newDatagram(bytes, bytes.length));

dc.receive(dg);

if (dg.getLength() > 0) {

System.err.println("Message received - " + new String(dg.getData(), 0, dg.getLength()));

}

} catch (ConnectionNotFoundException cnfe) {

//Connection not successful – server is possibly not running, do something about it } catch (IOException e) { e.printStackTrace(); }

The following example shows how we use

DatagramConnection

to send data to given server's port.

(17)

J2ME UDP Server

int port=8000;

try {

DatagramConnection dc = (DatagramConnection)Connector.open("datagram://:" + port);

while (true) {

Datagram dg = dc.newDatagram(100);

dc.receive(dg);

address = dg.getAddress();

if (dg.getLength() > 0) {

String message = new String(dg.getData(), 0, dg.getLength()).toUpperCase();

System.err.println("Message received: " + message);

byte[] bytes = message.getBytes();

dc.send(dc.newDatagram(bytes, bytes.length));

} }

} catch (IOException e) {

//Binding not successful – another server is possibly running on the same port e.printStackTrace();

}

The following example shows how we use

DatagramConnection

to to listen on given port. The server changes messages to uppercase.

(18)

J2ME Servers – Closing Remarks

When running servers on mobile devices with J2ME

we have to keep in mind following issues:

Local socket-based connections between applications may

not pose a problem, but the device must be able to run

more than one J2ME application/MIDlet at a time (we do

not have to use sockets to communicate between threads).

Remote applications must know the IP address of the

device acting as server, which may pose a problem

(in MIDP 2.0 we can call getLocalAddress() on an opened

server socket ).

To be accessible from Internet, the device must have a

public IP address (the addresses containing 10.*.*.*,

172.16.*.* – 172.31.*.*, 192.168.*.* and 169.254.*.* are

not accessible from Internet, since they are private)

(19)

Department of Computer Science VŠB-Technical University of Ostrava

19

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Multi Threading

MULTI

THREADING

(20)

Department of Computer Science VŠB-Technical University of Ostrava

20

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Threads

There is often need to turn a program into separate, independently running subtasks. Each of these independent subtasks is called a thread, and is programmed as if each thread runs by itself and has the CPU to itself. The thread model is a programming convenience to simplify juggling several operations at the same time within a single program. There is several reasons why to do this.

There can be one thread controlling and responding to a GUI, while another thread carries out the tasks or computations requested, while a third thread does file I/O, all for the same program.

Some programs are easier to write if they are split into threads. The classic example is the server part of a client/server. When a request comes in from a client, it is very convenient if the server can spawn a new thread to process that one request.

(21)

Department of Computer Science VŠB-Technical University of Ostrava

21

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Class Thread

public class CountDownThread extends Thread { private static int threads = 0;

private int thread = threads++;

public void run() {

for (int i = MAX_COUNT; i > 0; i--) System.out.println("thread #" + thread + ": " + i);

}}

Thread thread = new CountDownThread();

thread.start();

The simplest way to create a thread is to inherit from class java.lang.Thread. The most important method for Thread is run(), which is the code that will be executed simultaneously with the other threads in a program.

(22)

Department of Computer Science VŠB-Technical University of Ostrava

22

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Interface Runnable

public class CountDownThread implements Runnable { private static int threads = 0;

private int thread = threads++;

public void run() {

for (int i = MAX_COUNT; i > 0; i--) System.out.println("thread #" + thread + ": " + i);

}}

Thread thread = new Thread(new CountDownThread());

thread.start();

Sometimes it is impossible or inconvenient to inherit from Thread class.

The java.lang.Runnable interface, declaring the run() method, can be implemented in these cases.

(23)

Department of Computer Science VŠB-Technical University of Ostrava

23

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

The Life Cycle of a Thread

A thread goes through several states during its life cycle:

Creating

When a thread is created, it is merely an empty object. No system resources are allocated. The thread in this can be only started.

Starting

The start() method creates the system resources necessary to run the thread, schedules the thread to run, and calls the thread's run() method.

Making a Thread Not Runnable

A thread becomes Not Runnable when one of these events occurs: its sleep() or wait() method is invoked.

Stopping

A program does not stop a thread directly. Rather, a thread arranges for its own death by leaving its run() method.

(24)

Department of Computer Science VŠB-Technical University of Ostrava

24

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Synchronization

public class Game {

private Player black, white, previous;

public synchronized void turn(Player player) { if (player == previous)

throw new IllegalPlayerException(...);

...

There are many interesting situations where separate, concurrently running threads do share data and must consider the state and activities of other threads. Java provides a synchronization mechanism based on monitors. Each object in Java has a lock and a monitor to manage the lock. A block marked as synchronized forces any thread wishing to enter the block to acquire corresponding lock first. If another thread already holds the lock, the acquiring thread will block until the lock will be released. The lock is released when the thread leaves the block.

(25)

Department of Computer Science VŠB-Technical University of Ostrava

25

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Producer-Consumer Problem

public interface SharedData { public int getSize();

public void put(int[] data);

public int[] get();

}

The producer-consumer problem is a classic synchronization problem.

The producer and consumer processes share a common data. The producer executes a loop in which it puts new items into the data and the consumer executes a loop in which it removes items from the data.

Consumer Producer

SharedData

(26)

Department of Computer Science VŠB-Technical University of Ostrava

26

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Producer

public class Producer extends Thread { private SharedData data;

public void run() {

for (int i = 0; i < 10; i++) {

int[] array = new int[data.getSize()];

System.out.print("put");

for (int j = 0; j < array.length; j++) { array[j] = i;

System.out.print(" " + array[j]);

}

System.out.println();

data.put(array);

} } ...

The producer executes a loop in which it puts new items into the data store.

(27)

Department of Computer Science VŠB-Technical University of Ostrava

27

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Consumer

public class Consumer extends Thread { private SharedData data;

public void run() {

for (int i = 0; i < 10; i++) { int[] array = data.get();

System.out.print("got");

for (int j = 0; j < array.length; j++) System.out.print(" " + array[j]);

System.out.println();

} } ...

The consumer executes a loop in which it removes items from the data store.

(28)

Department of Computer Science VŠB-Technical University of Ostrava

28

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Naïve Shared Data

public class NaiveSharedData implements SharedData { private int[] data;

public void put(int[] data) {

for (int i = 0; i < data.length; i++) this.data[i] = data[i];

}

public int[] get() {

int[] data = new int[this.data.length];

for (int i = 0; i < data.length; i++) data[i] = this.data[i];

return data;

} ...

Traditional implementation of the SharedData interface seems to be all right, but ...

(29)

Department of Computer Science VŠB-Technical University of Ostrava

29

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Putting It All Together

SharedData data = new NaiveSharedData(3);

Producer producer = new Producer(data);

Consumer consumer = new Consumer(data);

producer.start();

consumer.start();

Output produced by the program is incorrect, because it contains inconsisten sequence 0 0 1.

The producer-consumer problem can be assembled by a few lines of code.

...put 1 1 1 got 0 0 1 got 1 1 1 put 2 2 2 ...

(30)

Department of Computer Science VŠB-Technical University of Ostrava

30

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Acquiring a Lock

public class BetterSharedData extends NaiveSharedData { public synchronized void put(int[] data) {

super.put(data);

}

public synchronized int[] get() { return super.get();

}

The code segments within a program that access the same object from separate, concurrent threads are called critical sections. A critical is identified with the synchronized keyword. A lock is associated with every object that has synchronized code.

...put 2 2 2 got 2 2 2 got 2 2 2

(31)

Department of Computer Science VŠB-Technical University of Ostrava

31

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Releasing a Lock (1)

public class PerfectSharedData extends BetterSharedData { private boolean read = true;

public synchronized void put(int[] data) { try {

while (!read) wait();

super.put(data);

read = false;

notifyAll();

}

catch (InterruptedException e) { ...

A thread releases an object's lock when it enters into wait() method of the object. The wait() method causes the thread to wait until another thread invokes the notify() or the notifyAll() method for the object.

(32)

Department of Computer Science VŠB-Technical University of Ostrava

32

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Releasing a Lock (2)

public synchronized int[] get() { int data[] = null;

try {

while (read) wait();

data = super.get();

read = true;

notifyAll();

} catch (InterruptedException e) { e.printStackTrace();

}

return data;

}

The InterruptedException is thrown by the wait() method if another thread interrupts the current thread.

(33)

Department of Computer Science VŠB-Technical University of Ostrava

33

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Scheduling Tasks

There are two classes, Timer and TimerTask, to facilitate running of tasks in a background thread.

Scheduling one-time tasks

Executes a task after specified delay.

Scheduling repeating tasks

Executes a task at regular intervals. There are two variations for scheduling repeating tasks.

Fixed-delay

Each execution of a task is based solely on how long it was since the previous task finished.

Fixed-rate

Each execution of a task is based on when the first task started and the requested delay between tasks.

(34)

Department of Computer Science VŠB-Technical University of Ostrava

34

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Timer Task

public class DrawerTask extends TimerTask { private AnimationCanvas canvas;

public DrawerTask(Canvas canvas) { this.canvas = canvas;

}

public void run() {

canvas.drawNextFrame();

} }

A subclass of TimerTask defines what is to be done. It declares abstract method run() which has be implemented by the subclass.

(35)

Department of Computer Science VŠB-Technical University of Ostrava

35

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Animation Canvas

public class AnimationCanvas extends Canvas { private Image[] frames = new Image[FRAMES];

int currentFrame = 0;

public AnimationCanvas() throws IOException { for (int i = 0; i < frames.length; i++) {

frames[i] = Image.createImage("/frame" + (i+1) + ".png");

} }

public void drawNextFrame() {

currentFrame = (currentFrame+1)%frames.length;

repaint();

} ...

The drawNextFrame() is invoked repeatedly by a DrawerTask.

(36)

Department of Computer Science VŠB-Technical University of Ostrava

36

J2ME TAMZ

by Roman Szturc 2006 & Pavel Moravec 2008

Timer

AnimationCanvas canvas = new AnimationCanvas();

TimerTask task = new DrawerTask(canvas);

Timer timer = new Timer();

// Repeat the task each 1 second.

timer.schedule(task, 0, 1000);

The timer executes its task reapeatedly, which in turn affects the animation canvas, forcing it to repaint.

References

Related documents

An application in terms of Section 11 of the Mineral and Petroleum Resources Development Act for ministerial consent to transfer the right to mine iron ore, vanadium and

This paper, in view of such a lapse, proposes a technology development framework as a Model for manufacturing and supplying technologies to local industry in Ghana with the potential

The aim of the present study was therefore to docu- ment indications for admission, complications and hospital outcomes of patients with DM admitted to the largest referral

The surface chlorophyll- a concentration maps will be used as a help to localize the density fronts since Chl- a fronts are very often related with the vertical velocities

Dim-to-Warm LED module provides a continuously adjustable range of color temperature control from 3000K dimming down to 1800K or 4000K dimming down to 2700K.. CRI ≥ 90 for entire

Weinzweig also joined the leadership academy students on Friday morning for another workshop that helped fellow candidates develop their lead panelists to discuss foreign

At the 2016 Food Tank Summit in Washington, D.C., a panel was dedicated to the issue, called “Beyond Calories: The Need for Nutrient Dense Diets.” The panel brought together leaders

Let us present our approach for one entity: a dataset corresponding to one of the 27 EU Member States (or the EU), one chapter of the nomenclature (or all 99 chapters), and one type