GCF (Generic Connection Framework) 提供 DatagramConnection 與 Datagram 介面支援 UDP 通訊。MIDP 2.0 新增 UDPDatagramConnection 擴充介面,提供 getLocalAddress()、getLocalPort() 方法。本文完整示範 UDP 客戶端/伺服器雙向通訊實作。
datagram://host:port — 客戶端模式,指定目標位址datagram://:port — 伺服器模式,綁定本地埠號監聽public class Sender extends Thread {
private DatagramConnection conn;
private String targetAddr;
private String message;
public Sender(DatagramConnection conn) {
this.conn = conn;
start();
}
public synchronized void send(String addr, String msg) {
targetAddr = addr;
message = msg;
notify();
}
public void run() {
while (true) {
synchronized (this) {
if (message == null) {
try { wait(); } catch (InterruptedException e) {}
}
}
try {
byte[] data = message.getBytes();
Datagram dg;
if (targetAddr == null) {
dg = conn.newDatagram(data, data.length);
} else {
dg = conn.newDatagram(data, data.length, targetAddr);
}
conn.send(dg);
} catch (IOException e) {
e.printStackTrace();
}
message = null;
}
}
}
public class UdpServer implements Runnable, CommandListener {
private DatagramMIDlet midlet;
private Display display;
private Form form;
private StringItem status;
private TextField input;
private Sender sender;
private String clientAddr;
public UdpServer(DatagramMIDlet midlet) {
this.midlet = midlet;
display = Display.getDisplay(midlet);
form = new Form("UDP Server");
status = new StringItem("狀態:", "等待連線...");
input = new TextField("發送:", "", 30, TextField.ANY);
form.append(status);
form.append(input);
form.addCommand(new Command("發送", Command.ITEM, 1));
form.setCommandListener(this);
display.setCurrent(form);
}
public void start() { new Thread(this).start(); }
public void run() {
try {
DatagramConnection dc = (DatagramConnection)
Connector.open("datagram://:5555");
sender = new Sender(dc);
status.setText("監聽埠 5555...");
while (true) {
Datagram dg = dc.newDatagram(100);
dc.receive(dg);
clientAddr = dg.getAddress();
String msg = new String(dg.getData(), 0, dg.getLength());
status.setText("收到: " + msg);
}
} catch (IOException e) {
showAlert("錯誤", "埠 5555 已被佔用");
}
}
public void commandAction(Command c, Displayable d) {
if (c.getLabel().equals("發送") && clientAddr != null) {
sender.send(clientAddr, input.getString());
}
}
}
public class UdpClient implements Runnable, CommandListener {
private DatagramMIDlet midlet;
private Display display;
private Form form;
private StringItem status;
private TextField input;
private Sender sender;
public UdpClient(DatagramMIDlet midlet) {
this.midlet = midlet;
display = Display.getDisplay(midlet);
form = new Form("UDP Client");
status = new StringItem("狀態:", "");
input = new TextField("發送:", "", 30, TextField.ANY);
form.append(status);
form.append(input);
form.addCommand(new Command("發送", Command.ITEM, 1));
form.setCommandListener(this);
display.setCurrent(form);
}
public void start() { new Thread(this).start(); }
public void run() {
try {
DatagramConnection dc = (DatagramConnection)
Connector.open("datagram://localhost:5555");
sender = new Sender(dc);
status.setText("已連線至伺服器");
while (true) {
Datagram dg = dc.newDatagram(100);
dc.receive(dg);
if (dg.getLength() > 0) {
String msg = new String(dg.getData(), 0, dg.getLength());
status.setText("收到: " + msg);
}
}
} catch (ConnectionNotFoundException e) {
showAlert("錯誤", "請先啟動伺服器");
} catch (IOException e) {
e.printStackTrace();
}
}
public void commandAction(Command c, Displayable d) {
if (c.getLabel().equals("發送")) {
sender.send(null, input.getString()); // null 表示用連線目標
}
}
}
public class DatagramMIDlet extends MIDlet implements CommandListener {
private Form menu;
private ChoiceGroup modeChoice;
private boolean paused;
protected void startApp() {
paused = false;
if (menu == null) {
menu = new Form("UDP Demo");
modeChoice = new ChoiceGroup("選擇模式", Choice.EXCLUSIVE);
modeChoice.append("伺服器", null);
modeChoice.append("客戶端", null);
menu.append(modeChoice);
menu.addCommand(new Command("啟動", Command.ITEM, 1));
menu.addCommand(new Command("離開", Command.EXIT, 2));
menu.setCommandListener(this);
}
Display.getDisplay(this).setCurrent(menu);
}
public void commandAction(Command c, Displayable d) {
if (c.getCommandType() == Command.EXIT) {
destroyApp(true); notifyDestroyed();
} else if (c.getLabel().equals("啟動")) {
String mode = modeChoice.getString(modeChoice.getSelectedIndex());
if (mode.equals("伺服器")) new UdpServer(this).start();
else new UdpClient(this).start();
}
}
public boolean isPaused() { return paused; }
public void pauseApp() { paused = true; }
public void destroyApp(boolean u) {}
}
finally 中關閉 DatagramConnectionUDP 適合對延遲敏感、可容忍偶發丟包的應用。若需可靠傳輸,請改用 TCP (SocketConnection) 或 HTTP。