实际上,单播就是一个报文从源主机向另一个目标主机发送,接收目标只有一个.
首先,写收发器类datagramrecvsender_s,这个类既要发送数据报又要接收数据报,发送一个文件夹中的所有图片,一张一张的进行,接收是在一个线程中进行,每收完一个文件,就激活一个事件,事件处理器处理这个事件.
类清单为:
package recmail.multiservice;
import java.net.datagrampacket;
import java.net.datagramsocket;
import java.net.socketexception;
import java.net.socketaddress;
import java.net.unknownhostexception;
import java.net.inetsocketaddress;
import java.io.ioexception;
import java.util.arraylist;
import java.net.inetaddress;
import java.io.file;
import java.util.iterator;
public class datagramrecvsender_s extends dataswaplisteneradapter
implements runnable {
public static final int datagramport = 10698;
private java.net.datagramsocket road;
private inetaddress ia;
datagrampacket dp;
public static final int datagram_length = 8192;
private datapacket cdp;
private boolean ishandling = true;
dataswapevent dsevent;
/**
* 这个构造器用于接收数据报.
*/
public datagramrecvsender_s() {
try {
system.out.println(“recv …”);
ia = inetaddress.getbyname(“localhost”);//192.168.0.17″127.0.0.1″
dsevent = new dataswapevent(this);
socketaddress sa = new inetsocketaddress(ia,
datagramrecvsender_s.datagramport);
//至少要指定数据报接收端口,这是对接收端的唯一要求.当然如果主机是多址主机,需要road = new datagramsocket(sa);
road = new datagramsocket(datagramrecvsender_s.datagramport);
system.out.println(road.isbound()+”::”+road.getbroadcast());
}
catch (socketexception ex) {
ex.printstacktrace();
}
catch (exception ex1) {
ex1.printstacktrace();
}
}
/**
* 这个构造器用于发送数据报.
* @param send string
*/
public datagramrecvsender_s(string send) {
try {
system.out.println(“start sending …”);
ia = inetaddress.getbyname(“192.168.0.4″);//”255.255.255.255″”192.168.0.4″”127.0.0.1”
dsevent = new dataswapevent(this);
socketaddress sa = new inetsocketaddress(ia,
datagramrecvsender_s.datagramport);
//如果需要接收数据报,就需要指定一个端口,否则不必指定.road = new datagramsocket(datagramrecvsender_s.datagramport-1);
road = new datagramsocket();
system.out.println(“isbound–“+road.isbound()+”:getbroadcast–“+road.getbroadcast());
}
catch (socketexception ex) {
ex.printstacktrace();
}
catch (unknownhostexception ex1) {
ex1.printstacktrace();
}
}
public void sendfile(string file) {
cdp = new datapacket(file);
system.out.println(file);
iterator it = cdp.getdatapackets().iterator();
byte[] b;
while (it.hasnext()) {
b = ( (dataentry) it.next()).getbyte();
//数据报是自包含的,自描述的数据,它的投递是由路由器执行的,路由器路由算法根据报文的目标地址选择适当的路由递送报文,
//所以数据报中要指定目标ip地址和目标主机处理端口.
datagrampacket dp = new datagrampacket(b, 0, b.length, ia,datagramrecvsender_s.datagramport);
try {
thread.sleep(100);
if(dp==null)
continue;
road.send(dp);
}
catch (exception ex) {
ex.printstacktrace();
}
}
}
public boolean ishandling() {
return ishandling;
}
public void ishandling(boolean ishand) {
ishandling = ishand;
}
public void run() {
byte[] buffer = new byte[datapacket.dataswapsize];
datagrampacket packet = new datagrampacket(buffer, buffer.length);
datapacket dp = new datapacket();
while (ishandling) {
packet.setlength(buffer.length);
system.out.println(“wait .. “);
try {
road.receive(packet);
dp.add(packet.getdata());
if (dp.isfull()) {
dsevent.setimage(dp.gereratedata());
this.processrecvfinishedevent(dsevent);
dp = new datapacket();
}
}
catch (ioexception ex) {
system.out.println(ex);
}
}
}
public static void main(string[] args) {
string file[];
arraylist al = new arraylist();
string path = “e:\\nature\\”;
file f = new file(path);
file = f.list();
datagramrecvsender_s dgrs = new datagramrecvsender_s(“”);
for(int j=0;j<1000;j++)
for (int i = 0; i < file.length; i++) {
try {
thread.sleep(2000);
}
catch (interruptedexception ex) {
}
if (file[i].endswith(“jpg”) || file[i].endswith(“bmp”))
dgrs.sendfile(path + file[i]);
}
}
}
下面看接收端的界面.
package recmail.multiservice;
import java.awt.borderlayout;
public class testdual
extends dualwindow implements dataswaplistener {
jimagepanel ip;
java.awt.image bi;
public testdual() {
}
public void init() {
super.init();
imageshow is = new imageshow();
is.adddataswaplistener(this);
thread thread = new thread(is, “test”);
thread.start();
}
public static void main(string[] args) {
testdual test = new testdual();
test.initmain();
test.go();
datagramrecvsender_s dgrs = new datagramrecvsender_s();
dgrs.adddataswaplistener(test);
thread thread = new thread(dgrs, “test”);
thread.start();
}
public void initmain() {
super.initmain();
ip = new jimagepanel();
root.setlayout(new borderlayout(5, 5));
root.add(ip, borderlayout.center);
}
public void ondatasendfinished(object s, dataswapevent e) {
}
public void ondatarecvfinished(object s, dataswapevent e) {
this.bi = e.getimage();
ip.setimage(bi);
system.out.println(“recv finished!”);
}
}
testdual扩展的dualwindow类清单:
package recmail.multiservice;
import javax.swing.jpanel;
import javax.swing.jframe;
import javax.swing.japplet;
public class dualwindow
extends japplet {
protected jpanel root;
private jframe frame;
public dualwindow() {
}
public void init() {
root = new jpanel();
this.setcontentpane(root);
}
public void initmain() {
root = new jpanel();
}
public static void main(string[] args) {
testdual test = new testdual();
test.initmain();
test.start();
test.go();
}
public void go() {
frame = new jframe();
frame.setcontentpane(root);
frame.setdefaultcloseoperation(jframe.exit_on_close);
frame.setsize(300, 200);
frame.validate();
frame.setvisible(true);
}
}
下一篇介绍广播的实现.