- 浏览: 370225 次
- 性别:
- 来自: Alien
文章分类
最新评论
-
风一样的男人__:
[flash=200,200][url]引用[/url][/f ...
java线程内存模型,线程、工作内存、主内存 -
极乐君:
厉害了,,,请问可以转载到我们专栏吗?会注明来源和地址的~专栏 ...
java线程内存模型,线程、工作内存、主内存 -
zdd001:
Spring 线程池使用 -
zdd001:
Spring 线程池使用 -
u014663756:
看了三行就知道是我想要的!!
java线程内存模型,线程、工作内存、主内存
- 晚上学习了下Java 的 NIO Socket编程,写了下面这个小程序,包括服务器端与客户端。实现的功能为客户端向服务器端发送随即数目的消息,服务器端一条一条的回应。消息内容保存在talks.properties文件中,内容为:
- Hi=Hi
- Bye=Bye
- 床前明月光=疑是地上霜
- 举头望明月=低头思故乡
- 少小离家老大回=乡音无改鬓毛衰
- 天王盖地虎=宝塔镇河妖
- 我是甲=我是乙
- 我是客户端=我是服务器
- 我是周星驰=我是周润发
- 客户端会随即发送“=”左边的消息,服务器端会回应客户端“=”右边的消息。如果客户端想断开连接,会向服务器发送一个"Bye",然后服务器会回应一个"Bye“。收到服务器端的"Bye"后,客户端会断开连接。
- 当然,java的properties文件不接受中文内容,你需要native2ascii一下。talks.properties 的实际文件内容为:
- Hi=Hi
- Bye=Bye
- \u5E8A\u524D\u660E\u6708\u5149=\u7591\u662F\u5730\u4E0A\u971C
- \u4E3E\u5934\u671B\u660E\u6708=\u4F4E\u5934\u601D\u6545\u4E61
- \u5C11\u5C0F\u79BB\u5BB6\u8001\u5927\u56DE=\u4E61\u97F3\u65E0\u6539\u9B13\u6BDB\u8870
- \u5929\u738B\u76D6\u5730\u864E=\u5B9D\u5854\u9547\u6CB3\u5996
- \u6211\u662F\u7532=\u6211\u662F\u4E59
- \u6211\u662F\u5BA2\u6237\u7AEF=\u6211\u662F\u670D\u52A1\u5668
- \u6211\u662F\u5468\u661F\u9A70=\u6211\u662F\u5468\u6DA6\u53D1
- 看下服务器端的代码。此例中的服务器端只有一个主线程,用于selector操作,并处理多个客户端的消息。在常规的socket编程中,每个客户端都需要单独开一个线程,效率比较低。代码为:
- package helloweenpad;
- import java.io.FileInputStream;
- import java.net.InetSocketAddress;
- import java.net.Socket;
- import java.nio.ByteBuffer;
- import java.nio.CharBuffer;
- import java.nio.channels.SelectionKey;
- import java.nio.channels.Selector;
- import java.nio.channels.ServerSocketChannel;
- import java.nio.channels.SocketChannel;
- import java.nio.charset.Charset;
- import java.nio.charset.CharsetDecoder;
- import java.nio.charset.CharsetEncoder;
- import java.util.Iterator;
- import java.util.Properties;
- public class MyFirstNIOServer {
- public static final int PORT = 12315;
- protected Selector selector;
- protected Charset charset = Charset.forName("UTF-8");
- protected CharsetEncoder charsetEncoder = charset.newEncoder();
- protected CharsetDecoder charsetDecoder = charset.newDecoder();
- protected Properties talks = new Properties();
- int clientCount;
- public MyFirstNIOServer() throws Exception {
- talks.load(new FileInputStream("E:\\talk.properties"));
- selector = Selector.open();
- ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
- serverSocketChannel.socket().bind(new InetSocketAddress(PORT)); // port
- serverSocketChannel.configureBlocking(false);
- serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// register
- p("Server localhost:" + PORT + " started. waiting for clients. ");
- while (true) {
- // selector 线程。select() 会阻塞,直到有客户端连接,或者有消息读入
- selector.select();
- Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
- while (iterator.hasNext()) {
- SelectionKey selectionKey = iterator.next();
- iterator.remove(); // 删除此消息
- // 并在当前线程内处理。(为了高效,一般会在另一个线程中处理此消息,例如使用线程池等)
- handleSelectionKey(selectionKey);
- }
- }
- }
- public void handleSelectionKey(SelectionKey selectionKey) throws Exception {
- if (selectionKey.isAcceptable()) {
- // 有客户端进来
- clientCount++;
- ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
- SocketChannel socketChannel = serverSocketChannel.accept();
- socketChannel.configureBlocking(false);
- Socket socket = socketChannel.socket();
- // 立即注册一个 OP_READ 的SelectionKey, 接收客户端的消息
- SelectionKey key = socketChannel.register(selector, SelectionKey.OP_READ);
- key.attach("第 " + clientCount + " 个客户端 [" + socket.getRemoteSocketAddress() + "]: ");
- p(key.attachment() + "\t[connected] =========================================");
- } else if (selectionKey.isReadable()) {
- // 有消息进来
- ByteBuffer byteBuffer = ByteBuffer.allocate(100);
- SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
- try {
- int len = socketChannel.read(byteBuffer);
- // 如果len>0,表示有输入。如果len==0, 表示输入结束。需要关闭 socketChannel
- if (len > 0) {
- byteBuffer.flip();
- String msg = charsetDecoder.decode(byteBuffer).toString();
- // 根据客户端的消息,查找到对应的输出
- String newMsg = talks.getProperty(msg);
- if (newMsg == null)
- newMsg = "Sorry? I don't understand your message. ";
- // UTF-8 格式输出到客户端,并输出一个'n'
- socketChannel.write(charsetEncoder.encode(CharBuffer.wrap(newMsg + "\n")));
- p(selectionKey.attachment() + "\t[recieved]: " + msg + " ----->\t[send]: " + newMsg);
- } else {
- // 输入结束,关闭 socketChannel
- p(selectionKey.attachment() + "read finished. close socketChannel. ");
- socketChannel.close();
- }
- } catch (Exception e) {
- // 如果read抛出异常,表示连接异常中断,需要关闭 socketChannel
- e.printStackTrace();
- p(selectionKey.attachment() + "socket closed? ");
- socketChannel.close();
- }
- } else if (selectionKey.isWritable()) {
- p(selectionKey.attachment() + "TODO: isWritable() ???????????????????????????? ");
- } else if (selectionKey.isConnectable()) {
- p(selectionKey.attachment() + "TODO: isConnectable() ????????????????????????? ");
- } else {
- p(selectionKey.attachment() + "TODO: else. ");
- }
- }
- public static void p(Object object) {
- System.out.println(object);
- }
- public static void main(String[] args) throws Exception {
- new MyFirstNIOServer();
- }
- }
- 再看下客户端代码。这个客户端使用了常规的socket编程,没有使用NIO。是否使用NIO对另一方是透明的,对方看不见,也不关心。无论使用NIO还是使用常规socket,效果都是一样的,只是NIO的效率要高一些。代码为:
- package helloweenpad;
- import java.io.BufferedReader;
- import java.io.FileInputStream;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.net.Socket;
- import java.util.Properties;
- import java.util.Random;
- public class MyFirstNIOClientTest extends Thread {
- public static final String HOST = "localhost";
- public static final int PORT = 12315;
- boolean exist = false;
- Properties talks = new Properties();
- Random random = new Random();
- String[] keys;
- int messageCount = 0;
- public void run() {
- try {
- // 对话内容
- talks.load(new FileInputStream("E:\\talk.properties"));
- // 客户端发送 "=" 左边的内容
- keys = new String[talks.size()];
- talks.keySet().toArray(keys);
- Socket socket = new Socket(HOST, PORT);
- OutputStream ous = socket.getOutputStream();
- InputStream ins = socket.getInputStream();
- // 接收线程,接收服务器的回应
- RecieverThread reciever = new RecieverThread(ins);
- reciever.start();
- while (!exist) {
- messageCount++;
- // 选择一个随机消息
- String msg = chooseMessage();
- synchronized (ins) {
- // 发送给服务器端
- ous.write(msg.getBytes("UTF-8"));
- System.out.println("[send]\t" + messageCount + ": " + msg);
- // 然后等待接收线程
- ins.wait();
- }
- if (msg.equals("Bye")) {
- break;
- }
- }
- ins.close();
- ous.close();
- socket.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public String chooseMessage() {
- int index = random.nextInt(keys.length);
- String msg = keys[index];
- // 如果 10 次就选中 Bye,则重新选择,为了使对话内容多一些
- if (messageCount < 10 && msg.equalsIgnoreCase("Bye")) {
- return chooseMessage();
- }
- return msg;
- }
- // 接收线程
- class RecieverThread extends Thread {
- private InputStream ins;
- public RecieverThread(InputStream ins) {
- this.ins = ins;
- }
- @Override
- public void run() {
- try {
- String line = null;
- BufferedReader r = new BufferedReader(new InputStreamReader(
- ins, "UTF-8"));
- // readLine()会阻塞,直到服务器输出一个 '\n'
- while ((line = r.readLine()) != null) {
- System.out.println("[Recieved]: " + line);
- synchronized (ins) {
- // 接收到服务器的消息,通知下主线程
- ins.notify();
- }
- if (line.trim().equals("Bye")) {
- exist = true;
- break;
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) throws Exception {
- // 开三个客户端线程
- for (int i = 0; i < 3; i++) {
- try {
- new MyFirstNIOClientTest().start();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
- =============================================================================
- 服务器端的输出:
- Server localhost:12315 started. waiting for clients.
- 第 1 个客户端 [/127.0.0.1:1890]: [connected] =========================================
- 第 2 个客户端 [/127.0.0.1:1865]: [connected] =========================================
- 第 3 个客户端 [/127.0.0.1:1866]: [connected] =========================================
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: 床前明月光 -----> [send]: 疑是地上霜
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: 我是周星驰 -----> [send]: 我是周润发
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: 少小离家老大回 -----> [send]: 乡音无改鬓毛衰
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: 床前明月光 -----> [send]: 疑是地上霜
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: 我是客户端 -----> [send]: 我是服务器
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: 举头望明月 -----> [send]: 低头思故乡
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: 床前明月光 -----> [send]: 疑是地上霜
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: 举头望明月 -----> [send]: 低头思故乡
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: 我是甲 -----> [send]: 我是乙
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: 我是周星驰 -----> [send]: 我是周润发
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: 举头望明月 -----> [send]: 低头思故乡
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: 床前明月光 -----> [send]: 疑是地上霜
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: 床前明月光 -----> [send]: 疑是地上霜
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: 床前明月光 -----> [send]: 疑是地上霜
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: Hi -----> [send]: Hi
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: 举头望明月 -----> [send]: 低头思故乡
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: 举头望明月 -----> [send]: 低头思故乡
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: 少小离家老大回 -----> [send]: 乡音无改鬓毛衰
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: 我是甲 -----> [send]: 我是乙
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: 床前明月光 -----> [send]: 疑是地上霜
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: 我是客户端 -----> [send]: 我是服务器
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: Hi -----> [send]: Hi
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: Hi -----> [send]: Hi
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: 我是周星驰 -----> [send]: 我是周润发
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: 我是周星驰 -----> [send]: 我是周润发
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: 举头望明月 -----> [send]: 低头思故乡
- 第 2 个客户端 [/127.0.0.1:1865]: [recieved]: Bye -----> [send]: Bye
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: Hi -----> [send]: Hi
- 第 2 个客户端 [/127.0.0.1:1865]: read finished. close socketChannel.
- 第 1 个客户端 [/127.0.0.1:1890]: [recieved]: Bye -----> [send]: Bye
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: 我是客户端 -----> [send]: 我是服务器
- 第 1 个客户端 [/127.0.0.1:1890]: read finished. close socketChannel.
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: 我是客户端 -----> [send]: 我是服务器
- 第 3 个客户端 [/127.0.0.1:1866]: [recieved]: Bye -----> [send]: Bye
- 第 3 个客户端 [/127.0.0.1:1866]: read finished. close socketChannel.
- 客户端的输出:
- [send] 1: 我是周星驰
- [send] 1: 少小离家老大回
- [Recieved]: 乡音无改鬓毛衰
- [send] 2: 床前明月光
- [Recieved]: 疑是地上霜
- [send] 3: 我是客户端
- [Recieved]: 我是服务器
- [Recieved]: 疑是地上霜
- [Recieved]: 我是周润发
- [Recieved]: 低头思故乡
- [send] 2: 举头望明月
- [Recieved]: 疑是地上霜
- [send] 3: 床前明月光
- [send] 1: 床前明月光
- [send] 2: 举头望明月
- [Recieved]: 低头思故乡
- [Recieved]: 我是乙
- [send] 4: 我是甲
- [Recieved]: 我是周润发
- [send] 5: 我是周星驰
- [send] 3: 床前明月光
- [send] 6: 床前明月光
- [send] 4: 举头望明月
- [Recieved]: 低头思故乡
- [send] 5: 床前明月光
- [Recieved]: 疑是地上霜
- [Recieved]: 疑是地上霜
- [Recieved]: 疑是地上霜
- [Recieved]: Hi
- [send] 4: Hi
- [Recieved]: 低头思故乡
- [send] 5: 举头望明月
- [Recieved]: 低头思故乡
- [Recieved]: 低头思故乡
- [send] 6: 举头望明月
- [send] 7: 少小离家老大回
- [s
发表评论
-
在JAVA中使用NIO进行网络编程(转)
2012-11-29 01:11 1059在JAVA中使用NIO进行网络编程 在JDK中,有 ... -
java分布式开发TCP/IP NIO无阻塞 Socket((基于消息方式实现系统间的通信) )(转)
2012-11-29 01:12 2在java中可以基于java.nio.c ... -
IO的阻塞与非阻塞、同步与异步以及Java网络IO交互方式(转)
2012-11-28 01:50 2315最近工作中,接触到 ... -
JAVANIO在Socket 通讯中的应用(转)
2012-11-28 01:40 1205JAVANIO在Socket 通讯 ... -
java分布式开发TCP/IP NIO无阻塞 Socket((基于消息方式实现系统间的通信) )(转)
2012-11-28 01:28 1215java分布式开发TCP/IP NIO无阻塞 So ... -
Java NIO 详解
2012-11-26 03:17 1052Java NIO 详解 2010-08- ... -
java IO NIO (转)
2012-11-24 02:03 3035(这一个章节将讲 ...
相关推荐
标题“nio.rar_NIO_NIO-socket_java nio_java 实例_java.nio”表明这个压缩包包含了一个关于Java NIO的实例,特别是关于NIO套接字(Socket)的编程示例。NIO套接字是Java NIO库中用于网络通信的关键组件,它们允许...
### Java NIO网络编程核心知识点解析 #### 非阻塞式Socket通信:Java NIO的革命性突破 从JDK 1.4版本开始,Java引入了NIO(Non-blocking I/O)API,这标志着Java网络编程的一个重大转折点。传统上,基于阻塞I/O的...
- NIO(非阻塞I/O)的`java.nio`包提供了更高效的Socket编程模型,适用于高并发场景。 总之,Java的Socket编程提供了强大的能力来构建网络应用程序。通过理解`Socket`和`ServerSocket`类,以及如何使用它们进行...
Java NIO(New Input/Output)是Java标准库提供的一种I/O模型,它与传统的 Blocking I/O(BIO)模型不同,NIO提供了非阻塞的读写方式,...对于理解和实践Java NIO在网络编程中的应用,这是一个非常有价值的参考实例。
总结来说,"NIO socket编程小例子 加法服务器"是一个很好的学习NIO网络编程的起点。通过这个实例,我们可以了解NIO Channel、Buffer和Selector的基本用法,以及如何构建一个简单的网络通信应用。对于任何想要提升...
Java Socket编程是网络编程的基础,它提供了在两个应用程序之间建立通信连接的能力。在这个场景中,我们讨论的是如何使用Java的Socket来实现文件上传功能,即从客户端将文件发送到服务器,然后保存到服务器的数据库...
本实例压缩包包含了一系列的Java Socket编程示例,旨在帮助开发者深入理解和掌握Socket编程的核心概念与技术。 Socket在Java中被定义为`java.net.Socket`类和`java.net.ServerSocket`类。Socket编程通常涉及两个...
在Java Socket编程中,我们还可以使用NIO(Non-blocking I/O)进行更高效的并发处理。NIO提供了选择器(Selector)和通道(Channel)等机制,可以在单线程下处理多个Socket连接,提高了系统资源的利用率。 另外,`...
在Java中,Socket编程是实现网络通信的基础,它提供了进程间通信的能力,使得两个相隔万里的计算机可以通过互联网进行数据交换。本篇文章将深入讲解如何通过三步学习Java Socket编程。 **第一步:理解Socket** ...
Socket通信在IT行业中是网络编程的基础,特别是在Java领域,它提供了服务器与客户端间进行数据交换的接口。NIO(Non-blocking I/O)是Java提供的一个高效I/O模型,相较于传统的IO模型,NIO具有非阻塞、多路复用等...
本书《Java网络编程实例:Java网络编程实例》显然聚焦于通过实际案例来教授这一核心技能。以下是一些主要的知识点,这些知识点通常会在书中详细讨论: 1. **TCP/IP协议基础**:首先,了解TCP/IP模型和协议栈是非常...
在Java编程领域,Socket是网络通信的基础,它允许两个或多个应用程序通过TCP/IP协议进行数据交换。本篇文章将深入探讨如何使用Java NIO(非阻塞I/O)来实现阻塞多线程通信,这对于高性能服务器端应用尤其重要。我们...
Java TCP/IP Socket编程是网络通信领域中的核心技术,它允许Java应用程序通过网络进行双向通信。在本教程中,我们将深入探讨这个主题,理解TCP/IP协议的基础,以及如何在Java中使用Socket进行实现。 TCP(传输控制...
1. **Java Socket编程**:Java的Socket类提供了基于TCP/IP协议的网络通信能力。通过ServerSocket创建服务器端,Socket创建客户端,两者建立连接后可以进行双向数据传输。例如,你可以构建一个简单的聊天应用或文件...
Java Socket编程是Java网络编程的重要组成部分,主要用于实现客户端与服务器之间的双向通信。在这个主题中,我们将深入探讨Java Socket的基本概念、工作原理以及如何在实际项目中应用。 首先,Socket是网络上的两个...
本文将深入探讨Java Socket编程的基础知识、关键概念以及如何在实践中应用。 一、Socket概述 Socket,也被称为套接字,是网络通信的端点,可以理解为两个应用程序之间的连接通道。在Java中,Socket类(java.net....
本教程将深入探讨Java Socket编程的基本概念、原理和实践应用。 一、Socket基本概念 Socket,也被称为套接字,是网络通信中的一个重要接口,它为两台计算机提供了一个低级别的、进程到进程的通信机制。在Java中,...
本文将通过一个对比实例,探讨一般Socket客户端与Mina NIO (Non-blocking I/O) Socket客户端的差异和特点,帮助开发者理解这两种技术在实际应用中的选择。 首先,普通Socket客户端基于BIO(Blocking I/O)模型,它...
本文将深入探讨基于Android的Socket编程实例,涵盖其基本概念、实现步骤以及常见问题。 **一、Socket基础知识** Socket在计算机网络中扮演着桥梁的角色,它允许两个网络应用程序之间建立连接并进行数据传输。在...
Java的Socket编程是Java网络编程的核心部分,它提供了在TCP/IP协议栈上进行通信的机制。Socket编程允许两台计算机通过Internet或局域网进行数据交换,是实现客户端-服务器模型的基础。本篇将深入探讨Java中的Socket...