`
dwj147258
  • 浏览: 195562 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Netty实现SSL双向验证完整实例

阅读更多

 一、证书准备

     要使用ssl双向验证,就必须先要生成服务端和客户端的证书,并相互添加信任,具体流程如下(本人调试这个用例的时候,花了很多时间来验证证书是否正确,以及握手失败的原因,这里证书生成过程只要按流程走,本人能保证绝对没有问题)

现在打开cmd,在哪个目录下打开,证书就会放在哪个目录下:

第一步:   生成Netty服务端私钥和证书仓库命令

 keytool -genkey -alias securechat -keysize 2048 -validity 365 -keyalg RSA -dname "CN=localhost" -keypass sNetty -storepass sNetty -keystore sChat.jks

 

  • -keysize 2048 密钥长度2048位(这个长度的密钥目前可认为无法被暴力破解)
  • -validity 365 证书有效期365天
  • -keyalg RSA 使用RSA非对称加密算法
  • -dname "CN=localhost" 设置Common Name为localhost
  • -keypass sNetty密钥的访问密码为sNetty
  • -storepass sNetty密钥库的访问密码为sNetty(其实这两个密码也可以设置一样,通常都设置一样,方便记)
  • -keystore sChat.jks 指定生成的密钥库文件为sChata.jks

第二步:生成Netty服务端自签名证书

             keytool -export -alias securechat -keystore sChat.jks -storepass sNetty -file sChat.cer

 第三步:生成客户端的密钥对和证书仓库,用于将服务端的证书保存到客户端的授信证书仓库中

    keytool -genkey -alias smcc -keysize 2048 -validity 365  -keyalg RSA -dname "CN=localhost" -keypass sNetty  -storepass sNetty -keystore cChat.jks

第四步:将Netty服务端证书导入到客户端的证书仓库中

keytool -import -trustcacerts -alias securechat -file sChat.cer -storepass sNetty -keystore cChat.jks

如果你只做单向认证,则到此就可以结束了,如果是双响认证,则还需继续往下走

第五步:生成客户端自签名证书

  keytool -export -alias smcc -keystore cChat.jks -storepass sNetty -file cChat.cer

最后一步:将客户端的自签名证书导入到服务端的信任证书仓库中:

   keytool -import -trustcacerts -alias smcc -file cChat.cer -storepass sNetty -keystore sChat.jks

            

到这里,证书就生成完毕了,我们就可以得到两个jks文件,一个是服务端的sChat.jks  ,一个是客户端的cChat.jks   ,这两个文件后面初始化sslCOntext的时候会用到

如果还想了解更多可以查看

http://dwj147258.iteye.com/blog/2339934

 

二、netty服务端

       下面就直接贴代码了,首先是实例化SSLContext的类:

 

package main.java.com.nionetty;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.springframework.core.io.ClassPathResource;
/**
 * 初始化sslcontext类
 *
 */
public class ContextSSLFactory {
	
	private static final SSLContext SSL_CONTEXT_S ;
	
	private static final SSLContext SSL_CONTEXT_C ;
	
	static{
		SSLContext sslContext = null ;
		SSLContext sslContext2 = null ;
		try {
			sslContext = SSLContext.getInstance("SSLv3") ;
			sslContext2 = SSLContext.getInstance("SSLv3") ;
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		}
		try{
			if(getKeyManagersServer() != null && getTrustManagersServer() != null ){
				sslContext.init(getKeyManagersServer(), getTrustManagersServer(), null);
			}
			if(getKeyManagersClient() != null && getTrustManagersClient() != null){
				sslContext2.init(getKeyManagersClient(), getTrustManagersClient(), null);
			}
			
		}catch(Exception e){
			e.printStackTrace() ;
		}
		sslContext.createSSLEngine().getSupportedCipherSuites() ;
		sslContext2.createSSLEngine().getSupportedCipherSuites() ;
		SSL_CONTEXT_S = sslContext ; 
		SSL_CONTEXT_C = sslContext2 ;
	}
	public ContextSSLFactory(){
		
	}
	public static SSLContext getSslContext(){
		return SSL_CONTEXT_S ;
	}
	public static SSLContext getSslContext2(){
		return SSL_CONTEXT_C ;
	}
	private static TrustManager[] getTrustManagersServer(){
		FileInputStream is = null ;
		KeyStore ks = null ;
		TrustManagerFactory keyFac = null ;
		
		TrustManager[] kms = null ;
		try {
			 // 获得KeyManagerFactory对象. 初始化位默认算法
			keyFac = TrustManagerFactory.getInstance("SunX509") ;
			is =new FileInputStream( (new ClassPathResource("main/java/conf/sChat.jks")).getFile() );
			ks = KeyStore.getInstance("JKS") ;
			String keyStorePass = "sNetty" ;
			ks.load(is , keyStorePass.toCharArray()) ;
			keyFac.init(ks) ;
			kms = keyFac.getTrustManagers() ;
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			if(is != null ){
				try {
					is.close() ;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return kms ;
	}
	private static TrustManager[] getTrustManagersClient(){
		FileInputStream is = null ;
		KeyStore ks = null ;
		TrustManagerFactory keyFac = null ;
		
		TrustManager[] kms = null ;
		try {
			 // 获得KeyManagerFactory对象. 初始化位默认算法
			keyFac = TrustManagerFactory.getInstance("SunX509") ;
			is =new FileInputStream( (new ClassPathResource("main/java/conf/cChat.jks")).getFile() );
			ks = KeyStore.getInstance("JKS") ;
			String keyStorePass = "sNetty" ;
			ks.load(is , keyStorePass.toCharArray()) ;
			keyFac.init(ks) ;
			kms = keyFac.getTrustManagers() ;
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			if(is != null ){
				try {
					is.close() ;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return kms ;
	}
	private static KeyManager[] getKeyManagersServer(){
		FileInputStream is = null ;
		KeyStore ks = null ;
		KeyManagerFactory keyFac = null ;
		
		KeyManager[] kms = null ;
		try {
			 // 获得KeyManagerFactory对象. 初始化位默认算法
			keyFac = KeyManagerFactory.getInstance("SunX509") ;
			is =new FileInputStream( (new ClassPathResource("main/java/conf/sChat.jks")).getFile() );
			ks = KeyStore.getInstance("JKS") ;
			String keyStorePass = "sNetty" ;
			ks.load(is , keyStorePass.toCharArray()) ;
			keyFac.init(ks, keyStorePass.toCharArray()) ;
			kms = keyFac.getKeyManagers() ;
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			if(is != null ){
				try {
					is.close() ;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return kms ;
	}
	private static KeyManager[] getKeyManagersClient(){
		FileInputStream is = null ;
		KeyStore ks = null ;
		KeyManagerFactory keyFac = null ;
		
		KeyManager[] kms = null ;
		try {
			 // 获得KeyManagerFactory对象. 初始化位默认算法
			keyFac = KeyManagerFactory.getInstance("SunX509") ;
			is =new FileInputStream( (new ClassPathResource("main/java/conf/cChat.jks")).getFile() );
			ks = KeyStore.getInstance("JKS") ;
			String keyStorePass = "sNetty" ;
			ks.load(is , keyStorePass.toCharArray()) ;
			keyFac.init(ks, keyStorePass.toCharArray()) ;
			kms = keyFac.getKeyManagers() ;
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			if(is != null ){
				try {
					is.close() ;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return kms ;
	}
}

 

 

服务端启动类:

 

package main.java.com.nionetty;

import javax.net.ssl.SSLEngine;
import javax.print.attribute.standard.MediaSize.Engineering;

import main.java.com.nettyTest.SecureChatServerHandler;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
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.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;

public class NettySocketServer {
	private static SslHandler sslHandler = null ;
	
	private EventLoopGroup bossGroup = null ;
	
	private EventLoopGroup workerGroup = null ;
	
	public void start(){
		bossGroup = new NioEventLoopGroup() ;
		workerGroup = new NioEventLoopGroup() ;
		try{
			ServerBootstrap serverStrap = new ServerBootstrap() ;
			serverStrap.group(bossGroup , workerGroup)
			.channel(NioServerSocketChannel.class)
			.option(ChannelOption.SO_BACKLOG, 128)
			.option(ChannelOption.SO_KEEPALIVE, true)
			.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000 * 5 * 60)
			.handler(new LoggingHandler(LogLevel.DEBUG))
			.childHandler(new ChannelInitializer<SocketChannel>() {

				@Override
				protected void initChannel(SocketChannel socketChannel) throws Exception {
					ChannelPipeline pie = socketChannel.pipeline() ;
					pie.addLast("decoder" , new MyDecoder()) ;
					pie.addLast("encoder" , new MyEncoder()) ;
					pie.addLast("handler" , new NettySocketSSLHandler()) ;
					SSLEngine engine = ContextSSLFactory.getSslContext().createSSLEngine();
			        engine.setUseClientMode(false);
			        engine.setNeedClientAuth(true);
			        pie.addFirst("ssl", new SslHandler(engine));
				}
				
			});
			serverStrap.bind(161616).sync() ;
			System.out.println("服务已开启");
		}catch(Exception e){
			e.printStackTrace() ;
			bossGroup.shutdownGracefully() ;
			workerGroup.shutdownGracefully() ;
		}
		
	}
		private SslHandler getSslHandler(){
			if(sslHandler == null ){
				SSLEngine sslEngine = ContextSSLFactory.getSslContext().createSSLEngine() ;
				sslEngine.setUseClientMode(false) ;
				//false为单向认证,true为双向认证
				sslEngine.setNeedClientAuth(true) ;
				sslHandler = new SslHandler(sslEngine);
			}
			return sslHandler ;
		}
		public static void main(String[] args) {
			new NettySocketServer().start() ;
		}
		
}

 编码器:

 

 

package main.java.com.nionetty;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

import java.nio.ByteBuffer;

public class MyEncoder extends MessageToByteEncoder<ByteBuffer>{

	@Override
	protected void encode(ChannelHandlerContext ctx, ByteBuffer message,
			ByteBuf out) throws Exception {

        if(message==null){
            return;
        }	
        if(message.hasArray()){
        	byte[] msg =message.array();
        	if(msg == null || msg.length <= 0){
                return;
        	}
        	out.writeBytes(msg) ;
        }
	}
    

   
}

 解码器:

 

 

/*
 * Copyright (C) TD Tech<br>
 * All Rights Reserved.<br>
 * 
 */
package main.java.com.nionetty;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.ByteBuffer;
import java.util.List;

/**
 * Create Date: 2014-11-4 下午02:42:21<br>
 * Create Author: lWX232692<br>
 * Description :
 */
public class MyDecoder extends ByteToMessageDecoder {


	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf buffer,
			List<Object> out) throws Exception {
		//UnpooledUnsafeDirectByteBuf(ridx: 0, widx: 1, cap: 1024)
		if (buffer != null) {
			ByteBuffer msg = null;
			try {
				if(buffer.readableBytes() > 0 ){
					msg = ByteBuffer.allocate(buffer.readableBytes()) ;
					byte[] bb = new byte[buffer.readableBytes()] ;
					buffer.readBytes(bb) ;
					msg.put(bb);
					msg.flip();
				}
			} catch (Exception e) {
				e.printStackTrace();
				msg = null ;
			}
			if (msg != null) {
				out.add(msg);
			}
		}
	}


}

业务实现类:

 

 

package main.java.com.nionetty;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.Arrays;

public class NettySocketSSLHandler extends SimpleChannelInboundHandler<ByteBuffer>{
	 @Override
	    public void channelActive(final ChannelHandlerContext ctx) throws Exception {
	        // Once session is secured, send a greeting and register the channel to the global channel
	        // list so the channel received the messages from others.
	        ctx.pipeline().get(SslHandler.class).handshakeFuture().addListener(
	                new GenericFutureListener<Future<Channel>>() {
	                    @Override
	                    public void operationComplete(Future<Channel> future) throws Exception {
	                    	if(future.isSuccess()){
	                    		System.out.println("握手成功");
	                    		byte[] array = new byte[]{ (byte)7d,  04} ;
	                        	ByteBuffer bu = ByteBuffer.wrap(array) ;
	                        	ctx.channel().writeAndFlush(bu) ;
	                    	}else{
	                    		System.out.println("握手失败");
	                    	}
	                        ctx.writeAndFlush(
	                                "Welcome to " + InetAddress.getLocalHost().getHostName() +
	                                        " secure chat service!\n");
	                        ctx.writeAndFlush(
	                                "Your session is protected by " +
	                                        ctx.pipeline().get(SslHandler.class).engine().getSession().getCipherSuite() +
	                                        " cipher suite.\n");

	                    }
	                });
	    }
    @Override
    public void handlerAdded(ChannelHandlerContext ctx)
        throws Exception {
    	 System.out.println("服务端增加");
    }
    
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx){
    	System.out.println("移除:"+ctx.channel().remoteAddress());
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
       System.out.println("Unexpected exception from downstream.");
        ctx.close();
    }
    @Override
    public void messageReceived(ChannelHandlerContext ctx, ByteBuffer msg) throws Exception {
    	System.out.println("服务端receive msg ");
    	byte[] array = new byte[]{00, 01, 00, 00, 00, 06, 05, 03, (byte)7d, 00, 00, 07} ;
    	ByteBuffer bu = ByteBuffer.wrap(array) ;
    	ctx.channel().writeAndFlush(bu) ;
    }
	
}

 

 

三、客户端

 

     客户端实现类

 

 

package main.java.com.nionetty.client;

import java.net.InetSocketAddress;
import java.net.SocketAddress;

import javax.net.ssl.SSLEngine;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
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.ssl.SslHandler;
import main.java.com.nionetty.ContextSSLFactory;
import main.java.com.nionetty.MyDecoder;
import main.java.com.nionetty.MyEncoder;

public class NettySocketClient {
	
	private EventLoopGroup group ;
	
	private Channel channel = null ; 
	public void connect(String ip , int port){
		group = new NioEventLoopGroup();
		try{
			Bootstrap strap = new Bootstrap();
			strap.group(group)
			.channel(NioSocketChannel.class)
			.option(ChannelOption.TCP_NODELAY, true)
			.option(ChannelOption.SO_KEEPALIVE , true)
			.handler(new ChannelInitializer<SocketChannel>() {
				@Override
				protected void initChannel(SocketChannel socketChannel) throws Exception {
					ChannelPipeline pieple = socketChannel.pipeline() ;
					pieple.addLast("decoder" , new MyClientDecoder()) ;
					pieple.addLast("encoder" , new MyClientEncoder()) ;
					pieple.addLast("handler" , new NettySocketSSLClientHandler()) ;
					 SSLEngine engine = ContextSSLFactory.getSslContext2().createSSLEngine();
				     engine.setUseClientMode(true);
				     pieple.addFirst("ssl", new SslHandler(engine));
				}
			});
		SocketAddress address = new InetSocketAddress(ip, port);
		final ChannelFuture future = strap.connect(address).sync();
		channel = future.awaitUninterruptibly().channel();
		System.out.println("连接成功, channel =" + channel.remoteAddress());
		}catch(Exception e ){
			e.printStackTrace();
			group.shutdownGracefully() ;
		}finally{
			
		}
	}
	private static SslHandler sslHandlerClient = null ;
	public static SslHandler getSslHandler(){
		if(sslHandlerClient == null){
			SSLEngine sslEngine = ContextSSLFactory.getSslContext2().createSSLEngine() ;
			sslEngine.setUseClientMode(true) ;
			sslHandlerClient = new SslHandler(sslEngine);
		}
		return sslHandlerClient ;
	}
	public static void main(String[] args) {
		new NettySocketClient().connect("192.168.10.256", 161616) ;
	}
}

 编码器:

 

 

package main.java.com.nionetty.client;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

import java.nio.ByteBuffer;

public class MyClientEncoder extends MessageToByteEncoder<ByteBuffer>{

	@Override
	protected void encode(ChannelHandlerContext ctx, ByteBuffer message,
			ByteBuf out) throws Exception {

        if(message==null){
            return;
        }	
        if(message .hasArray()){
        	byte[] msg =message.array();
        	if(msg == null || msg.length <= 0){
                return;
        	}
        	out.writeBytes(msg);
        }
	}
    

   
}

 解码器:

 

 

/*
 * Copyright (C) TD Tech<br>
 * All Rights Reserved.<br>
 * 
 */
package main.java.com.nionetty.client;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.ByteBuffer;
import java.util.List;

/**
 * Create Date: 2014-11-4 下午02:42:21<br>
 * Create Author: lWX232692<br>
 * Description :
 */
public class MyClientDecoder extends ByteToMessageDecoder {


	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf buffer,
			List<Object> out) throws Exception {
		//UnpooledUnsafeDirectByteBuf(ridx: 0, widx: 1, cap: 1024)
		if (buffer != null) {
			ByteBuffer msg = null;
			try {
				if(buffer.readableBytes() > 0 ){
					msg = ByteBuffer.allocate(buffer.readableBytes()) ;
					byte[] bb = new byte[buffer.readableBytes()] ;
					buffer.readBytes(bb) ;
					msg.put(bb);
					msg.flip();
				}
			} catch (Exception e) {
				e.printStackTrace();
				msg = null ;
			}
			if (msg != null) {
				out.add(msg);
			}
		}
	}


}

 业务handler:

/*
 * Copyright (C) TD Tech<br>
 * All Rights Reserved.<br>
 * 
 */
package main.java.com.nionetty.client;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.ByteBuffer;
import java.util.List;

/**
 * Create Date: 2014-11-4 下午02:42:21<br>
 * Create Author: lWX232692<br>
 * Description :
 */
public class MyClientDecoder extends ByteToMessageDecoder {


	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf buffer,
			List<Object> out) throws Exception {
		//UnpooledUnsafeDirectByteBuf(ridx: 0, widx: 1, cap: 1024)
		if (buffer != null) {
			ByteBuffer msg = null;
			try {
				if(buffer.readableBytes() > 0 ){
					msg = ByteBuffer.allocate(buffer.readableBytes()) ;
					byte[] bb = new byte[buffer.readableBytes()] ;
					buffer.readBytes(bb) ;
					msg.put(bb);
					msg.flip();
				}
			} catch (Exception e) {
				e.printStackTrace();
				msg = null ;
			}
			if (msg != null) {
				out.add(msg);
			}
		}
	}


}

 测试通过,搞了因为在网上没有找到完整的实例,所以因为一个小问题,找了两天都没有找到原因,希望看到的同学能够有所收获

 

1
0
分享到:
评论
3 楼 q124976 2018-07-31  
您好,您的文章最后一块 业务handler 的代码,好像跟上边的重复了,您能修改一下吗?
2 楼 hongtu1993 2018-04-24  
您好. 可以提供一份源码吗? 万分感谢
1 楼 smart152829 2017-07-01  

很不错的文章,最近看了看了夜行侠老师讲的Netty深入浅出源码剖析,里面用到了长连接高并发,在测试的时候,性能真的比之前的tomcat那些容器好几十倍

相关推荐

    netty的SSL双向认证

    在Netty中实现SSL双向认证,我们需要以下步骤: 1. **生成证书**:首先,为服务器和客户端分别生成数字证书。这通常包括创建私钥和公钥,然后使用证书签名请求(CSR)将公钥提交给受信任的证书颁发机构(CA)进行...

    基于Netty的聊天程序

    你还需要考虑如何实现用户身份验证,以保护聊天系统的安全性。 5. **并发处理**: Netty的事件驱动模型非常适合处理大量并发连接。它利用多线程和非阻塞I/O,避免了传统I/O模型中的线程上下文切换开销。 6. **日志...

    MQTTservice

    描述中提到,这个服务是利用Netty框架来实现的。Netty是一个高性能、异步事件驱动的网络应用框架,适用于开发服务器和客户端。它提供了高效的TCP/IP套接字通信,并且支持WebSocket等协议,但在高并发情况下,...

    Java开发的一个真正意义上的跨服聊天系统源码.zip

    "Java开发的一个真正意义上的跨服聊天系统源码.zip"提供了一个实现这一功能的实例,它不仅包含了源代码,还揭示了设计和实现跨服聊天系统的关键技术。下面,我们将深入探讨这个项目中涉及的主要知识点。 首先,我们...

    java网络编程随书光盘

    8. **网络安全**:包括加密技术如SSL/TLS,以及身份验证、授权等,Java的JSSE(Java Secure Socket Extension)提供相关支持。 9. **网络编程设计模式**:如工厂模式用于创建Socket或ServerSocket,单例模式用于...

    java版在线聊天系统

    4. **实时推送**:为了实现实时性,可以采用WebSocket协议,它提供双向通信,使得服务器能主动向客户端推送消息。Java的WebSocket API在Java EE 7及以上版本中已经内置。 5. **安全性**:SSL/TLS协议用于加密通信,...

    使用spring-websocket包搭建websocket服务

    在生产环境中,务必考虑WebSocket的安全性,例如使用SSL/TLS加密连接,配置Spring Security来控制访问权限,以及使用JWT令牌进行身份验证。 **七、性能优化** 为了提高WebSocket服务的性能,可以考虑使用NIO或Netty...

    安卓APP soket 服务端DEMO

    在安卓应用开发中,Socket通信是一种常见的网络编程方式,它允许设备之间进行双向通信。本DEMO主要展示了如何在Android平台上构建一个简单的Socket服务端,以便实现与其他客户端(如另一台Android设备或任何支持...

    java高级工程师面试总结

    - 基于Netty实现高性能的网络通信。 - 采用SPI(Service Provider Interface)机制扩展功能。 - 通过Zookeeper实现服务发现和管理。 #### 数据结构和算法 - **单向链表的逆序排列**: - 可以通过迭代法或递归...

    JAVA网络通信系统的研究与开发(论文+源代码+开题报告)

    7. **网络安全**:网络通信涉及数据安全问题,如加密传输(SSL/TLS)、身份验证、防止DDoS攻击等。Java提供JSSE(Java Secure Socket Extension)框架来支持安全的网络通信。 8. **异常处理**:在网络通信中,错误...

    pusherClientForAndroid:android的客户端

    Pusher是一个云服务,它提供了一种简单的方式来实现WebSocket接口,使得应用程序能够实现实时的双向通信。 首先,`nettyPusherAndroid`是Pusher客户端的核心组件,它基于Netty框架构建。Netty是一个高性能、异步...

Global site tag (gtag.js) - Google Analytics