程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> 在J2ME中基於UDP協議編程

在J2ME中基於UDP協議編程

編輯:J2ME
在GCF中提供了DatagramConnection和Datagram兩個接口,借助他們我們可以在J2ME中基於UDP協議開發聯網應用程序,在MIDP2.0中,添加了UDPDatagramConnection這個接口。他擴展了DatagramConnection並添加了兩個方法getLocalAddress()和getLocalPort()。我們知道UDP服務是不可靠的,如果你希望開發更可靠的聯網應用的話可以采用SocketConnection,因為TCP服務是面向連接且可靠的。我們還必須清楚地一點是以上所說的各種連接方式都不是MIDP規范中規定必須實現的。因此在使用之前請參考特定設備的開發文檔。MIDP中只有Http連接是必須支持的。

    同樣,我們要獲得DatagramConnection的話,必須通過Connector的open方法,其中的URL應該滿足如下的形式。

  1. datagram://localhost:5555 這樣的話表示建立了一個客戶端模式的連接。在指定ip:localhost和指定端口:5555
  2. datagram://:5555  這樣建立的是一個服務器端模式的連接,在本地的5555端口。

建立連接後,我們可以通過DatagramConnection的newDatagram()方法構造一個Datagram,然後調用DatagramConnection的send()方法。這樣數據報將會發送到指定的接受方。例如你可以構建這個一個負責發送數據的Sender類。

package com.sIEmens.datagramtest;

import Javax.microedition.io.Datagram;
import Javax.microedition.io.DatagramConnection;

public class Sender extends Thread
{

    private DatagramConnection dc;

    private String address;

    private String message;

    public Sender(DatagramConnection dc)
    {
        this.dc = dc;
        start();
    }

    public synchronized void send(String addr, String msg)
    {
        address = addr;
        message = msg;
        notify();
    }

    public synchronized void run()
    {

        while (true)
        {

            // If no clIEnt to deal, wait until one connects
            if (message == null)
            {
                try
                {
                    wait();
                } catch (InterruptedException e)
                {
                }
            }

            try
            {
                byte[] bytes = message.getBytes();
                Datagram dg = null;
                // Are we a sender thread for the clIEnt ? If so then there's
                // no address parameter
                if (address == null)
                {
                    dg = dc.newDatagram(bytes, bytes.length);
                } else
                {
                    dg = dc.newDatagram(bytes, bytes.length, address);
                    System.out.println(address);
                }
                dc.send(dg);
            } catch (Exception ioe)
            {
                ioe.printStackTrace();
            }

            // Completed clIEnt handling, return handler to pool and
            // mark for wait
            message = null;
        }
    }

}
注意聯網的時候我們應該在另外一個線程中而不是在主線程中。

     服務器端的目的就是啟動後監聽指定的端口,當客戶端連接過來後接受數據並記錄下客戶端的地址,以便服務器端向客戶端發送數據。
package com.sIEmens.datagramtest;

import Java.io.IOException;

import Javax.microedition.io.Connector;
import Javax.microedition.io.Datagram;
import Javax.microedition.io.DatagramConnection;
import Javax.microedition.io.UDPDatagramConnection;
import Javax.microedition.lcdui.Alert;
import Javax.microedition.lcdui.AlertType;
import Javax.microedition.lcdui.Command;
import Javax.microedition.lcdui.CommandListener;
import Javax.microedition.lcdui.Display;
import Javax.microedition.lcdui.Displayable;
import Javax.microedition.lcdui.Form;
import Javax.microedition.lcdui.StringItem;
import Javax.microedition.lcdui.TextFIEld;

public class Server implements Runnable, CommandListener
{

    private DatagramMIDlet parent;

    private Display display;

    private Form f;

    private StringItem si;

    private TextFIEld tf;

    private Command sendCommand = new Command("Send", Command.ITEM, 1);

    Sender sender;

    private String address;

    public Server(DatagramMIDlet m)
    {
        parent = m;
        display = Display.getDisplay(parent);
        f = new Form("Datagram Server");
        si = new StringItem("Status:", " ");
        tf = new TextField("Send:", "", 30, TextFIEld.ANY);
        f.append(si);
        f.append(tf);
        f.addCommand(sendCommand);
        f.setCommandListener(this);
        display.setCurrent(f);
    }

    public void start()
    {

        Thread t = new Thread(this);
        t.start();
    }

    public void run()
    {
        try
        {

            si.setText("Waiting for connection");
            DatagramConnection dc =(DatagramConnection)Connector.open("datagram://:5555");
          

            sender = new Sender(dc);

            while (true)
            {
                Datagram dg = dc.newDatagram(100);
                dc.receive(dg);
                address = dg.getAddress();
                si.setText("Message received - "
                        + new String(dg.getData(), 0, dg.getLength()));
             
            }

        } catch (IOException ioe)
        {
            Alert a = new Alert("Server", "Port 5000 is already taken.", null,
                    AlertType.ERROR);
            a.setTimeout(Alert.FOREVER);
            a.setCommandListener(this);
            display.setCurrent(a);
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void commandAction(Command c, Displayable s)
    {
        if (c == sendCommand && !parent.isPaused())
        {
            if (address == null)
            {
                si.setText("No destination address");
            } else
            {
                sender.send(address, tf.getString());
            }
        }
        if (c == Alert.DISMISS_COMMAND)
        {
            parent.destroyApp(true);
            parent.notifyDestroyed();
        }
    }

    public void stop()
    {
    }

}

客戶端代碼則是建立連接後向服務器端發送數據,並等待接受服務器返回的數據。
package com.sIEmens.datagramtest;

import Java.io.IOException;

import Javax.microedition.io.ConnectionNotFoundException;
import Javax.microedition.io.Connector;
import Javax.microedition.io.Datagram;
import Javax.microedition.io.DatagramConnection;
import Javax.microedition.lcdui.Alert;
import Javax.microedition.lcdui.AlertType;
import Javax.microedition.lcdui.Command;
import Javax.microedition.lcdui.CommandListener;
import Javax.microedition.lcdui.Display;
import Javax.microedition.lcdui.Displayable;
import Javax.microedition.lcdui.Form;
import Javax.microedition.lcdui.StringItem;
import Javax.microedition.lcdui.TextFIEld;

public class ClIEnt implements Runnable, CommandListener
{

    private DatagramMIDlet parent;

    private Display display;

    private Form f;

    private StringItem si;

    private TextFIEld tf;

    private Command sendCommand = new Command("Send", Command.ITEM, 1);

    Sender sender;

    public ClIEnt(DatagramMIDlet m)
    {
        parent = m;
        display = Display.getDisplay(parent);
        f = new Form("Datagram ClIEnt");
        si = new StringItem("Status:", " ");
        tf = new TextField("Send:", "", 30, TextFIEld.ANY);
        f.append(si);
        f.append(tf);
        f.addCommand(sendCommand);
        f.setCommandListener(this);
        display.setCurrent(f);

    }

    public void start()
    {
        Thread t = new Thread(this);
        t.start();
    }

    public void run()
    {
        try
        {

            DatagramConnection dc = (DatagramConnection) Connector
                    .open("datagram://localhost:5555");
           

            si.setText("Connected to server");

            sender = new Sender(dc);

            while (true)
            {
                Datagram dg = dc.newDatagram(100);
                dc.receive(dg);
                // Have we actually received something or is this just a timeout
                // ?
                if (dg.getLength() > 0)
                {
                    si.setText("Message received - "
                            + new String(dg.getData(), 0, dg.getLength()));
                }
            }

        } catch (ConnectionNotFoundException cnfe)
        {
            Alert a = new Alert("ClIEnt", "Please run Server MIDlet first",
                    null, AlertType.ERROR);
            a.setTimeout(Alert.FOREVER);
            display.setCurrent(a);
        } catch (IOException ioe)
        {
            ioe.printStackTrace();
        }
    }

    public void commandAction(Command c, Displayable s)
    {
        if (c == sendCommand && !parent.isPaused())
        {
            sender.send(null, tf.getString());
        }
    }

    public void stop()
    {
    }

}
本文的代碼取自WTK demo中的例子,您可以參考demo中的源代碼!下面給出MIDlet的代碼
package com.sIEmens.datagramtest;

import Javax.microedition.lcdui.Choice;
import Javax.microedition.lcdui.ChoiceGroup;
import Javax.microedition.lcdui.Command;
import Javax.microedition.lcdui.CommandListener;
import Javax.microedition.lcdui.Display;
import Javax.microedition.lcdui.Displayable;
import Javax.microedition.lcdui.Form;
import Javax.microedition.midlet.MIDlet;

public class DatagramMIDlet extends MIDlet implements CommandListener
{

    private static final String SERVER = "Server";

    private static final String CLIENT = "ClIEnt";

    private static final String[] names = { SERVER, CLIENT };

    private static Display display;

    private Form f;

    ChoiceGroup cg;

    private boolean isPaused;

    private Command exitCommand = new Command("Exit", Command.EXIT, 1);

    private Command startCommand = new Command("Start", Command.ITEM, 1);

    public DatagramMIDlet()
    {
        display = Display.getDisplay(this);
        f = new Form("Datagram Demo");
        cg = new ChoiceGroup("Please select peer", Choice.EXCLUSIVE, names,
                null);
        f.append(cg);

        f.addCommand(exitCommand);
        f.addCommand(startCommand);
        f.setCommandListener(this);

        display.setCurrent(f);
    }

    public static Display getDisplay()
    {
        return display;
    }

    public boolean isPaused()
    {
        return isPaused;
    }

    public void startApp()
    {
        isPaused = false;
    }

    public void pauseApp()
    {
        isPaused = true;
    }

    public void destroyApp(boolean unconditional)
    {
    }

    public void commandAction(Command c, Displayable s)
    {
        if (c == exitCommand)
        {
            destroyApp(true);
            notifyDestroyed();
        } else if (c == startCommand)
        {
            String name = cg.getString(cg.getSelectedIndex());
            if (name.equals(SERVER))
            {
                Server server = new Server(this);
                server.start();
            } else
            {
                Client client = new ClIEnt(this);
                clIEnt.start();
            }
        }
    }

}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved