在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来
在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来
贴下课堂笔记:
在Java中使用NIO进行网络TCP套接字编程主要以下几个类:
ServerSocketChannel: 服务端套接字通道,主要监听接收客户端请求
Selector:通道选择器,主要用于管理服务端通道和所有客户端通道(监听通道中发生的事件),也就说是一个多路通道复用器。
SelectorKey: 事件选择键
SocketChannel: 套接字通道(客户端)
这篇文章《NIO编程中的SelectionKey.interestOps方法中的逻辑运算》解决了我一些疑问,地址:https://blog.csdn.net/woaiqianzhige/article/details/78696188
NIO 套接字服务端开发步骤:
- 创建选择器
- 启动服务端通道
- 设置服务端通道为非阻塞模式
- 将服务端通道注册到选择器
- 轮训通道事件
- 处理通道事件
- 关闭通道(可选)
案例:服务端接收客户端发送的短信息,服务端回复已收到。
服务端代码:
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语句的位置放错了位置,哎,看了半天没看出来的更多相关文章
- vue学习-day05 -- 案例:名字合并(监听data数据的改变)
1.案例:名字合并(监听data数据的改变) 使用keyup事件监听data数据的改变 <!DOCTYPE html> <html> <head> <titl ...
- java Socket(TCP)编程小项目
package 服务器端相关操作; import java.io.Serializable; /* * 创建存储需要传输信息的对象,方便客户端向服务器端传送数据 */ public class Cli ...
- 微信小程序实现watch属性监听数据变化
Vue 提供了一种通用的方式来观察和响应 Vue 实例上的数据变动:监听属性 watch. 虽然watch的滥用会导致性能不佳,但在一些情况下我们还是需要watch,使得代码更加简洁.逻辑更加清晰(其 ...
- Scratch编程小案例:愤怒的小牛
愤怒的小鸟曾经很热门,网上还说他是程序员最喜欢玩的游戏.最先我是WIKIOI的评测页面看到他的,后来在2014年全国信息学奥林匹克联赛第一天第三题飞扬的小鸟也看到了它.因此,突然想做一个类似愤怒的小鸟 ...
- 《java入门第一季》之UDP协议下的网络编程小案例
需求,一台电脑发送数据,其他电脑都可以收到该数据.使用广播地址. 发送端: import java.io.BufferedReader; import java.io.IOException; imp ...
- 小程序组件中有bindinput监听报异常
真机上有问题,ide上是没问题的, 组件有处理函数,结果异常说页面没有处理函数,加上处理函数后就不报异常了.
- 广播接收者案例_sd卡状态监听
(1)定义广播接收者 import android.content.BroadcastReceiver; import android.content.Context; import android. ...
- 《java入门第一季》之类小案例(模拟用户登录)
首先是做一个用户登录的小案例.在此基础上加入其它逻辑. import java.util.Scanner; /* * 模拟登录,给三次机会,并提示还有几次.如果登录成功,就可以玩猜数字小游戏了. * ...
- 第13章 TCP编程(3)_基于自定义协议的多进程模型
5. 自定义协议编程 (1)自定义协议:MSG //自定义的协议(TLV:Type length Value) typedef struct{ //协议头部 ];//TLV中的T unsigned i ...
随机推荐
- Vue中的scoped及穿透方法
何为scoped? 在vue文件中的style标签上,有一个特殊的属性:scoped.当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,也就是说,该样式只能适用于当前组 ...
- android 开发常见问题
指定版本 就OK了 路径: android/app/build.gradle compile ("com.facebook.react:react-native:填你自己的RN版本" ...
- jquery-layer弹框在火狐浏览器中弹框不显示的问题
在使用layer控件设置弹框时, 谷歌浏览器中能正常弹出, 显示在页面中央位置. 而在火狐浏览器中, 弹框只显示标题, 并且弹框内容不显示. 在火狐浏览器中弹框的效果如下图红色方框中的弹出框所示, 但 ...
- Linux共享库、静态库、动态库详解
1. 介绍 使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数据可以在事后供其他的程序使用.程序函数库 ...
- MySQL,简单了解下、
第一章 数据备份与导入导出 1.1.备份基本概念介绍 1.2.mysqldump详解 1.3.mydumper浅析 1.4.MySQL物理备份基本操作 1.5.了解mysqlpump工具 1.6.数据 ...
- 使用Spring Session实现Spring Boot水平扩展
小编说:本文使用Spring Session实现了Spring Boot水平扩展,每个Spring Boot应用与其他水平扩展的Spring Boot一样,都能处理用户请求.如果宕机,Nginx会将请 ...
- spring boot -Properties & configuration
72. Properties & configuration72.1 Automatically expand properties at build timeRather than hard ...
- sql server 高可用故障转移(6)
创建分布式事务处理DTC群集服务 在hsr3 ip 49上继续 \ 输入一个没有冲突的ip地址用作SQL-CL的DTC解析地址:192.168.2.110,通过检测后会在DNS服务器中自动创建一条记录 ...
- pymongo的使用
利用python操作mongodb需要导入pymongo库 pip install pymongo 1.连接mongodb import pymongo client = pymo ...
- javascript 判断对象类型
typeof typeof是一个一元运算符,它返回的结果 始终是一个字符串,对不同的操作数,它返回不同的结果. 此表总结了typeof所有可能的返回值: 操作数类型 返回值 undefined &qu ...