zoukankan      html  css  js  c++  java
  • 在J2ME中实现基于UDP协议通讯程序

    在GCF中提供了DatagramConnection和Datagram两个接口,借助他们我们可以在J2ME中基于UDP协议开发联网应用程序。在MIDP2.0中,添加了UDPDatagramConnection这个接口,他扩展了DatagramConnection并添加了两个方法getLocalAddress()和getLocalPort()。我们知道UDP服务是不可靠的,如果你希望开发更可靠的联网应用的话可以采用SocketConnection,因为TCP服务是面向连接且可靠的。我们还必须清楚地一点是以上所说的各种连接方式都不是MIDP规范中规定必须实现的。因此在使用之前请参考特定设备的开发文档。MIDP中只有Http连接是必须支持的。 

      同样,我们要获得DatagramConnection的话,必须通过Connector的open方法,其中的URL应该满足如下的形式。 
    datagram://localhost:5555 这样的话表示建立了一个客户端模式的连接。在指定ip:localhost和指定端口:5555 
    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();
          }
        }
      }

    }


    查看本文来源

    上进,务实
  • 相关阅读:
    Python记录12:迭代器+生成器+生成式
    Python记录11:叠加多个装饰器+有参装饰器
    Python记录10:模块
    Day7
    Day7
    Day7
    Day7
    Day7
    Day7
    Day7
  • 原文地址:https://www.cnblogs.com/gaonengquan/p/1374390.html
Copyright © 2011-2022 走看看