一个简单的NIO Socket通信程序

一个简单的通信小程序

学习看书时,手写试试

服务器端

package ecnu.sgy.SocketChannleTest.serverChannel;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/*** * * 简单的测试程序,仅作学习使用 * */
public class ServerChannel {



    public static void main(String[] args) throws IOException {
         // 服务器端端口
        int port = 8000;

        //定义一个缓冲器
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        // 打开服务器端通道
        ServerSocketChannel serverSockerChannel = ServerSocketChannel.open();

        //配置该通道为非阻塞
        serverSockerChannel.configureBlocking(false);

        //打开一个服务器端socket
        ServerSocket serverSocket = serverSockerChannel.socket();

        //绑定端口 
        serverSocket.bind(new InetSocketAddress(port));


        //打开一个selector
        Selector selector = Selector.open();

        //将通道注册到该selector中
        serverSockerChannel.register(selector, SelectionKey.OP_ACCEPT);

        //循环监听通道事件
        while(true){
            //就绪的channle
            int number = selector.select();
            //如果没有就绪的通道则继续循环
            if(number == 0)
                continue;

            //如果有就绪的事件,则会放在一个Set集合中
            Set selectkeys = selector.selectedKeys();
            Iterator it = selectkeys.iterator();

            //访问该集合
            while(it.hasNext()){
                //获取一个通道的key
                SelectionKey key = (SelectionKey) it.next();

                //如果发生的是连接请求
                if((key.readyOps()&SelectionKey.OP_ACCEPT)==SelectionKey.OP_ACCEPT){

                    //获得当前通道
                    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();

                    //打开这个连接socket,接受新的请求
                    SocketChannel sc = ssc.accept();

                    //将该新的请求通道设置为非阻塞
                    sc.configureBlocking(false);

                    //将该新的通道注册到selector中
                    sc.register(selector, SelectionKey.OP_READ);

                    //移除该已经处理过的key
                    it.remove();

                }else if((key.readyOps()&SelectionKey.OP_READ)==SelectionKey.OP_READ){
                    //从客户端读取数据

                    int byteLength = 0;
                    StringBuilder content = new StringBuilder() ;
                    SocketChannel sc = (SocketChannel)key.channel();
                    //byteBuffer.clear();
                    while(true){
                        byteBuffer.clear();
                        byteLength = sc.read(byteBuffer);
                        System.out.println(byteLength);
                        if(byteLength<=0)
                            break;
                        //表示可以从buffer中读取数据了
                        byteBuffer.flip();
                        content.append(Charset.forName("utf-8").decode(byteBuffer).toString());
                        //清空buffer,为下次读写准备
                        byteBuffer.clear();
                    }
                    System.out.println( "服务器接收信息成功。");
                    System.out.println("read from client : "+content);

                    //不加上这一句,会报异常:远程主机强迫关闭了一个现有的连接
                    sc.close();
                    //移除已经处理完的事件
                    it.remove();
                }

            }           

        }

    }
}

简单的客户端代码

package ecnu.sgy.SocketChannleTest.clientChannle;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

public class ClientChannel {

    static int hostport ;
    static String hostname ;
    public ClientChannel(String hostname,int hostport) {

        this.hostport = hostport;
        this.hostname = hostname;
    }
    public static void main(String[] args) throws IOException{

        new ClientChannel("192.168.0.63",8000);

        //打开监听信道并设置为非阻塞模式 
        SocketChannel clientChannel = SocketChannel.open(new InetSocketAddress(hostname, hostport));
        System.out.println( "连接服务器成功。");
        clientChannel.configureBlocking(false);

        //注册通道选择器
        Selector selector = Selector.open();
        clientChannel.register(selector, SelectionKey.OP_READ);


//      ByteBuffer buffer = ByteBuffer.allocate(1024);
        String mes = "i am client腹股沟灌灌灌灌灌灌灌灌灌灌灌灌灌灌灌灌打发十分广泛的地方灌灌灌灌灌灌灌灌灌灌阿三顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶啊风格灌灌灌灌灌灌灌灌灌灌灌灌灌灌灌灌"
                + "大呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃啵啵啵啵啵啵啵啵啵啵啵啵啵啵啵啵啵啵不发稿费高飞高飞高飞高飞高飞高飞高飞高飞为呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃"
                + "安第斯山杀杀杀杀杀杀杀杀杀杀杀杀杀杀杀为呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃"
                + "噶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶"
                + "aggggggggggggggggggzbccccccccccccccccc下啵啵啵啵啵啵啵啵啵啵啵啵啵啵啵啵啵啵"
                + "找到方法烦烦烦烦烦烦烦烦烦烦烦烦烦烦烦"
                + "发表公开数据放到公司发的表格计算的发表你不舒服的你不是你见过你不仅能恢复比较斯蒂法诺不过副本贾南风关键部分公司内部收费的你不就是把你交给你发给您拜个年是否对您表示今年不妨告诉你"
                + "不能思考能看见你空间告诉你不能随便弄热水不过凡事不能弄舒服呢拜佛大逆不道宋丰年舍不得把你送id放假呗哦日尽管当时那个不山东妇女松岛枫宁波是否对您表示貂绒保暖msdn不是的宁波分公司的哪本书那本"
                + "你不是看能不送吧so;泵送非;保送复旦;哪波士顿覅宁波虽然那部分悲伤是不死哦你vesorgvjdfsonbksbnfskjbsndfnfbsdbseoinbdfsjkbnsjkfdbnserbnfdskjn"
                + "不是你地方酷酷酷酷酷酷酷酷酷酷酷酷酷酷"
                + "你不是的佛教不能送injusfddkfkdnsjdkfnnnnnnnnnnnnnnnnnnnnnnnnnn";
        ByteBuffer buffer = ByteBuffer.wrap(mes.getBytes("utf-8"));

        clientChannel.write(buffer);
        System.out.println( "向服务器发送信息成功。");

        //clientChannel.close();
    }
}

如果在浏览器中输入:“http://localhost:8000”,会返回http请求信息
一个简单的NIO Socket通信程序_第1张图片

你可能感兴趣的:(一个简单的NIO Socket通信程序)