1、定义Callback接口
package eco.data.m3.supernode.udp;
public interface Callback {
void onMessage(String content);
void onFault(String reason);
}
2.定义客户端
package eco.data.m3.supernode.udp;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//import java.net.DatagramPacket;
import java.awt.image.BufferedImageFilter;
import java.net.InetSocketAddress;
import java.lang.String;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Random;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class Client {
private static Logger logger = LoggerFactory.getLogger(Client.class);
public static final int MessageReceived = 0x99;
private int scanPort;
private HashMap<Integer, Callback> callbackHashMap = new HashMap<>();
Channel channel;
public Client(int scanPort) {
this.scanPort = scanPort;
init();
}
private void init(){
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new ClientHandler(this));
try {
channel = b.bind(scanPort).sync().channel();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class ClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
Client client;
public ClientHandler(Client client) {
this.client = client;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg0) throws Exception {
byte[] resp =new byte[45];
msg0.content().readBytes(resp);
int convId=byteArrayToInt(subBytes(resp,0,4));
System.out.println(convId);
int SrcPort=byteArrayToInt(subBytes(resp,4,4));
int DesPort=byteArrayToInt(subBytes(resp,8,4));
String SrcIp=new String(subBytes(resp,12,12), "utf-8");
String DestIp=new String(subBytes(resp,24,12), "utf-8");
String data0=new String(subBytes(resp,40,5), "utf-8");
System.out.println(SrcPort);
System.out.println(DesPort);
System.out.println(SrcIp);
System.out.println(DestIp);
System.out.println(data0);
Callback callback = client.getCallbackHashMap().get(convId);
if (callback==null){
///
// reply
// sendPackage(msg0)
// forward
}else {
callback.onMessage("sd");
}
// if(response.startsWith("结果:")){
// System.out.println(response);
// ctx.close();
// }
}
}
public void sendPackage(int convId,String data,int SrcPort,int DesPort,String SrcIp,String DestIp ,int nextPort, Callback callback) {
try {
//System.out.println(convId);
Udp_Message_Test msg=new Udp_Message_Test(0,0,0,null,null,null);
msg.setconvId(convId);
msg.setSrcPort(SrcPort);
msg.setDesPort(DesPort);
msg.setSrcIp(SrcIp);
msg.setDestIp(DestIp);
msg.setContent(data);
byte[] data_buf=con_byte(msg.getContent(),msg.getconvId(),msg.getSrcPort(),msg.getDesPort(),msg.getSrcIp(),msg.getDestIp() ,nextPort);
//DatagramPacket dp = new DatagramPacket( Unpooled.copiedBuffer("hello!!!", CharsetUtil.UTF_8), new InetSocketAddress("10.108.78.53", scanPort));//不同节点这句需要修改(可能需要加判断)
// ByteBuf buff = (ByteBuf) data_buf;//需要字节数组转ByteBuf
ByteBuf buff = Unpooled.buffer(16);
// buff.writeInt(scanPort);
buff.writeBytes(data_buf);
// System.out.println(data_buf);
DatagramPacket dp = new DatagramPacket(buff ,new InetSocketAddress("127.0.0.1", nextPort));//不同节点这句需要修改(可能需要加判断)
channel.writeAndFlush(dp).sync();
callbackHashMap.put(convId, callback);
logger.info("Search, sendPackage()");
// System.out.println(byteArrayToInt(subBytes(data_buf,0,4)));
}catch (Exception e){
e.printStackTrace();
logger.info("Search, An Error Occur ==>" + e);
}
}
public byte[] con_byte(String data,int convId,int SrcPort,int DesPort,String SrcIp,String DestIp ,int scanPort){
byte[] buf1 = new byte[4];
buf1[0] = (byte) ((convId >> 24) & 0xFF);
buf1[1] = (byte) ((convId >> 16) & 0xFF);
buf1[2] = (byte) ((convId >> 8) & 0xFF);
buf1[3] = (byte) (convId & 0xFF);
byte[] buf2 = new byte[4];
buf2[0] = (byte) ((SrcPort >> 24) & 0xFF);
buf2[1] = (byte) ((SrcPort >> 16) & 0xFF);
buf2[2] = (byte) ((SrcPort >> 8) & 0xFF);
buf2[3] = (byte) (SrcPort & 0xFF);
byte[] buf3 = new byte[4];
buf3[0] = (byte) ((DesPort >> 24) & 0xFF);
buf3[1] = (byte) ((DesPort >> 16) & 0xFF);
buf3[2] = (byte) ((DesPort >> 8) & 0xFF);
buf3[3] = (byte) (DesPort & 0xFF);
byte[] buf4 = new byte[SrcIp.length()];
buf4=SrcIp.getBytes();
byte[] buf5 = new byte[DestIp.length()];
buf5=DestIp.getBytes();
byte[] buf6 = new byte[4];
buf6[0] = (byte) ((scanPort >> 24) & 0xFF);
buf6[1] = (byte) ((scanPort >> 16) & 0xFF);
buf6[2] = (byte) ((scanPort >> 8) & 0xFF);
buf6[3] = (byte) (scanPort & 0xFF);
byte[] buf7 = new byte[data.length()];
buf7=data.getBytes();
byte[] buf = new byte[16 +SrcIp.length()+DestIp.length()+data.length()];
System.arraycopy(buf1, 0, buf, 0, 4);
System.arraycopy(buf2, 0, buf, 4, 4);
System.arraycopy(buf3, 0, buf, 8, 4);
System.arraycopy(buf4, 0, buf, 12, SrcIp.length());
System.arraycopy(buf5, 0, buf, 12+SrcIp.length(),DestIp.length() );
System.arraycopy(buf6, 0, buf, 12+SrcIp.length()+DestIp.length(),4 );
System.arraycopy(buf7, 0, buf, 16+SrcIp.length()+DestIp.length(),data.length());
return buf;
}
public static byte[] subBytes(byte[] src, int begin, int count) {
byte[] bs = new byte[count];
System.arraycopy(src, begin, bs, 0, count);
return bs;
}
//byte 数组与 int 的相互转换
public static int byteArrayToInt(byte[] b) {
return b[3] & 0xFF |
(b[2] & 0xFF) << 8 |
(b[1] & 0xFF) << 16 |
(b[0] & 0xFF) << 24;
}
public HashMap<Integer, Callback> getCallbackHashMap() {
return callbackHashMap;
}
}
3、定义传输的消息格式
package eco.data.m3.supernode.udp;
import java.io.IOException;
import java.lang.String;
import eco.data.m3.net.util.StreamUtil;
import io.netty.buffer.ByteBuf;
public class Udp_Message_Test {
private int convId;
private int SrcPort;
private int DesPort;
private String SrcIp;
private String DestIp;
private String content;
public Udp_Message_Test( int convId,int SrcPort,int DesPort,String SrcIp,String DestIp,String content){
this.convId=convId;
this.SrcPort=SrcPort;
this.DesPort=DesPort;
this.SrcIp=SrcIp;
this.DestIp=DestIp;
this.content = content;
}
public void toByteBuf(ByteBuf out) throws IOException {
out.writeInt(this.convId);
out.writeInt(this.SrcPort);
out.writeInt(this.DesPort);
StreamUtil.toStream(this.SrcIp, out);
StreamUtil.toStream(this.DestIp, out);
StreamUtil.toStream(this.content, out);
}
public void fromByteBuf(ByteBuf in) throws IOException {
this.convId = in.readInt();
this.SrcPort = in.readInt();
this.DesPort = in.readInt();
this.SrcIp = StreamUtil.stringFromStream(in);
this.DestIp = StreamUtil.stringFromStream(in);
this.content = StreamUtil.stringFromStream(in);
}
public int getconvId() {
return convId;
}
public void setconvId(int convId ) {
this.convId = convId ;
}
public int getSrcPort() {
return SrcPort;
}
public void setSrcPort(int SrcPort) {
this.SrcPort =SrcPort ;
}
public int getDesPort() {
return DesPort;
}
public void setDesPort(int DesPort) {
this.DesPort =DesPort ;
}
public String getSrcIp() {
return SrcIp;
}
public void setSrcIp(String SrcIp) {
this.SrcIp =SrcIp ;
}
public String getDestIp() {
return DestIp;
}
public void setDestIp(String DestIp) {
this.DestIp =DestIp ;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
4.定义测试类
package eco.data.m3.supernode.udp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Random;
/**
* Created by Lovell on 9/29/16.
*/
public class Test {
private static Logger logger = LoggerFactory.getLogger(Test.class);
@org.junit.Test
public void test1() throws Exception {
// Server.initServer();
Client client2 = new Client(8698);
int convId = new Random().nextInt();
client2.sendPackage(convId,"hello",8698,8699,"10.108.78.53",
"10.108.78.53", 8698,new Callback() {
@Override
public void onMessage(String content) {
//
success = true;
System.out.println("收到回调结果");
}
@Override
public void onFault(String reason) {
}
});
}
boolean success = false;
@org.junit.Test
public void test2() throws Exception {
Client client = new Client(8699);//client的监听端口
int convId = new Random().nextInt();
client.sendPackage(convId,"hello",8699,8698,"127.0.0.1",
"127.0.0.1", 8699,new Callback() {
@Override
public void onMessage(String content) {
//
success = true;
System.out.println("收到回调结果");
}
@Override
public void onFault(String reason) {
}
});
// client2.sendPackage("hello",8690,8691,"10.108.78.53",
// "12.7.0.0.1", 8698,new Callback() {
// @Override
// public void onMessage(String content) {
//
// //
// success = true;
//
//
// }
//
// @Override
// public void onFault(String reason) {
//
// }
// });
// client.sendPackage("hello", new Callback() {
// @Override
// public void onMessage(String content) {
// //
// success = true;
//
//
// }
//
// @Override
// public void onFault(String reason) {
//
// }
// });
// client.sendPackage("hello", new Callback() {
// @Override
// public void onMessage(String content) {
// //
// success = true;
//
//
// }
//
// @Override
// public void onFault(String reason) {
//
// }
// });
// client.sendPackage("hello", new Callback() {
// @Override
// public void onMessage(String content) {
// //
// success = true;
//
//
// }
//
// @Override
// public void onFault(String reason) {
//
// }
// });
long untilTime = System.currentTimeMillis() + 10000;
while (System.currentTimeMillis()<untilTime){
Thread.sleep(10);
if(success==true){
System.out.println("回调完成");
break;
}
}
Thread.sleep(100000);
}
}
Test类每定义一个client对象,调用sendPackage方法,就建立一个回调,随机生成一个整型数字convid,以<convid,callback>的形式存入哈希表中。在这里的测试中,本机给本机发送消息,触发client里的channelread0()方法,获取数据帧中的convid,判断哈希表中是否有对应的callback。如有,就调用onMessage方法回调回去。(也可以给其他节点发,但是要回复消息给本节点)
最后,放一个测试结果。
参考文章:https://blog.csdn.net/xiaanming/article/details/8703708/
http://www.voidcn.com/article/p-zsnrikrg-mm.html