代码的基本思想是:创建两个线程R/S, R刚开始会等待S的广播数据,如果R接收到S的广播数据,就回就一个字符串给S,S接收到字符串后打印出来
记得先在AndroidManifest.xml当中加入否则发送数据会报异常,出现EACCES错误.
直接看代码吧.
package com.helloworld;
import java.net.NetworkInterface;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import org.apache.http.conn.util.InetAddressUtils;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.KeyEvent;
import android.view.InputEvent;
import android.widget.ListView;
public class MainActivity extends Activity {
private static int UDP_PORT = 9111; // UDP通信端口
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// TODO Auto-generated method stub
Receiver r = new Receiver(); // Receiver实例
Sender s = new Sender(); // Sender实例
r.start(); // 主线程根本不允许进行socket通信,所以Sender/Receiver都是基于线程的,这里启动他们就是了,先让r启动起来阻塞在receive函数上
s.start(); // s启动后等待了3S才发数据
}
public static class Receiver extends Thread {
public void run() {
byte[] buf = new byte[1024];
DatagramSocket sock = null;
DatagramPacket pack = null;
try {
sock = new DatagramSocket(UDP_PORT);
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
/*
try {
sock.setBroadcast(true); // 这一步可以省掉,因为默认是true
} catch (SocketException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
*/
pack = new DatagramPacket(buf, buf.length);
System.out.println("Receiver# Waiting...");
try {
sock.setSoTimeout(5000); // 接收等待时长
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
sock.receive(pack);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Receiver# Got from " +
pack.getAddress().toString() + " : " +
pack.getPort() + " -> " +
new String(buf, 0, pack.getLength())); // 如果你确定收到的数据是字符串,需要打印的话这里要new一个String出来,用pack.getData().toString()打印出来是一堆16进制数
// 等待500MS后再发数据出去
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String smsg = new String("I'm a server...");
DatagramPacket spack = new DatagramPacket(smsg.getBytes(), smsg.getBytes().length, pack.getAddress(), pack.getPort());
try {
sock.send(spack);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Receiver# Sent to " + pack.getAddress().toString() + ":" + pack.getPort() + " -> " + smsg.toString());
sock.close();
}
}
public static class Sender extends Thread {
public void run () {
DatagramSocket sock = null;
String s = new String("HHHHHHello");
/* 打印所以网络设备上绑定的IP
Enumeration en = null;
try {
en = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
while (en.hasMoreElements()) {
NetworkInterface ni = en.nextElement();
Enumeration ias = ni.getInetAddresses();
while (ias.hasMoreElements()) {
InetAddress ia = ias.nextElement();
if (ia.isLoopbackAddress() ||
ia.isLinkLocalAddress() ||
InetAddressUtils.isIPv6Address(ia.getHostAddress())) {
continue;
}
if (!InetAddressUtils.isIPv4Address(ia.getHostAddress())) {
continue;
}
System.out.println("IP: " + ia.getHostAddress().toString() + " for " + ni.toString());
}
}
*/
// 等3S再发,防止另外一边还没有准备好接收
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
InetAddress ia = null;
try {
ia = InetAddress.getByName("255.255.255.255"); // 广播地址
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Sender# LocalHost: " + ia.getHostAddress().toString());
System.out.println("Sender# IA " + ia.toString());
try {
sock = new DatagramSocket();
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
/* 同样可以省掉
try {
sock.setBroadcast(true);
} catch (SocketException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
*/
DatagramPacket spack = new DatagramPacket(s.getBytes(), s.getBytes().length, ia, UDP_PORT);
try {
sock.send(spack);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("Sender# Sent to 255.255.255.255:" + UDP_PORT + " -> " + s.toString());
System.out.println("Sender# Then wait response...");
byte[] rbuf = new byte[1024];
DatagramPacket rpack = new DatagramPacket(rbuf, rbuf.length);
// 设置一个超时时间,别让receive一直阻塞
try {
sock.setSoTimeout(3000);
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
boolean timeout = false;
try {
try {
sock.receive(rpack); // 这里的receive没有指定端口号,我想不通为什么他能接收到数据,在Receiver里面第一次接收时如果不指定端口号,就会出空指针异常,这里还需要再找找原因??????
} catch (SocketTimeoutException e1) {
timeout = true;
e1.printStackTrace();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (timeout) { // 不知道怎么判断到底接收到数据没,我用rpack.getLength()取长度,总是会>0,所以这里用个标志
System.out.println("Sender# Wait timeout...");
} else {
System.out.println("Sender# Got:" + new String(rbuf, 0, rpack.getLength()));
}
sock.close();
}
}
}
阅读(2588) | 评论(0) | 转发(0) |