Socket通訊-Netty框架實現Java通訊(字串資訊的傳輸)
Netty簡介
Netty是由JBOSS提供的一個java開源框架。Netty提供非同步的、事件驅動的網路應用程式框架和工具,用以快速開發高效能、高可靠性的網路伺服器和客戶端程式。 也就是說,Netty 是一個基於NIO的客戶、伺服器端程式設計框架,使用Netty 可以確保你快速和簡單的開發出一個網路應用,例如實現了某種協議的客戶,服務端應用。Netty相當簡化和流線化了網路應用的程式設計開發過程,例如,TCP和UDP的socket服務開發。 “快速”和“簡單”並不用產生維護性或效能上的問題。Netty 是一個吸收了多種協議的實現經驗,這些協議包括FTP,SMTP,HTTP,各種二進位制,文字協議,並經過相當精心設計的專案,最終,Netty 成功的找到了一種方式,在保證易於開發的同時還保證了其應用的效能,穩定性和伸縮性。
本文的目的
使用Netty實現一個Socket通訊,包括客戶端和服務端,通過服務端進行監聽,客戶端傳送資訊,服務端可進行接收,並進行返回資料,完成一個完整的通訊。
工程結構
POM檔案配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.taowd.socket</groupId>
<artifactId>SocketDemo2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency >
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>
</dependencies>
</project>
服務端程式碼
EchoServer.java
package Server;
import java.nio.charset.Charset;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.codec.string.StringEncoder;
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public void start() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap sb = new ServerBootstrap();
sb.option(ChannelOption.SO_BACKLOG, 1024);
sb.group(group, bossGroup) // 繫結執行緒池
.channel(NioServerSocketChannel.class) // 指定使用的channel
.localAddress(this.port)// 繫結監聽埠
.childHandler(new ChannelInitializer<SocketChannel>() { // 繫結客戶端連線時候觸發操作
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println("報告");
System.out.println("資訊:有一客戶端連結到本服務端");
System.out.println("IP:" + ch.localAddress().getHostName());
System.out.println("Port:" + ch.localAddress().getPort());
System.out.println("報告完畢");
ch.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));
ch.pipeline().addLast(new EchoServerHandler()); // 客戶端觸發操作
ch.pipeline().addLast(new ByteArrayEncoder());
}
});
ChannelFuture cf = sb.bind().sync(); // 伺服器非同步建立繫結
System.out.println(EchoServer.class + " 啟動正在監聽: " + cf.channel().localAddress());
cf.channel().closeFuture().sync(); // 關閉伺服器通道
} finally {
group.shutdownGracefully().sync(); // 釋放執行緒池資源
bossGroup.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws Exception {
new EchoServer(8888).start(); // 啟動
}
}
EchoServerHandler.java
package Server;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
/*
* channelAction
*
* channel 通道 action 活躍的
*
* 當客戶端主動連結服務端的連結後,這個通道就是活躍的了。也就是客戶端與服務端建立了通訊通道並且可以傳輸資料
*
*/
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println(ctx.channel().localAddress().toString() + " 通道已啟用!");
}
/*
* channelInactive
*
* channel 通道 Inactive 不活躍的
*
* 當客戶端主動斷開服務端的連結後,這個通道就是不活躍的。也就是說客戶端與服務端的關閉了通訊通道並且不可以傳輸資料
*
*/
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println(ctx.channel().localAddress().toString() + " 通道不活躍!");
// 關閉流
}
/**
*
* @author Taowd
* TODO 此處用來處理收到的資料中含有中文的時 出現亂碼的問題
* 2017年8月31日 下午7:57:28
* @param buf
* @return
*/
private String getMessage(ByteBuf buf) {
byte[] con = new byte[buf.readableBytes()];
buf.readBytes(con);
try {
return new String(con, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
/**
* 功能:讀取伺服器傳送過來的資訊
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 第一種:接收字串時的處理
ByteBuf buf = (ByteBuf) msg;
String rev = getMessage(buf);
System.out.println("客戶端收到伺服器資料:" + rev);
}
/**
* 功能:讀取完畢客戶端傳送過來的資料之後的操作
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("服務端接收資料完畢..");
// 第一種方法:寫一個空的buf,並重新整理寫出區域。完成後關閉sock channel連線。
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
// ctx.flush();
// ctx.flush(); //
// 第二種方法:在client端關閉channel連線,這樣的話,會觸發兩次channelReadComplete方法。
// ctx.flush().close().sync(); // 第三種:改成這種寫法也可以,但是這中寫法,沒有第一種方法的好。
}
/**
* 功能:服務端發生異常的操作
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
System.out.println("異常資訊:\r\n" + cause.getMessage());
}
}
客戶端程式碼
EchoClient.java
package Cilent;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
public class EchoClient {
private final String host;
private final int port;
public EchoClient() {
this(0);
}
public EchoClient(int port) {
this("localhost", port);
}
public EchoClient(String host, int port) {
this.host = host;
this.port = port;
}
public void start() throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group) // 註冊執行緒池
.channel(NioSocketChannel.class) // 使用NioSocketChannel來作為連線用的channel類
.remoteAddress(new InetSocketAddress(this.host, this.port)) // 繫結連線埠和host資訊
.handler(new ChannelInitializer<SocketChannel>() { // 繫結連線初始化器
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println("正在連線中...");
ch.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));
ch.pipeline().addLast(new EchoClientHandler());
ch.pipeline().addLast(new ByteArrayEncoder());
ch.pipeline().addLast(new ChunkedWriteHandler());
}
});
// System.out.println("服務端連線成功..");
ChannelFuture cf = b.connect().sync(); // 非同步連線伺服器
System.out.println("服務端連線成功..."); // 連線完成
cf.channel().closeFuture().sync(); // 非同步等待關閉連線channel
System.out.println("連線已關閉.."); // 關閉完成
} finally {
group.shutdownGracefully().sync(); // 釋放執行緒池資源
}
}
public static void main(String[] args) throws Exception {
new EchoClient("127.0.0.1", 8888).start(); // 連線127.0.0.1/65535,並啟動
}
}
EchoClientHandler.java
package Cilent;
import java.nio.charset.Charset;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
/**
* 向服務端傳送資料
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客戶端與服務端通道-開啟:" + ctx.channel().localAddress() + "channelActive");
String sendInfo = "Hello 這裡是客戶端 你好啊!";
System.out.println("客戶端準備傳送的資料包:" + sendInfo);
ctx.writeAndFlush(Unpooled.copiedBuffer(sendInfo, CharsetUtil.UTF_8)); // 必須有flush
}
/**
* channelInactive
*
* channel 通道 Inactive 不活躍的
*
* 當客戶端主動斷開服務端的連結後,這個通道就是不活躍的。也就是說客戶端與服務端的關閉了通訊通道並且不可以傳輸資料
*
*/
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客戶端與服務端通道-關閉:" + ctx.channel().localAddress() + "channelInactive");
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
System.out.println("讀取客戶端通道資訊..");
ByteBuf buf = msg.readBytes(msg.readableBytes());
System.out.println(
"客戶端接收到的服務端資訊:" + ByteBufUtil.hexDump(buf) + "; 資料包為:" + buf.toString(Charset.forName("utf-8")));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
System.out.println("異常退出:" + cause.getMessage());
}
}
執行結果圖
相關推薦
Socket通訊-Netty框架實現Java通訊(字串資訊的傳輸)
Netty簡介 Netty是由JBOSS提供的一個java開源框架。Netty提供非同步的、事件驅動的網路應用程式框架和工具,用以快速開發高效能、高可靠性的網路伺服器和客戶端程式。 也就是說,Netty 是一個基於NIO的客戶、伺服器端程式設計框架,使用Ne
AndroidAsync框架實現區域網通訊
package com.actiview.asynclib; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.
基於netty框架實現的TCP服務端程式
工程目錄結構 程式碼:NioServer main類 import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.Channel
分布式架構的基石,簡單的 RPC 框架實現(JAVA)
測試 請求 消費 進制 runt trace 發布 @override etc RPC架構 RPC 的全稱是 Remote Procedure Call,它是一種進程間通信方式。允許像調用本地服務一樣調用遠程服務。 1.RPC 框架原理 RPC
Linux 程序間通訊——訊息佇列實現雙向通訊
函式: key_t ftok(const char *filename, int proj_id); 通過檔名和專案號獲得System V IPC鍵值(用於建立訊息佇列、共享記憶體所用) proj_id:專案號,不為0即可 返回:成功則返回鍵值,失敗則返回-1 函式: in
web Socket與netty框架支援高併發
ONE、分析HTTP與WEB SOCKET的優缺點: 一、HTTP協議的弊端 將HTTP協議的主要弊端總結如下: (1)半雙工協議:可以在客戶端和服務端2個方向上傳輸,但是不能同時傳輸。同一時刻,只能在一個方向上傳輸。 (2) HTTP訊息冗長
使用Python的Flask框架實現視訊的流媒體傳輸
Flask 是一個 Python 實現的 Web 開發微框架。這篇文章是一個講述如何用它實現傳送視訊資料流的詳細教程。我敢肯定,現在你已經知道我在O'Reilly Media上釋出了有關Flask的一本書和一些視訊資料。在這些上面,Flask框架介紹的覆蓋面是相當完整的,出於某種原因,也有一小部分的功能沒有太
【HttpClient學習與實戰】1.使用httpClient實現get與post資訊傳輸
一般網路會給我們提供許多資料介面,我們的一些資訊並不是我們本系統提供而是第三方給我們提供的,他們通常會給我們一個提供資料來源的介面,訪問這個介面可以獲取相應的資料用於我們自己的應用中(WebService和現如今的json/xml通過http資訊的傳輸模式都是如此)。 ht
Netty框架的簡單使用,實現socket通訊
個人部落格:haichenyi.com。感謝關注 題外話,很多人都把JDK1.4提供的NIO稱之為非同步非阻塞I/O;其實,並不然,從嚴格意義上面講,它只能稱為非阻塞I/O。在JDK1.7提供的NIO 2.0,新增了非同步的套接字通道Channel,它才是
Java學習筆記之--------網路程式設計之Socket通訊----聊天室實現
Socket通訊 網路上的兩個程式通過一個雙向的通訊連線實現資料的交換,這個連線的一端稱為一個socket。基於TCP/IP協議,建立穩定的點對點的通訊。 特點:實時、快速、安全性高、佔用系統資源多、效率低。 通常也稱作"套接字",套接字是一種程序間的資料交換機制。這些程序既可以在同一機
Java 實現socket 與伺服器實現實時通訊
現在有一個需求,就是要去給一臺客戶端主動去傳送指令,或者推送訊息,就尋求朋友問了問告訴我說socket可以實現,所以就在網上找了些資料一遍學習,一遍測試,現在把我最後的成果記錄下來。 如果對於socket有概念上的不理解的話,可以去百度一下會有很
JAVA通訊(2)--實現簡單的RPC框架
一、RPC簡介 RPC,全稱為Remote Procedure Call,即遠端過程呼叫,它是一個計算機通訊協議。它允許像呼叫本地服務一樣呼叫遠端服務。它可以有不同的實現方式。如RMI(遠端方法呼叫)、Hessian、Http invoker等。另外,RPC是
JAVA通訊(1)-- 使用Socket實現檔案上傳與下載
客戶端 /** * 檔案上傳客戶端 * * @author chen.lin * */ public class UploadClient extends JFrame { /** * */ priva
java socket和netty通訊
一、Socket簡單通訊1、先啟動server端import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; /**
java SSM框架 websocket即時通訊 代碼生成器 shiro redis 後臺框架源碼
pdh 音頻 orf 元素 數據庫連接池 extra 數據庫連接 宋體 jpg 1. 權限管理:點開二級菜單進入三級菜單顯示 角色(基礎權限)和按鈕權限 角色(基礎權限): 分角色組和角色,獨立分配菜單權限和增刪改查權限。 按鈕權限: 給角色分配按鈕
Socket.IO介紹:支持WebSocket、用於WEB端的即時通訊的框架
網絡 進行 最新版本 ajax 並且 移動 接口 事件 ODB 一、基本介紹 WebSocket是HTML5的一種新通信協議,它實現了瀏覽器與服務器之間的雙向通訊。而Socket.IO是一個完全由JavaScript實現、基於Node.js、支持WebSocket的協議
java 實現udp通訊
ket 地址 upd void ESS util dst 服務端 unknown 需求:應用A(通常有多個)和應用B(1個)進行 socket通訊,應用A必須知道應用B的ip地址(在應用A的配置文件中寫死的),這個時候就必須把應用B的ip設成固定ip(但是某些時候如更換路由
網路程式設計(InetAddress類、Socket和ServerSocket、實現客戶端和伺服器之間的雙向通訊)
網路程式設計的底層是IO,通過IO將一臺計算機中的資料傳送到另一臺計算機中。傳送的時候,要知道接受方的地址,該地址即為IP地址。知道IP地址後即可進行傳送。A向B發訊息,訊息是發過去了,但是B要怎樣接受呢?因此定義了埠,B監聽了A所使用的埠。A發的訊息中含有埠號,當B接受到訊息時,知道了埠號
實現socket的服務和客戶端通訊
對學習過程中自己敲的一些關於socket有關的程式碼做了個簡單總結,在這分享一下,給有需要的同學借鑑一下。 什麼是socket? 網路上的兩個程式通過一個雙向的通訊連線實現資料的交換,這個連線的一端稱為一個socket。 建立網路通訊連線至少要一對埠號(socket)。socke
Java以GET和POST方式實現HTTP通訊
此程式可以建立HTTP通訊,分別以GET和POST方式向WEB伺服器提交資訊,並接收WEB伺服器返回的響應。 import java.io.*; import java.net.*; public class s311 { public static void main(S