Java ServerSocketChannel SocketChannel(回调)

2023-11-25

我正在努力学习Java。我想实现一个简单的联网连接 4 游戏以及聊天功能。

我希望我的网络逻辑是非阻塞的,所以经过大量研究,我发现 SocketChannel 就是我重新调整我的需求后的样子。

仍然没有意义的是 SocketChannel 中缺少 CallBack 函数。就像 C# 中的情况一样。

这次我的疑问是:如何将收到的数据传递到聊天或游戏表单(JFrame)?

一些指导是最受欢迎的。


您需要使用选择器。首先创建一个选择器来接收事件:

Selector selector = Selector.open()

然后您需要向选择器注册 ServerSocketChannel:

SelectionKey acceptKey = server.register(selector, SelectionKey.OP_ACCEPT);

然后,您需要使用选择器来处理传入的事件(您可以将其视为该过程的“回调”部分:

while(true){
  //how many channel keys are available
  int available = selector.select(); 
  //select is blocking, but should only return if available is >0, this is more of a sanity check
  if(available == 0) continue;

  Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
  while(keys.hasNext()){
    SelectionKey key = keys.next();
    keys.remove();
    //someone is trying to connect to the server socket
    if(key.isAcceptable())  doAccept(key); 
    //someone is sending us data
    else if(key.isReadable()) doRead(key); 
    //we are trying to (and can) send data
    else if(key.isWritable()) doWrite(key);
}

重点将在 doAccept()、doRead() 和 doWrite() 中。对于接受键,选择键将包含创建新套接字的信息。

doAccept(SelectionKey key){

//create the new socket
SocketChannel socket = ((ServerSocketChannel)key.channel()).accept(); 
//make it non-blocking as well
socket.configureBlocking(false);

...
//here you would likely have some code to init your game objects / communication protocol, etc. and generate an identifier object (used below).
//and be able to find the socket created above
...

//Since it is non blocking it needs a selector as well, and we register for both read and write events
SelectionKey socketKey = socket.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
// so we can identify the events as they come in
socketKey.attach(someSocketIndentifier);
}

最后一行向键添加一些对象,以便从选择器接收到的事件可以归因于连接(例如,它可能是游戏中的玩家)。所以现在你可以接受新的连接,你只需要读取和写入。

doRead(SelectionKey key){
  //here we retrieve the key we attached earlier, so we now what to do / wheer the data is coming from
  MyIdentifierType myIdentifier = (MyIdentifierType)key.attachment();
  //This is then used to get back to the SocketChannel and Read the Data
  myIdentifier.readTheData();
}

类似地对于写

doWrite(SelectionKey key){
  //here we retrieve the key we attached earlier, so we now what to do / wheer the data is coming from
  MyIdentifierType myIdentifier = (MyIdentifierType)key.attachment();
  //This is then used to get back to the SocketChannel and Read the Data
  myIdentifier.getSocketHandler().writePendingData();
}

读取相当简单,您只需创建一个 ByteBuffer,然后调用 SocketChannels read(ByteBuffer) (或其变体之一)即可在通道上准备好数据,直到其为空。

写入有点棘手,因为您通常希望缓冲要写入的数据,直到收到写入事件:

class MyNetworkClass{
  ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
  SocketChannel commchannel; //from the server accept processing

  ...

  public void write(byte[] data){
    //here the class writeBuffer object is filled with the data
    //but it isn't actually sent over the socket
    ...
  }

  public void writePendingData(){
    //here actually write the data to the socket
    commchannel.write(writeBuffer);
  }
}

请注意,您将需要适当的代码来管理类中的缓冲区(如果缓冲区已满),或者如果缓冲区中的所有数据未写出到套接字,则需要在写入挂起方法中对其进行适当修改,以及过程中可能抛出的各种异常。希望这有助于您入门。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java ServerSocketChannel SocketChannel(回调) 的相关文章

  • 如何创建一个在给定范围内随机打乱数字的 int 数组[重复]

    这个问题在这里已经有答案了 基本上 假设我有一个可以容纳 10 个数字的 int 数组 这意味着我可以在每个索引中存储 0 9 每个数字只能存储一次 如果我运行下面的代码 int num new int 10 for int i 0 i l
  • 尝试将 XLSX 数据导入 R 时出现 IllegalArgumentException

    在将 xlsx 文件导入 R 时 我遇到了以下错误 mydata lt read xlsx C Users aniruddha Downloads failingExample xlsx 1 Error in jcall row ir Lo
  • API 级别 15 的印地语字体(又名 Android 4.0.2)

    我有一个基于印地语内容的 Android 应用程序 并使用了 Android API 16 SDK 中的 devangiri 字体 并重命名为印地语 ttf 文本在 API 级别 16 和 17 上渲染良好 但在 Android API 级
  • 良好的客户端套接字池

    我需要管理从我的 Java 应用程序到外部服务器的长时间运行的 TCP 套接字连接 我正在寻找一个好的套接字池 这样我就可以重复使用套接字 有什么建议吗 你可以看看在上面建立一个套接字池公共池 http commons apache org
  • 启动jetty服务器时出现NoClassDefFoundError

    我正在尝试在码头服务器中托管我的网络应用程序 spring 我将 war 文件复制到 jetty 服务器中的 webapp 文件夹中 我并不是想嵌入jetty服务器 而是试图在jetty内托管应用程序 如tomcat 我没有安装jetty
  • 使用 Spring boot CrudRepository 过滤数据

    我有一个简单的 REST 服务 可以使用 Spring boot 访问数据CrudRepository 该存储库已经实现了分页和排序功能 如下所示 public interface FlightRepository extends Crud
  • System.out 什么时候不会出现在 Java 控制台中?

    我明白任何要标准化的东西 System out 将出现在 Java 控制台窗口中 启用时 我在某个地方发现 在某些情况下可能无法尝试这样做 例如 在 Swing 应用程序中 是这样吗 基本上 什么情况或设置我不希望在控制台中看到标准输出 例
  • 让线程休眠的更好方法

    我一直在编写有关 Java 8 中 2D 图形的教程 当时 NetBeans 给了我一个提示 Thread Sleep会影响性能 然而 尽管我已经找到了几种更好的方法 但我还没有找到一种方法来包含它们而不弄乱代码 package platf
  • 记录中嵌套 Spring 配置(ConfigurationProperties)

    如何绘制一张地图application yaml将嵌套属性配置为 Java 中类似的记录结构 例如 如果我们有以下 yaml foo bar something 42 baz otherThing true color blue 所需的记录
  • Struts 2 - 使用 CKEditor 拦截上传的图像文件

    我有一个CKEditor在网站的不同页面上 所以我将上传内容设置为true以及让它工作的所有配置内容 并且图像上传工作得很好 Send it to the Server 标签 但从这里我想拦截或互动upload函数能够将图像上传到文件夹中
  • 如何以编程方式使用 TestNG 运行 Selenium Java 测试?

    我使用 Selenium RC 和 Java 使用 TestNG 作为测试框架 我使用 Eclipse 作为 IDE 我想非常轻松地从我自己的程序中调用 TestNG 我怎样才能做到这一点 我的以下 Java 代码运行良好 Test pub
  • Android 设计导航抽屉 - 如何在 nav xml 中添加开关?

    我正在使用新的 Android 设计导航抽屉 我想在抽屉里加一个开关 有办法实现这个吗 这是菜单 xml menu menu
  • Java中使用final关键字会提高性能吗?

    在 Java 中 我们看到很多地方final可以使用关键字 但其使用并不常见 例如 String str abc System out println str 在上述情况下 str can be final但这通常被忽略 当一个方法永远不会
  • Servlet上下文和Spring应用程序上下文的本质区别

    我正在阅读 spring 框架文档 现在我在应用范围概念 http docs spring io spring docs current spring framework reference htmlsingle beans factory
  • JPA 的 commit() 方法是否使实体分离?

    我现在一直在搜索JPA实体生命周期 但现在 关于实体生命周期存在一些缺失的点 我在 stackoverflow 的一篇帖子中找到了下图 请记住该图已被投票 根据此图 当我们持久化实体时 它就变成了托管实体 好的 没问题 当我们提交时 数据会
  • 对 JFace Treeviewer 多列进行排序

    我希望用户能够对TreeViewer只要他想 只要单击列标题即可 但是我不知道正确的方法 我发现我们可以使用ViewerComparator对不同的元素进行排序 但是 我不知道如何设置侦听器以便能够正确进行升序或降序排序 有没有办法让 JF
  • Java HashMap 与 ArrayList 相比的内存开销

    我想知道java HashMap与ArrayList相比的内存开销是多少 Update 我想提高搜索一大包 600 万以上 相同对象的特定值的速度 因此 我正在考虑使用一个或多个HashMap来代替ArrayList 但我想知道 HashM
  • 在文件中查找一行并将其删除

    我正在寻找一个小代码片段 它将在文件中找到一行并删除该行 不是内容而是行 但找不到 例如 我在以下文件中 我的文件 txt aaa bbb ccc ddd 需要有这样的功能 public void removeLine String lin
  • SocketTimeoutException:插入 Google 云端硬盘时读取超时 - 是否可以重试?

    如同Java Google Drive SDK File insert execute 上的 SocketTimeoutException https stackoverflow com questions 17583630 java go
  • onActivityresult 数据为空

    这是我的相机应用程序 我想在其中捕获图像并裁剪它 但它拍照保存在我的 myimage 目录中 但不执行裁剪功能 请我需要帮助 我是这个领域的新人 这是我的相机开源代码 Intent intent new Intent MediaStore

随机推荐

  • 如何在 Blazor 中模拟 setTimeout()?

    我正在尝试在 Blazor 中复制一个简单的 JS 方法 这个想法是type out给定单词 句子 等中的每个字符 W3学校有一个很好的例子 说明了如何快速完成此操作 那么 给出他们的示例 如何在 C 和 JS 中做同样的事情呢 var i
  • 使用剪贴板管理器在 Android 中复制粘贴图像

    我想使用剪贴板管理器将图像从我的 Android 应用程序复制到其他 Android 应用程序 我做了很多研究并阅读了this教程 但不包括图像复制部分 下面的代码复制图像 但当我尝试粘贴时 仅粘贴图像的路径 ContentValues v
  • 如何让lldb忽略EXC_BAD_ACCESS异常?

    我正在 Mac OSX 上根据 sigaction sa handler 机制编写一个程序 运行用户的代码片段并准备随时捕获信号 异常 该程序工作正常 但问题是我无法使用 lldb 对其进行调试 即使我设置了 lldb 似乎也无法忽略任何异
  • 滚动函数触发多次而不是一次

    我正在尝试创建一个网站 只需一次滚动操作即可自动滚动到每个部分 这意味着代码必须检查页面是向上滚动还是向下滚动 我相信下面的代码解决了我的问题 但是在页面滚动时滚动操作被多次触发 您将看到 if 语句中的第一个警报达到 5 而不是所需的 1
  • $.getJson 在 IE 中不起作用

    好的 由于某种原因我的 getJson 无法工作 我正在提取一些股票信息 它适用于除 IE 之外的所有主要浏览器 我在这里创建了一个 JSfiddle http jsfiddle net qZhSk 如果有人可以帮助我理解我做错了什么 那将
  • MySql,分割字符串并插入表中

    我的存储过程有两个输入 第一个是 RoledID 第二个是 MenuID MenusIDs 是需要使用 RoledID 插入的逗号分隔菜单 ID 列表 RoleId 只是一个 INT 我们需要将此 RoledID 与每个 MenuID 相对
  • 如何用python构建人口金字塔

    我正在尝试使用 seaborn 从 pandas df 构建人口金字塔 问题是有些数据没有显示 正如您从我创建的图中看到的 缺少一些数据 Y 轴刻度为 21 而 df 的年龄类别为 21 那么为什么它们不匹配呢 我缺少什么 这是我写的代码
  • 如何更改WKWebView中的文本选择颜色?

    我正在尝试更改文本选择颜色WKWebView 我几乎尝试了所有建议的解决方案UIWebView WKWebView我能找到的 更改色调颜色不起作用 应用CSS selection webkit tap highlight color标签也不
  • BULK INSERT 后检查 FK 约束

    我有几个大数据集 O 1TB 我想将其导入到我的数据库中 我用BULK INSERT将数据导入临时表 然后使用SELECT and INSERT INTO用数据填充我的真实表格 这是因为我想改变一些事情的顺序 并将一些数据文件拆分成逻辑表
  • 在 Django 中格式化 DateTimeField

    在 Django 中保存时间戳时DateTimeField using auto now add这边走 creation timestamp models DateTimeField auto now add True 该字段以毫秒为单位保
  • Lua全局变量包含当前文件的路径?

    Lua中是否有一个全局变量包含当前正在解释的文件的路径 类似于 Python 的东西 file 多变的 我跑得很快for k v in pairs G do print k end在口译员中看看我是否能找到任何东西 仅列出以下变量 stri
  • 您没有用于调试 C# 的扩展,我们是否应该在 Marketplace 中找到 C# 扩展?

    我正在尝试使用 VSCode 调试 C 脚本 但当我按 F5 时它显示 但我确实在 VSCode 中安装了 C 扩展 关于我的 VSCode Version 1 56 2 system setup Commit 054a9295330880
  • 如何使用最后插入的 ID 将行插入到另一个表中?

    我的桌子上有两张SQL server GamerName and GamerValues 我想要那个 当我insert上的新行GamerName GamerName ID Name 1 Jeff 2 Geoff 3 Jarrod 4 Joe
  • 密钥库被篡改或密码不正确

    我知道已经有这样的问题 但我找不到任何可以帮助我的答案 我正在尝试获取 Google Maps API 密钥 为此我必须使用以下命令拥有 MD5 密钥 keytool list v alias androiddebugkey keystor
  • 如何将嵌套字典中的值映射到 Pydantic 模型?

    我正在尝试将嵌套 dict json 中的值映射到我的 Pydantic 模型 对我来说 当我的 json dict 具有扁平结构时 这很有效 然而 我正在努力将值从嵌套结构映射到我的 Pydantic 模型 假设我有一个以下格式的 jso
  • 如何检测浏览器中的目录选择功能?

    我想知道浏览器是否能够选择文件夹 而不仅仅是多个文件 当前的 Chrome 支持此功能 例如 http html5 demos appspot com static html5storage demos upload directory i
  • 为什么在 HashMap.keySet() 中声明局部变量 ks? [复制]

    这个问题在这里已经有答案了 我查看了java util HashMap的源代码 看到了以下代码 public Set
  • 提供正确的移动语义

    我目前正在尝试弄清楚如何使用包含指向已分配内存的指针的对象正确执行移动语义 我有一个大数据结构 其中包含指向实际存储的内部原始指针 出于效率原因 现在我添加了一个移动构造函数并移动operator 在这些方法中我std move 指向新结构
  • IServiceCollection 覆盖单个构造函数参数

    我有一个带有三个构造函数参数的类 在我的组合根中 我只想定义 覆盖one三个构造函数参数 另外两个依赖项已映射到我的 DI 容器中 并且应该从 IServiceProvider 创建 使用 Ninject 我可以做这样的事情 Bind
  • Java ServerSocketChannel SocketChannel(回调)

    我正在努力学习Java 我想实现一个简单的联网连接 4 游戏以及聊天功能 我希望我的网络逻辑是非阻塞的 所以经过大量研究 我发现 SocketChannel 就是我重新调整我的需求后的样子 仍然没有意义的是 SocketChannel 中缺