`
micheal19840929
  • 浏览: 166524 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

在J2ME中实现基于UDP协议通讯程序

    博客分类:
  • J2ME
阅读更多

  在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类。

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;
    }
  }

}

 

     注意联网的时候我们应该在另外一个线程中而不是在主线程中。
 
  服务器端的目的就是启动后监听指定的端口,当客户端连接过来后接受数据并记录下客户端的地址,以便服务器端向客户端发送数据。 
 

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()
  {
  }

}

 

  客户端代码则是建立连接后向服务器端发送数据,并等待接受服务器返回的数据。

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的代码

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

}

 

分享到:
评论

相关推荐

    J2ME中使用Socket开发联网程序

    在 J2ME 中,用于实现 UDP 连接的主要类是 `DatagramConnection`。 #### 三、SocketConnection 在 J2ME 中的具体应用 ##### 1. 创建服务器端监听套接字 在 J2ME 中,可以通过以下步骤创建一个 TCP 服务器端监听套...

    J2ME网络编程以及网络游戏的实现

    1. **通信协议**:网络游戏通常采用TCP或UDP协议进行通信,TCP提供可靠的连接,UDP则适合低延迟的数据传输。 2. **服务器架构**:可以是Client/Server模型,所有客户端连接到同一个服务器,或者分布式服务器架构,...

    J2ME里面的线程和网络

    3. **Datagram编程**:使用java.net.DatagramSocket和DatagramPacket,可以实现基于UDP的无连接通信,适合广播或多播。 4. **URL连接**:java.net.URL和URLConnection类用于访问HTTP、FTP等协议的网络资源,支持文件...

    基于J2ME的移动终端系统的分析与实现

    同时,J2ME也支持其他通信协议,如TCP/IP和UDP,确保了数据传输的安全与稳定。 此外,用户界面设计对于提升用户体验至关重要。J2ME提供了丰富的用户界面组件和工具,允许开发者创建直观、友好的界面,增强应用程序...

    QQ聊天+j2me+java

    3. 编写通信协议:根据QQ聊天服务的协议(可能是基于XML、JSON或其他格式),编写客户端的通信逻辑,确保消息的正确发送和接收。 4. 数据管理:实现RMS功能,存储用户信息和聊天记录,同时处理数据同步,防止数据...

    基于J2ME的手机游戏开发模式

    基于J2ME的手机游戏开发模式,是早期智能手机游戏开发中的一个重要方向。J2ME,即Java2平台微型版(Java Platform Micro Edition),是Sun Microsystems为嵌入式设备和移动设备设计的一种Java平台版本。在2000年代初...

    J2ME中文帮助文档

    8. **ByteArrayInputStream/ByteArrayOutputStream**: 提供基于内存的字节流实现,用于读写字节数组。 9. **Calendar**: 提供操作日期和时间的方法。 10. **Canvas**: 用于绘制图形和处理用户输入的基本组件。 ...

    第十章无线网络开发--j2me开发.ppt

    - **创建连接**:在J2ME中,`Connector.open()`方法使用URL参数创建连接,返回一个实现了特定连接接口的对象。GCF的平台无关性使其无需依赖设备的特有功能,而是通过提供的连接协议(如HTTP、UDP、Socket)创建实际...

    《J2ME简单介绍》.rar

    4. **网络连接**:J2ME提供了网络通信的能力,包括HTTP、TCP/IP和UDP协议,使应用程序能够访问互联网资源,实现数据同步、在线更新等功能。 5. **安全性**:J2ME应用在设备上运行时受到严格的权限控制,以确保安全...

    J2ME MIDP 手机编程实例集源码.rar

    在J2ME中,通过javax.microedition.io.Connector和java.net.Socket类来实现UDP通信。开发者需要创建DatagramSocket,发送和接收DatagramPacket来交换数据。这个实例集中的代码将展示如何有效地使用这些类来实现游戏...

    j2me精解

    3. 网络功能:通过HttpConnection和DatagramConnection,MIDP可以实现HTTP和UDP协议的网络通信。 4. 文件系统:MIDP有受限的文件存储功能,可用于保存应用程序数据。 四、CLDC(Connected Limited Device ...

    基于Android平台的汇集团购信息业务描述.pdf

    - **指令服务**:使用J2ME与Android通过Socket通信,采用UDP协议处理客户端指令,完成操作后通过Socket返回结果。该过程包括接收连接请求、解析指令、执行操作和反馈结果。 4. **客户端设计** 客户端基于Android...

    Sprint J2ME Requirements v2.2

    - **目标与推荐**:文档旨在确保所有基于J2ME的产品和服务均符合Sprint的要求标准,以便提供一致且高质量的用户体验。 - **设备范围**:规定了哪些类型的设备(如手机、PDA等)需遵循该规范。 - **合规矩阵**:提供...

    基于java的移动通讯技术研究

    论文《基于Java的移动通讯技术研究》可能涵盖了以上各个方面的理论分析和实际案例,详细讨论了如何利用Java技术解决移动通信中的问题,以及如何提升用户体验。此外,附带的文件列表中包含多个图片文件,可能是论文中...

    自己动手写SIP协议栈

    最后,文档中还记录了一项在局域网内进行的SIP通信实验,验证了ZmhSipStack及其应用程序在实际环境中的表现。这一部分详细描述了实验条件、步骤以及最终的结果。 通过上述内容可以看出,SIP协议栈的实现不仅涉及...

    j2me api中文版

    20. **CommConnection**: 通信连接接口,用于定义串行或并行通信协议。 21. **Command**: 用户界面中的命令,例如按钮点击事件。 22. **CommandListener**: 监听命令事件的接口。 23. **Connection**: 通用的网络...

    毕业设计简介

    学生需要掌握嵌入式系统开发、RS232协议和以太网协议,以及如何在资源受限的环境中实现高效的数据传输。 3. **基于 CDMA 网络的图像传输** CDMA是一种无线通信标准,用于移动电话网络。传输图像需要了解CDMA网络...

    Socket-JAVA-test.rar_java mtk_mtk java

    StreamSocket基于TCP协议,提供可靠的、面向连接的服务,而DatagramSocket基于UDP协议,提供无连接、不可靠的数据报服务。 在"Socket-JAVA-test.rar"这个压缩包中,我们可以期待找到一个使用StreamSocket的示例,...

    java源码包---java 源码 大量 实例

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

Global site tag (gtag.js) - Google Analytics