在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来

贴下课堂笔记:

在Java中使用NIO进行网络TCP套接字编程主要以下几个类:

ServerSocketChannel: 服务端套接字通道,主要监听接收客户端请求

Selector:通道选择器,主要用于管理服务端通道和所有客户端通道(监听通道中发生的事件),也就说是一个多路通道复用器。

SelectorKey: 事件选择键

SocketChannel: 套接字通道(客户端)

这篇文章《NIO编程中的SelectionKey.interestOps方法中的逻辑运算》解决了我一些疑问,地址:https://blog.csdn.net/woaiqianzhige/article/details/78696188

NIO 套接字服务端开发步骤:

  1. 创建选择器
  2. 启动服务端通道
  3. 设置服务端通道为非阻塞模式
  4. 将服务端通道注册到选择器
  5. 轮训通道事件
  6. 处理通道事件
  7. 关闭通道(可选)

案例:服务端接收客户端发送的短信息,服务端回复已收到。

服务端代码:

 import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set; public class Server {
private Selector selector;
private ServerSocketChannel serverSocketChannel;
private ByteBuffer byteBuffer = ByteBuffer.allocate(8192); /**
* 构造方法 启动服务器
*
* @param port
* @throws IOException
*/
public Server() {
try {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(10086));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Server start successful with port: 10086");
} catch (ClosedChannelException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) throws Exception {
new Server().start();
} private void start() {
while (true) {
try {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = keys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
keyIterator.remove();
if (!key.isValid()) {
continue;
}
if (key.isAcceptable()) {
accept(key);
}
if (key.isReadable()) {
receive(key);
}
if (key.isWritable()) {
reply(key);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
} private void reply(SelectionKey key) {
try {
SocketChannel socketChannel = (SocketChannel) key.channel();
byteBuffer.clear();
String message = "receive success";
byteBuffer.put(message.getBytes());
byteBuffer.flip();
socketChannel.write(byteBuffer);
System.out.println("reply:" + message);
byteBuffer.clear();
key.interestOps(SelectionKey.OP_READ);
} catch (IOException e) {
e.printStackTrace();
}
} private void receive(SelectionKey key) {
try {
SocketChannel socketChannel = (SocketChannel) key.channel();
byteBuffer.clear();
int flag = socketChannel.read(byteBuffer);
if (flag == -1) {
key.channel().close();
key.cancel();
return;
}
byteBuffer.flip();
byte[] buf = new byte[byteBuffer.remaining()];
byteBuffer.get(buf);
String message = new String(buf);
System.out.println("receive message:" + message);
byteBuffer.clear();
key.interestOps(SelectionKey.OP_WRITE);
} catch (IOException e) {
e.printStackTrace();
}
} private void accept(SelectionKey key) {
try {
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
System.out.println(Thread.currentThread().getName() + ": create client channel.");
} catch (ClosedChannelException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

客户端代码:

 import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner; public class Client {
private Selector selector;
private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
private SocketChannel socketChannel; public Client() {
try {
selector = Selector.open();
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
socketChannel.connect(new InetSocketAddress("127.0.0.1", 10086));
System.out.println("Client start successful");
} catch (ClosedChannelException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
new Client().start();
} private void start() {
while (true) {
try {
selector.select();
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid()) {
continue;
}
if (key.isConnectable()) {
if (socketChannel.finishConnect()) {
key.interestOps(key.interestOps() & ~SelectionKey.OP_CONNECT);
System.out.println("Client connect server success");
}
}
if (key.isReadable()) {
receive(key);
}
if (key.isWritable()) {
reply(key);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} private void reply(SelectionKey key) {
try {
@SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
byteBuffer.clear();
System.out.println("please input message:");
String message = scanner.next();
byteBuffer.put(message.getBytes());
byteBuffer.flip();
socketChannel.write(byteBuffer);
byteBuffer.clear();
System.out.println("send message:" + message);
key.interestOps(SelectionKey.OP_READ);
} catch (IOException e) {
e.printStackTrace();
}
} private void receive(SelectionKey key) {
try {
byteBuffer.clear();
socketChannel.read(byteBuffer);
byteBuffer.flip();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
String message = new String(bytes).trim();
System.out.println("receive message: " + message);
byteBuffer.clear();
key.interestOps(SelectionKey.OP_WRITE);
} catch (IOException e) {
e.printStackTrace();
}
}
}

真是粗心大意了。。。特发此博文给我自己涨涨记性

在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来的更多相关文章

  1. vue学习-day05 -- 案例:名字合并(监听data数据的改变)

    1.案例:名字合并(监听data数据的改变) 使用keyup事件监听data数据的改变 <!DOCTYPE html> <html> <head> <titl ...

  2. java Socket(TCP)编程小项目

    package 服务器端相关操作; import java.io.Serializable; /* * 创建存储需要传输信息的对象,方便客户端向服务器端传送数据 */ public class Cli ...

  3. 微信小程序实现watch属性监听数据变化

    Vue 提供了一种通用的方式来观察和响应 Vue 实例上的数据变动:监听属性 watch. 虽然watch的滥用会导致性能不佳,但在一些情况下我们还是需要watch,使得代码更加简洁.逻辑更加清晰(其 ...

  4. Scratch编程小案例:愤怒的小牛

    愤怒的小鸟曾经很热门,网上还说他是程序员最喜欢玩的游戏.最先我是WIKIOI的评测页面看到他的,后来在2014年全国信息学奥林匹克联赛第一天第三题飞扬的小鸟也看到了它.因此,突然想做一个类似愤怒的小鸟 ...

  5. 《java入门第一季》之UDP协议下的网络编程小案例

    需求,一台电脑发送数据,其他电脑都可以收到该数据.使用广播地址. 发送端: import java.io.BufferedReader; import java.io.IOException; imp ...

  6. 小程序组件中有bindinput监听报异常

    真机上有问题,ide上是没问题的,   组件有处理函数,结果异常说页面没有处理函数,加上处理函数后就不报异常了.

  7. 广播接收者案例_sd卡状态监听

    (1)定义广播接收者 import android.content.BroadcastReceiver; import android.content.Context; import android. ...

  8. 《java入门第一季》之类小案例(模拟用户登录)

    首先是做一个用户登录的小案例.在此基础上加入其它逻辑. import java.util.Scanner; /* * 模拟登录,给三次机会,并提示还有几次.如果登录成功,就可以玩猜数字小游戏了. * ...

  9. 第13章 TCP编程(3)_基于自定义协议的多进程模型

    5. 自定义协议编程 (1)自定义协议:MSG //自定义的协议(TLV:Type length Value) typedef struct{ //协议头部 ];//TLV中的T unsigned i ...

随机推荐

  1. Python_小学口算题库生成器

    import random import os import tkinter import tkinter.ttk from docx import Document columnsNumber = ...

  2. java定时任务调度-Timer(1)

    一.定义 有且仅有一个后台线程对多个业务线程进行定时定频率的调度 二. Timer  ---->  Timer Task  (中有run();方法) 通过 new Timer().schedul ...

  3. MySql Query Cache 优化

    query cache原理 当mysql接收到一条select类型的query时,mysql会对这条query进行hash计算而得到一个hash值,然后通过该hash值到query cache中去匹配 ...

  4. sql server 高可用性技术总结

    一.  复制Replication(快照.事务.合并) 应用场景: 负载均衡.提供副本读,写操作. 分区将历史数据复制到其它表中. 授权,将数据提供它人使用. 数据合并. 故障转移. 优点: 实现简单 ...

  5. Fedora Linux安装deb包

    前言: 我们知道,在Linux系统上有两种主要的软件包格式,分别是RPM和deb. RPM是"RPM Package Manager(RPM软件包管理器)"的递归缩写.RPM是一种 ...

  6. tkinter中表格的建立(十三)

    表格的建立 import tkinter from tkinter import ttk wuya = tkinter.Tk() wuya.title("wuya") wuya.g ...

  7. Backbone.js 和 Nodejs 的一些共同点搞不清楚

    前端方面 我用 Backbone.js 做过前端的开发,印象里就是后端按模型对象的属性把 JSON 数据发过来,我写在模板里渲染就好了 模板加载( underscore.js ) 建立模型 渲染视图 ...

  8. javascript 面向对象程序设计--深刻理解对象

    javascript中,每个对象都是基于一个引用类型创建的,我们可以把ECMAScript 的对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数. 深刻理解对象 创建自定义对象的最简单方式就 ...

  9. 究竟谁在绑架中国的4G政策?

    2009年中国正式发放3G牌照以来,尽管在开始阶段受到了应用不足的困扰,但是随着智 能手机的迅速推广,3G移动通信也开始在中国得到了飞速的发展.就在消费者以及市场 逐步接受并广泛应用该技术之际,4G通 ...

  10. MFC中ComboBox控件用法

    MFC ComboBox 一.入门篇 ComboBox (组合框)控件很简单,可以节省空间.从用户角度来看,这个控件是由一个文本输入控件和一个下拉菜单组成的.用户可以从一个预先定义的列表里选择一个选项 ...