溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用java實(shí)現(xiàn)客戶端與服務(wù)器

發(fā)布時(shí)間:2021-04-30 14:42:08 來源:億速云 閱讀:317 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下如何使用java實(shí)現(xiàn)客戶端與服務(wù)器,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

Java可以用來干什么

Java主要應(yīng)用于:1. web開發(fā);2. Android開發(fā);3. 客戶端開發(fā);4. 網(wǎng)頁開發(fā);5. 企業(yè)級(jí)應(yīng)用開發(fā);6. Java大數(shù)據(jù)開發(fā);7.游戲開發(fā)等。

運(yùn)行效果

開啟多個(gè)客戶端

服務(wù)端效果:

如何使用java實(shí)現(xiàn)客戶端與服務(wù)器

客戶端效果:

如何使用java實(shí)現(xiàn)客戶端與服務(wù)器

當(dāng)一個(gè)客戶端斷開連接:

如何使用java實(shí)現(xiàn)客戶端與服務(wù)器

代碼

因?yàn)榇a中有注釋,我就直接貼上來了

服務(wù)端:

package com.dayrain.server;
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
 
public class NioServer {
    /**端口**/
    private static final int PORT = 8081;
    /**buffer大小**/
    private static final int DEFAULT_BUFFER_SIZE = 1024;
    private final Selector selector;
    private final ByteBuffer readBuffer = ByteBuffer.allocate(NioServer.DEFAULT_BUFFER_SIZE);
    private final ByteBuffer writeBuffer = ByteBuffer.allocate(NioServer.DEFAULT_BUFFER_SIZE);
 
    private static int count = 0;
 
    public static void main(String[] args) throws IOException {
        new NioServer().start();
    }
 
    public NioServer() throws IOException {
        //創(chuàng)建一個(gè)服務(wù)端channel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
 
        //設(shè)置為非阻塞
        serverSocketChannel.configureBlocking(false);
 
        //獲取服務(wù)器socket
        ServerSocket socket = serverSocketChannel.socket();
        //綁定ip和端口
        socket.bind(new InetSocketAddress(NioServer.PORT));
 
        //創(chuàng)建多路復(fù)用選擇器,并保持打開狀態(tài),直到close
        selector = Selector.open();
 
        //將服務(wù)器管道注冊(cè)到selector上,并監(jiān)聽accept事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("server start on port: " + NioServer.PORT);
        start();
    }
 
    public void start() throws IOException {
 
        //selector是阻塞的,直到至少有一個(gè)客戶端連接。
        while (selector.select() > 0) {
            //SelectionKey是channel想Selector注冊(cè)的令牌,可以通過chancel取消(不是立刻取消,會(huì)放進(jìn)一個(gè)cancel list里面,下一次select時(shí)才會(huì)把它徹底刪除)
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                //當(dāng)這個(gè)key的channel已經(jīng)準(zhǔn)備好接收套接字連接
                if(selectionKey.isAcceptable()) {
                    connectHandle(selectionKey);
                }
 
                //當(dāng)這個(gè)key的channel已經(jīng)準(zhǔn)備好讀取數(shù)據(jù)時(shí)
                if(selectionKey.isReadable()) {
                    readHandle(selectionKey);
                }
            }
        }
    }
 
    /**
     * 處理連接
     * @param selectionKey
     */
    private void connectHandle(SelectionKey selectionKey) throws IOException {
        //注意,服務(wù)端用的是ServerSocketChannel,BIO中是ServerSocket
        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
        SocketChannel socketChannel = serverSocketChannel.accept();
        if(socketChannel == null) {
            return;
        }
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
 
        System.out.println("客戶端連接成功,當(dāng)前總數(shù):" + (++count));
 
        writeBuffer.clear();
        writeBuffer.put("連接成功".getBytes(StandardCharsets.UTF_8));
        writeBuffer.flip();
        socketChannel.write(writeBuffer);
    }
 
    /**
     * 讀取數(shù)據(jù)
     * @param selectionKey
     */
    private void readHandle(SelectionKey selectionKey){
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        try {
            readBuffer.clear();
            int read = socketChannel.read(readBuffer);
            if(read > 0) {
                readBuffer.flip();
                String receiveData = StandardCharsets.UTF_8.decode(readBuffer).toString();
 
                System.out.println("收到客戶端消息: " + receiveData);
 
                writeBuffer.clear();
                writeBuffer.put(receiveData.getBytes(StandardCharsets.UTF_8));
                writeBuffer.flip();
                socketChannel.write(writeBuffer);
            }
 
        }catch (Exception e) {
            try {
                socketChannel.close();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
            System.out.println("客戶端斷開了連接~~");
            count--;
        }
    }
}

客戶端

package com.dayrain.client;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
 
public class NioClient {
 
    private static final int PORT = 8081;
    private static final int DEFAULT_BUFFER_SIZE = 1024;
    private final Selector selector;
    private final ByteBuffer readBuffer = ByteBuffer.allocate(NioClient.DEFAULT_BUFFER_SIZE);
    private final ByteBuffer writeBuffer = ByteBuffer.allocate(NioClient.DEFAULT_BUFFER_SIZE);
 
    public static void main(String[] args) throws IOException {
        NioClient nioClient = new NioClient();
 
        //終端監(jiān)聽用戶輸入
        new Thread(nioClient::terminal).start();
 
        //這個(gè)方法是阻塞的,要放在最后
        nioClient.start();
    }
 
    public NioClient() throws IOException {
        selector = Selector.open();
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(InetAddress.getLocalHost(), NioClient.PORT));
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
    }
 
    public void start() throws IOException {
        while (selector.select() > 0) {
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                //拿到selectionKey后要?jiǎng)h除,否則會(huì)重復(fù)處理
                iterator.remove();
                if(selectionKey.isReadable()) {
                    handleRead(selectionKey);
                }
 
                //只要連接成功,selectionKey.isWritable()一直為true
                if(selectionKey.isWritable()) {
                    handleWrite(selectionKey);
                }
            }
        }
    }
 
    /**
     * 監(jiān)聽寫操作
     */
    private void handleWrite(SelectionKey selectionKey) throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
 
        // writeBuffer有數(shù)據(jù)就直接寫入,因?yàn)榱黹_了線程監(jiān)聽用戶讀取,所以要上鎖
        synchronized (writeBuffer) {
            writeBuffer.flip();
            while (writeBuffer.hasRemaining()) {
                socketChannel.write(writeBuffer);
            }
            writeBuffer.compact();
        }
 
    }
 
    /**
     * 監(jiān)聽讀操作
     */
    private void handleRead(SelectionKey selectionKey) throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        readBuffer.clear();
        socketChannel.read(readBuffer);
 
        readBuffer.flip();
        String res = StandardCharsets.UTF_8.decode(readBuffer).toString();
        System.out.println("收到服務(wù)器發(fā)來的消息: " + res);
        readBuffer.clear();
    }
 
    /**
     * 監(jiān)聽終端的輸入
     */
    private void terminal() {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        try {
            String msg;
            while ((msg = bufferedReader.readLine()) != null) {
                synchronized (writeBuffer) {
                    writeBuffer.put((msg + "\r\n").getBytes(StandardCharsets.UTF_8));
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
 
    }
 
}

以上是“如何使用java實(shí)現(xiàn)客戶端與服務(wù)器”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI