服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

在j2me中实现基于udp协议通讯程序


  在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();
      }
    }
  }

}

扫描关注微信公众号