netty04(重點來了、指定某個客戶端發信息或者群發)小聲嘀咕~~我也是從零開始學得、、、想學習netty的又不知道怎麼下手的童鞋們~~
阿新 • • 發佈:2018-11-09
還是和上幾篇一樣,先給出前面筆記的連線,有沒看的可以去看看再來!
看到這裡、你基本上可以使用netty接受資訊和根據對應的資訊返回資訊了
接下來我們在web專案中使用,通過訪問去啟動,通過請求去給指定的客戶端發信息,所以說到這篇就是重點了,我們不講底層,不講理論,直接上程式碼!
因為自己就是從零開始的,一上來你就給我講一大堆理論、底層、我就mmp哦!瞭解底層我個人覺得你總是得會基本的使用瞭然後再開始去理解底層吧,不然那麼枯燥無味的事情,誰會喜歡?
那我們就接著上一篇的來哈!
package com.netty.nettys01; import com.service.NettyTest01; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelId; import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; import io.netty.util.concurrent.GlobalEventExecutor; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import static org.apache.http.Consts.UTF_8; public class DiscardServerHandler extendsChannelInboundHandlerAdapter { /** * 在這裡使用DefaultChannelGroup將每次連線的 Channel 存起來,每一個Channel 底層就是一個連線 */ private static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); private static final Map map = new HashMap<String,ChannelId>(); @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { /** * 這裡就是添加了 */ channels.add(ctx.channel()); /** * 獲取每一個連線的唯一標示吧,相當於 */ ChannelId Id= ctx.channel().id(); /** * map就不用解釋了吧,這裡就用 1 代替了key;正常專案的話肯定使用使用者的唯一標示了 */ map.put("1",Id); /** * 這裡只是寫了個測試遍歷了一下 */ Iterator<Channel> ls= channels.iterator(); while (ls.hasNext()){ Channel l= ls.next(); System.out.println(l.id().toString()); } } /** * 下面這兩個get方法是個人使用方法,不好的還希望大家給點意見 * @return */ public static ChannelGroup getChannels() { return channels; } public static Map getMap() { return map; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf in=(ByteBuf)msg; System.out.println(ctx.channel().id().toString()+"收到資訊:"+in.toString(UTF_8)); String reMsg="66666"; ByteBuf in2= Unpooled.copiedBuffer(reMsg.getBytes()); ctx.writeAndFlush(in2); new NettyTest01().test(null,null); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
對於上面的程式碼,雖然有註釋了。不過我還是說一下大概思路吧
channelActive 這個方法會在每次有連線進來的時候執行!
DefaultChannelGroup 這個物件可以用來儲存連線,其實我覺得用其他的存也可以哈,不過既然netty本身提供了,我想應該有它自己的優勢吧
最後使用一個map存下了登入的唯一標示;雖然key寫死了為 1;也就是每次登入會覆蓋上一個;這裡就只模擬指定發給最後一個登入的客戶端了,儲存的方式有很多,基於每個專案架構的不同,我也就不多說了!
下面是發信息的類
package com.service; import com.netty.nettys01.DiscardServerHandler; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelId; import io.netty.channel.group.ChannelGroup; import org.springframework.stereotype.Service; import java.util.Iterator; import java.util.Map; @Service public class NettyTest01 { public void test(ChannelId id,String key){ /** * 每次呼叫獲取所有的連線; */ ChannelGroup channelGroup=DiscardServerHandler.getChannels(); Map<String,ChannelId> map= DiscardServerHandler.getMap(); if (key!=null){ ChannelId id2= map.get("1"); Channel el= channelGroup.find(id2); el.writeAndFlush(Unpooled.copiedBuffer("99999".getBytes())); return; } Iterator<Channel> ls= channelGroup .iterator(); while (ls.hasNext()){ Channel l= ls.next(); System.out.println(l.id().toString()); l.writeAndFlush(Unpooled.copiedBuffer("1234545".getBytes())); } } }
接著說這個類的思路吧,這個類寫在service層,交由spring管理了;自然就可以注入到你想注入的地方了!
呼叫方法判斷是否傳入key,如果不傳入就群發,傳入了就發給指定的,當然這裡的規則就是你們自己定了
就是根據對應的key獲取對應的連線,然後傳送資訊
下面的是controller 層 的訪問啟動服務程式碼,隨意寫個案例,我就隨便放程式碼了(*╹▽╹*)
package com.controller; import com.netty.nettys01.DiscardServer; import com.service.NettyTest01; import com.service.TestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class Controller01 { @Autowired private TestService testService; @Autowired private NettyTest01 nettyTest01; @Autowired private ThreadPoolTaskExecutor threadPoolTaskExecutor; @RequestMapping("test2") public String test02() throws Exception { System.out.println(123); int c= threadPoolTaskExecutor.getActiveCount(); System.out.println("c="+c); nettyTest01.test(null,"1"); return "index"; } @RequestMapping("test4") @ResponseBody public String test04() throws Exception { new Thread(new Runnable() { public void run() { int port; /* if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; }*/ port = 8089; try { new DiscardServer(port).run(); }catch (Exception e){ System.out.println(123); } } }).start(); return "1"; } @RequestMapping("test3") @ResponseBody public int test03(){ System.out.println(123); /* for(int i=0;i<100;i++){ threadPoolTaskExecutor.execute(new Runnable() { public void run() { synchronized (Controller01.class) { try { String i= HttpUtils.get("http://192.168.31.223:8085/test4.do"); System.out.println(i); System.out.println(System.currentTimeMillis()); } catch (Exception e) { e.printStackTrace(); } } } }); }*/ return testService.get(); } }
說一下這個類吧,test4 請求是用來啟動的,由於本身啟動是堵塞的,所以使用執行緒啟動。。。。。。
test2 是收到請求以後會給key為1的連線傳送資訊
回到上面的方法 可以看出 是給最後一個連線傳送了資訊 99999 這個就是指定的發了
如果傳入兩個 null ,就會群發了。。。這篇先說到這裡 ,。。。因為我也還在學習。。。。。