java网络编程(6):socket通信

第0章:简介


第1章:阻塞通信实践

(1)服务端(SocketServerTest.java)

package com.mcc.core.test.socket;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * socket服务端
 *
 * @author <a href="mailto:[email protected]">menergy</a>
 *         DateTime: 14-2-15  上午12:08
 */
public class SocketServerTest {
    public static void main(String arg[]){
        try{

            ServerSocket server=null;

            try{

                server=new ServerSocket(4700);//创建一个ServerSocket在端口4700监听客户请求

            }catch(Exception e) {

                System.out.println("can not listen to:"+e);//出错,打印出错信息

            }

            Socket socket=null;

            try{

                socket=server.accept();//使用accept()阻塞等待客户请求,有客户请求到来则产生一个Socket对象,并继续执行

            }catch(Exception e) {

                System.out.println("Error."+e);//出错,打印出错信息

            }

            String line;

            BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));//由Socket对象得到输入流,并构造相应的BufferedReader对象

            PrintWriter os=new PrintWriter(socket.getOutputStream());//由Socket对象得到输出流,并构造PrintWriter对象

            BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));//由系统标准输入设备构造BufferedReader对象

            System.out.println("Client:"+is.readLine());

            //在标准输出上打印从客户端读入的字符串

            line=sin.readLine();//从标准输入读入一字符串

            while(!line.equals("bye")){//如果该字符串为 "bye",则停止循环

                os.println(line);//向客户端输出该字符串

                os.flush();//刷新输出流,使Client马上收到该字符串

                System.out.println("Server:"+line);//在系统标准输出上打印读入的字符串

                System.out.println("Client:"+is.readLine());//从Client读入一字符串,并打印到标准输出上

                line=sin.readLine();//从系统标准输入读入一字符串

            }//继续循环

            os.close(); //关闭Socket输出流

            is.close(); //关闭Socket输入流

            socket.close(); //关闭Socket

            server.close(); //关闭ServerSocket

        }catch(Exception e){

            System.out.println("Error:"+e);//出错,打印出错信息

        }
    }
}


(2)客户端(SocketClientTest.java)

package com.mcc.core.test.socket;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * socket客户端
 *
 * @author <a href="mailto:[email protected]">menergy</a>
 *         DateTime: 14-2-14  下午11:59
 */
public class SocketClientTest {
    public static void main(String arg[]){
        try{

            Socket socket=new Socket("127.0.0.1",4700);//向本机的4700端口发出客户请求

            BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));//由系统标准输入设备构造BufferedReader对象

            PrintWriter os=new PrintWriter(socket.getOutputStream());//由Socket对象得到输出流,并构造PrintWriter对象

            BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));//由Socket对象得到输入流,并构造相应的BufferedReader对象

            String readline;

            readline=sin.readLine(); //从系统标准输入读入一字符串

            while(!readline.equals("bye")){//若从标准输入读入的字符串为 "bye"则停止循环

                os.println(readline);//将从系统标准输入读入的字符串输出到Server

                os.flush();//刷新输出流,使Server马上收到该字符串

                System.out.println("Client:"+readline);//在系统标准输出上打印读入的字符串

                System.out.println("Server:"+is.readLine());//从Server读入一字符串,并打印到标准输出上

                readline=sin.readLine(); //从系统标准输入读入一字符串

            } //继续循环

            os.close(); //关闭Socket输出流

            is.close(); //关闭Socket输入流

            socket.close(); //关闭Socket

        }catch(Exception e) {

            System.out.println("Error"+e); //出错,则打印出错信息

        }
    }
}

第2章:非阻塞通信实践

(1)服务端(NIOServer.java)

package com.mcc.core.socket.server;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;

/**
 * 无阻塞IO服务器
 *
 * @author <a href="mailto:[email protected]">menergy</a>
 *         DateTime: 14-2-24  上午10:39
 */
public class NIOServer {
    static int BLOCK = 4096;
    // 处理与客户端的交互
    public class HandleClient {
        protected FileChannel channel;
        protected ByteBuffer buffer;
        public HandleClient() throws IOException {
            this.channel = new FileInputStream(filename).getChannel();
            this.buffer = ByteBuffer.allocate(BLOCK);
        }
        public ByteBuffer readBlock() {
            try {
                buffer.clear();
                int count = channel.read(buffer);
                buffer.flip();
                if (count <= 0)
                    return null;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return buffer;
        }
        public void close() {
            try {
                channel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    protected Selector selector;
    protected String filename = "e://data/ctbCgiInfo_2014.txt"; // a big file
    protected ByteBuffer clientBuffer = ByteBuffer.allocate(BLOCK);
    protected CharsetDecoder decoder;

    public NIOServer(int port) throws IOException {
        selector = this.getSelector(port);
        Charset charset = Charset.forName("UTF-8");
        decoder = charset.newDecoder();
    }

    // 获取Selector
    protected Selector getSelector(int port) throws IOException {
        ServerSocketChannel server = ServerSocketChannel.open();
        Selector sel = Selector.open();
        server.socket().bind(new InetSocketAddress(port));
        server.configureBlocking(false);
        server.register(sel, SelectionKey.OP_ACCEPT);
        return sel;
    }

    // 监听端口
    public void listen() {
        try {
            for (;;) {
                selector.select();
                Iterator<SelectionKey> iter = selector.selectedKeys()
                        .iterator();
                while (iter.hasNext()) {
                    SelectionKey key = iter.next();
                    iter.remove();
                    handleKey(key);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 处理事件
    protected void handleKey(SelectionKey key) throws IOException {
        if (key.isAcceptable()) { // 接收请求
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel channel = server.accept();
            channel.configureBlocking(false);
            channel.register(selector, SelectionKey.OP_READ);
        } else if (key.isReadable()) { // 读信息
            SocketChannel channel = (SocketChannel) key.channel();
            int count = channel.read(clientBuffer);
            if (count > 0) {
                clientBuffer.flip();
                CharBuffer charBuffer = decoder.decode(clientBuffer);
                System.out.println("Client >>" + charBuffer.toString());
                SelectionKey wKey = channel.register(selector,
                        SelectionKey.OP_WRITE);
                wKey.attach(new HandleClient());
            } else
                channel.close();
            clientBuffer.clear();
        } else if (key.isWritable()) { // 写事件
            SocketChannel channel = (SocketChannel) key.channel();
            HandleClient handle = (HandleClient) key.attachment();
            ByteBuffer block = handle.readBlock();
            if (block != null)
                channel.write(block);
            else {
                handle.close();
                channel.close();
            }
        }
    }

    public static void main(String[] args) {
        int port = 12345;
        try {
            NIOServer server = new NIOServer(port);
            System.out.println("Listernint on " + port);
            while (true) {
                server.listen();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}



(2)客户端(NIOClient.java)

package com.mcc.core.socket.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 无阻塞IO客户端
 *
 * @author <a href="mailto:[email protected]">menergy</a>
 *         DateTime: 14-2-24  上午10:48
 */
public class NIOClient {
    static int SIZE = 100;
    static InetSocketAddress ip = new InetSocketAddress("localhost",12345);
    static CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
    static class Download implements Runnable {
        protected int index;
        public Download(int index) {
            this.index = index;
        }

        public void run() {
            try {
                long start = System.currentTimeMillis();
                SocketChannel client = SocketChannel.open();
                client.configureBlocking(false);
                Selector selector = Selector.open();
                client.register(selector, SelectionKey.OP_CONNECT);
                client.connect(ip);
                ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
                int total = 0;
                FOR: for (;;) {
                    selector.select();
                    Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
                    while (iter.hasNext()) {
                        SelectionKey key = iter.next();
                        iter.remove();
                        if (key.isConnectable()) {
                            SocketChannel channel = (SocketChannel) key.channel();
                            if (channel.isConnectionPending())
                                channel.finishConnect();
                            channel.write(encoder.encode(CharBuffer.wrap("Hello from " + index)));
                            channel.register(selector, SelectionKey.OP_READ);
                        } else if (key.isReadable()) {
                            SocketChannel channel = (SocketChannel) key.channel();
                            int count = channel.read(buffer);
                            if (count > 0) {
                                total += count;
                                // 读取的信息信息
                                final String readMessage = new String(buffer.array(), 0, count);
                                System.out.println("读取信息:\n" + readMessage);
                                buffer.clear();
                            } else {
                                client.close();
                                break FOR;
                            }
                        }
                    }
                }
                double last = (System.currentTimeMillis() - start) * 1.0 / 1000;
                System.out.println("Thread " + index + " downloaded " + total
                        + "bytes in " + last + "s.");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        ExecutorService exec = Executors.newFixedThreadPool(SIZE);
        for (int index = 0; index < SIZE; index++) {
            exec.execute(new Download(index));
        }
        exec.shutdown();
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章