我的编程空间,编程开发者的网络收藏夹
学习永远不晚

教你怎么用java实现客户端与服务器一问一答

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

教你怎么用java实现客户端与服务器一问一答

运行效果

开启多个客户端

服务端效果:

客户端效果:

当一个客户端断开连接:

代码

因为代码中有注释,我就直接贴上来了

服务端:


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;
    
    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 {
        //创建一个服务端channel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
 
        //设置为非阻塞
        serverSocketChannel.configureBlocking(false);
 
        //获取服务器socket
        ServerSocket socket = serverSocketChannel.socket();
        //绑定ip和端口
        socket.bind(new InetSocketAddress(NioServer.PORT));
 
        //创建多路复用选择器,并保持打开状态,直到close
        selector = Selector.open();
 
        //将服务器管道注册到selector上,并监听accept事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("server start on port: " + NioServer.PORT);
        start();
    }
 
    public void start() throws IOException {
 
        //selector是阻塞的,直到至少有一个客户端连接。
        while (selector.select() > 0) {
            //SelectionKey是channel想Selector注册的令牌,可以通过chancel取消(不是立刻取消,会放进一个cancel list里面,下一次select时才会把它彻底删除)
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                //当这个key的channel已经准备好接收套接字连接
                if(selectionKey.isAcceptable()) {
                    connectHandle(selectionKey);
                }
 
                //当这个key的channel已经准备好读取数据时
                if(selectionKey.isReadable()) {
                    readHandle(selectionKey);
                }
            }
        }
    }
 
    
    private void connectHandle(SelectionKey selectionKey) throws IOException {
        //注意,服务端用的是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("客户端连接成功,当前总数:" + (++count));
 
        writeBuffer.clear();
        writeBuffer.put("连接成功".getBytes(StandardCharsets.UTF_8));
        writeBuffer.flip();
        socketChannel.write(writeBuffer);
    }
 
    
    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();
 
        //终端监听用户输入
        new Thread(nioClient::terminal).start();
 
        //这个方法是阻塞的,要放在最后
        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后要删除,否则会重复处理
                iterator.remove();
                if(selectionKey.isReadable()) {
                    handleRead(selectionKey);
                }
 
                //只要连接成功,selectionKey.isWritable()一直为true
                if(selectionKey.isWritable()) {
                    handleWrite(selectionKey);
                }
            }
        }
    }
 
    
    private void handleWrite(SelectionKey selectionKey) throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
 
        // writeBuffer有数据就直接写入,因为另开了线程监听用户读取,所以要上锁
        synchronized (writeBuffer) {
            writeBuffer.flip();
            while (writeBuffer.hasRemaining()) {
                socketChannel.write(writeBuffer);
            }
            writeBuffer.compact();
        }
 
    }
 
    
    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("收到服务器发来的消息: " + res);
        readBuffer.clear();
    }
 
    
    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实现客户端与服务器一问一答的文章就介绍到这了,更多相关java实现客户端与服务器一问一答内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

教你怎么用java实现客户端与服务器一问一答

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何使用java实现客户端与服务器

小编给大家分享一下如何使用java实现客户端与服务器,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Java可以用来干什么Java主要应用于:1. web开发;2.
2023-06-14

怎么在java中使用SocketChannel实现一个客户端

怎么在java中使用SocketChannel实现一个客户端?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。常用的java框架有哪些1.SpringMVC,Spr
2023-06-14

Java聊天室之实现一个服务器与多个客户端通信

这篇文章主要为大家详细介绍了Java简易聊天室之实现一个服务器与多个客户端通信,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以了解一下
2022-11-13

python客户端与服务器端通信怎么实现

使用套接字进行Python客户端和服务器端通信分四步:创建服务器端、创建客户端端、发送和接收数据,关闭连接。示例代码展示了如何使用套接字在服务器端和客户端端之间建立连接、发送和接收数据。包括其他注意事项,例如防火墙配置、数据序列化和错误处理。
python客户端与服务器端通信怎么实现
2024-04-12

python客户端与服务器端通信怎么实现

Python客户端与服务器端通信可以通过套接字(socket)实现。1. 服务器端首先需要创建一个套接字,并绑定到指定的IP地址和端口上:```pythonimport socket# 创建一个套接字对象server_socket = so
2023-09-08

Java中怎么利用Socket实现一个通讯客户端

本篇文章给大家分享的是有关Java中怎么利用Socket实现一个通讯客户端,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。具体客户端代码如下:import java.net.*;
2023-06-17

怎么使用linux socket实现服务器和客户端对话

本文小编为大家详细介绍“怎么使用linux socket实现服务器和客户端对话”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用linux socket实现服务器和客户端对话”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来
2023-05-25

编程热搜

目录