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();
    }
}



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