在客户端和服务器中,客户端接收到音讯随后澳门正规网上娱乐

通过3个实例来评释Netty的施用。用一个服务器连接5个客户端线程,客户端连接上服务器以往就向服务器发送消息,服务器收到到消息后向客户端再次回到新闻,客户端接收到信息之后,等待随机的时间,再向服务端发送新闻,那样直接循环下去。

 基于TCP协议的Socket编制程序和通讯

类型布局:

在网络通信中,第一次主动发起通信的先后被称作客户端(Client)程序,简称客户端,而在第3遍通信中等待连接的次序被称作服务器端(Server)程序,简称服务器。1旦通信建构,则客户端和服务器端完全平等,未有本质的分别。 

澳门正规网上娱乐 1

“请求-响应”模式

NettyServer.java:

 Socket类:发送TCP消息

package Server;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;  
import org.jboss.netty.channel.*;  
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;  
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;

import Util.Constant;


public class NettyServer {

    public static String host = "127.0.0.1";

    // 创建1个线程池
    static ExecutionHandler executionHandler = new ExecutionHandler(new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576));

    public static void main(String[] args) {
        // ChannelFactory
        final ChannelFactory channelFactory = new NioServerSocketChannelFactory(  
                // Boss线程池,处理Socket请求
                Executors.newCachedThreadPool(),  
                // Worker线程池,由于使用的是NIO,1个Worker线程可以管理多个Channel
                Executors.newCachedThreadPool()); 
        // ServerBootstrap
        ServerBootstrap bootstrap = new ServerBootstrap(channelFactory);

        ServerPipelineFactory serverPipelineFactory = new ServerPipelineFactory(executionHandler);
        bootstrap.setPipelineFactory(serverPipelineFactory); 

        // 禁用nagle算法
        bootstrap.setOption("child.tcpNoDelay", true);  
        // 启用TCP保活检测
        bootstrap.setOption("child.keepAlive", true); 

        // 监听5个端口
        bootstrap.bind(new InetSocketAddress(Constant.p1));
        System.out.println("Listening port " + Constant.p1 + "...");
        bootstrap.bind(new InetSocketAddress(Constant.p2));
        System.out.println("Listening port " + Constant.p2 + "...");
        bootstrap.bind(new InetSocketAddress(Constant.p3));
        System.out.println("Listening port " + Constant.p3 + "...");
        bootstrap.bind(new InetSocketAddress(Constant.p4));
        System.out.println("Listening port " + Constant.p4 + "...");
        bootstrap.bind(new InetSocketAddress(Constant.p5));
        System.out.println("Listening port " + Constant.p5 + "...");
    }

}

  ServerSocket类:创立服务器

ServerPipelineFactory.java:

套接字是1种进度间的数据交流机制。这个进程既能够在同一机器上,也可以在通过互联网连接的分裂机器上。换句话说,套接字起到通信端点的效率。单个套接字是二个端点,而一对套接字则构成1个双向通信信道,使非关系进度能够在地面或通过网络开展数据沟通。一旦确立套接字连接,数据就能够在萧规曹随或分裂的系统中双向或单向发送,直到当中三个端点关闭连接。套接字与主机地址和端口地址相关联。

package Server;

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.execution.ExecutionHandler;

public class ServerPipelineFactory implements ChannelPipelineFactory {

    private final ExecutionHandler executionHandler; 

    public ServerPipelineFactory(ExecutionHandler executionHandler){
        this.executionHandler = executionHandler;
    }

    @Override
    public ChannelPipeline getPipeline() throws Exception {
        // TODO Auto-generated method stub
        return Channels.pipeline( 
                new StringEncoder(),    
                new StringDecoder(), 
                // 多个pipeline之间必须共享同一个ExecutionHandler,放在业务逻辑handler之前
                executionHandler,
                // 业务逻辑handler
                new MyServerHandler());
    } 

}

主机地址即是客户端或服务器程序所在的主机的IP地址。端口地址是指客户端或服务器程序使用的主机的通信端口。在客户端和服务器中,分别创设独立的Socket,并经过Socket的性格,将七个Socket进行连接,那样,客户端和服务器通过套接字所确立连接使用输入输出流实行通讯。

MyServerHandler.java:

TCP/IP套接字是最有限帮忙的双向流协议,使用TCP/IP能够发送任性数量的数据。实际上,套接字只是Computer桃月编号的端口。假设发送方和接收方计算机鲜明好端口,他们就可以通讯了。

package Server;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import Util.Tool;

public class MyServerHandler extends SimpleChannelHandler{

    @SuppressWarnings("static-access")
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        System.out.println("Server received:" + e.getMessage());
        // 休息随机秒后发送消息
        Thread th = Thread.currentThread();
        int interval = Tool.getInterval(100);
        th.sleep(interval*1000);
        e.getChannel().write("from Server: Hello!");
        super.messageReceived(ctx, e);
    }

    @Override  
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {  
        e.getCause().printStackTrace();  
        Channel ch = e.getChannel();  
        ch.close(); 
        super.exceptionCaught(ctx, e);
    } 

    @Override  
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("A client connected!");
        super.channelConnected(ctx, e); 
    }

}

TCP/IP通讯连接的粗略进度:

NettyClient.java:

坐落AComputer上的TCP/IP软件向B计算机发送包罗端口号的新闻,BComputer的TCP/IP软件接收该新闻,并开始展览检查,查看是还是不是有她领会的程序正在该端口上接收消息。若是有,他就将该音讯交给这么些程序。

package Client;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;  
import org.jboss.netty.channel.*;  
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;  
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;

import Util.Constant;

public class NettyClient extends Thread{

    public static String host = "127.0.0.1";
    ClientBootstrap bootstrap;
    int port;

    // 创建1个线程池
    static ExecutionHandler executionHandler = new ExecutionHandler(new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576));

    public NettyClient(int port) {
        this.port = port;
        // ChannelFactory
        final ChannelFactory channelFactory = new NioClientSocketChannelFactory(  
                // Boss线程池
                Executors.newCachedThreadPool(),  
                // Worker线程池
                Executors.newCachedThreadPool());  
        // ServerBootstrap
        bootstrap = new ClientBootstrap(channelFactory);

        ClientPipelineFactory clientPipelineFactory = new ClientPipelineFactory(executionHandler);
        bootstrap.setPipelineFactory(clientPipelineFactory);
        bootstrap.setOption("tcpNoDelay" ,true);  
        bootstrap.setOption("keepAlive", true);  
        bootstrap.connect(new InetSocketAddress(port));

    }

    public void run(){
        ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
        // 开始试图连接
        System.out.println("Connecting to port " + port + "...");
        // 等待直到连接关闭或失败
        future.getChannel().getCloseFuture().awaitUninterruptibly(); 
        // 关闭线程池准备退出
        bootstrap.releaseExternalResources();
    }

    public static void main(String[] args) {
        NettyClient nc1 = new NettyClient(Constant.p1);
        NettyClient nc2 = new NettyClient(Constant.p2);
        NettyClient nc3 = new NettyClient(Constant.p3);
        NettyClient nc4 = new NettyClient(Constant.p4);
        NettyClient nc5 = new NettyClient(Constant.p5);

        nc1.start();
        nc2.start();
        nc3.start();
        nc4.start();
        nc5.start();
    }

}

要使程序使得地运转,就非得有1个客户端和一个服务器。

ClientPipelineFactory.java:

经过Socket的编制程序顺序:

package Client;

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.execution.ExecutionHandler;

public class ClientPipelineFactory implements ChannelPipelineFactory {

    private final ExecutionHandler executionHandler; 

    public ClientPipelineFactory(ExecutionHandler executionHandler){
        this.executionHandler = executionHandler;
    }

    @Override
    public ChannelPipeline getPipeline() throws Exception {
        // TODO Auto-generated method stub
        return Channels.pipeline( 
                new StringEncoder(),    
                new StringDecoder(), 
                // 多个pipeline之间必须共享同一个ExecutionHandler,放在业务逻辑handler之前
                executionHandler,
                // 业务逻辑handler
                new MyClientHandler());
    } 
}

1.创办服务器ServerSocket,在创设时,定义ServerSocket的监听端口(在那些端口接收客户端发来的音讯!)

MyClientHandler.java:

二.ServerSocket调用accept()方法,使之远在阻塞状态

package Client;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

import Util.Tool;

public class MyClientHandler extends SimpleChannelHandler{


    // 连接到服务端时,发出消息
    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { 
        System.out.println("Connected to Server!");
        e.getChannel().write("from Client: Hello! " + System.currentTimeMillis()); 
        super.channelConnected(ctx, e);
    }  

    @SuppressWarnings("static-access")
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        System.out.println("Client Received:" + e.getMessage());
        // 休息随机秒后发送消息
        Thread th = Thread.currentThread();
        int interval = Tool.getInterval(5);
        th.sleep(interval*1000);
        e.getChannel().write("from Client: Hello! "  + System.currentTimeMillis());
        super.messageReceived(ctx, e);
    }  

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {  
        e.getCause().printStackTrace();  
        Channel ch = e.getChannel();  
        ch.close(); 
        super.exceptionCaught(ctx, e);
    } 

}

三.开立客户机Socket,并安装服务器的IP及端口

Constant.java:

四.客户机发出连接请求,创立连接。

package Util;

public class Constant {
    final static int start = 10000;
    public static int p1 = start + 1;
    public static int p2 = start + 2;
    public static int p3 = start + 3;
    public static int p4 = start + 4;
    public static int p5 = start + 5;
}

五.分头收获服务器和客户端Socket的InputStream和OutputStream

Tool.java:

陆.采取Socket和ServerSocket实行多少传输。 

package Util;

import java.util.Random;

public class Tool {

    static Random rand = new Random();

    public static int getInterval(int max){
        return rand.nextInt(max);
    }
}

【示例壹】单向通讯服务器端代码

 

import java.io.BufferedWriter;

import java.io.IOException;

import java.io.OutputStreamWriter;

import java.net.ServerSocket;

import java.net.Socket;

/**

 * 最简易的劳务器端代码

 * @author Administrator

 *

 */

public class BasicSocketServer {

    public static void main(String[] args) {

       try {

           //创立服务器端套接字

           ServerSocket serverSocket = new   ServerSocket(888捌); 
//TCP端口1共多少个??

           //监听,等待客户端请求,并愿意接受一连。

           System.out.println(“服务端创建监听”);

           Socket socket = serverSocket.accept();

           //通过流向客户端发送数据

//         ObjectOutputStream oos = new  
ObjectOutputStream(socket.getOutputStream());

//         oos.writeObject(“aaaaa”);

//         oos.close();

           BufferedWriter bw   = new BufferedWriter(new  
OutputStreamWriter(socket.getOutputStream()));

           bw.write(“hhhh”);

           bw.close();

           socket.close();

       } catch (IOException e) {

           // TODO Auto-generated catch block

           e.printStackTrace();

       }

    }

【示例2】单向通讯Socket客户端代码

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.net.InetAddress;

import java.net.Socket;

/**

 * 最简易的Socket客户端

 * @author Administrator

 *

 */

public class BasicSocketClient {

    public static void main(String[] args) {

       try {

   
       //内定的是所要连接的服务器的IP和端口。而不是友善机器的端口。发送端口是自由的。

           Socket socket
new Socket(InetAddress.getLocalHost(),8888);

//         ObjectInputStream ois = new  
ObjectInputStream(socket.getInputStream());

//         String string = (String) ois.readObject();

//         System.out.println(string);

           BufferedReader br   = new BufferedReader(new  
InputStreamReader(socket.getInputStream()));

           System.out.println(br.readLine());

           br.close();

           socket.close();

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

}

本节咱们明白了Socket的单项通信,那么怎么着兑现Socket的双向交流?下节大家根本教学下~


「全栈Java笔记」是1部能帮大家从零到1/10人为全栈Java程序员种类笔记。小编江洛杉矶湖人队称
Mr.
G,10年Java研究开发经验,曾在神州数码、航天院某所研究开发主旨从事软件设计及研究开发职业,从小白逐步做到技术员、高工、架构师。明白Java平台软件开荒,精晓JAVAEE,熟练各个流行开辟框架。

 笔记包蕴从浅入深的陆大片段:

 A-Java入门阶段

 B-数据库从入门到通晓

 C-手刃移动前端和Web前端

 D-J二EE从明白到实战

 E-Java高等框架精解

 F-Linux和Hadoop