基础准备首先需要明白数据传输的底层实现机制,在上一章中有详细的介绍,我们提到了 SendQ 和 RecvQ 缓冲队列,这两个缓冲区的容量在具体实现时会受一定的限制,虽然它们使用的实际内存大小会动态地增长和收缩,但还是需要一个硬性的限制,以防止行为异常的程序所控制的单一 TCP 连接将系统的内存全部消耗。
底层数据结构如果不理解套接字的具体实现所关联的数据结构和底层协议的工作细节,就很难抓住网络编程的精妙之处,对于 TCP 套接字来说,更是如此。套接字所关联的底层的数据结构集包含了特定 Socket 实例所关联的信息。比附,套接字结构除其他信息外还包含:该套接字所关联的本地和远程互联网地址和端口号。
NIO 主要原理及使用NIO 采取通道(Channel)和缓冲区(Buffer)来传输和保存数据,它是非阻塞式的 I/O,即在等待连接、读写数据(这些都是在一线程以客户端的程序中会阻塞线程的操作)的时候,程序也可以做其他事情,以实现线程的异步操作。
简介Java NIO 从 JDK1.4 引入,它提供了与标准 IO 完全不同的工作方式。NIO 包(java.nio.*)引入了四个关键的抽象数据类型,它们共同解决传统的 I/O 类中的一些问题。Buffer:它是包含数据且用于读写的线形表结构。其中还提供了一个特殊类用于内存映射文件的 I/O 操作。Charset:它提供 Unicode 字符串影射到字节序列以及逆影射的操作。
示例在第一章中,作者给出了一个 TCP Socket 通信的例子——反馈服务器,即服务器端直接把从客户端接收到的数据原原本本地反馈回去。示例客户端代码如下:import java.net.Socket; import java.net.SocketException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;
线程池在 Java TCP Socket 编程这篇文章中,服务器端采用的实现方式是:一个客户端对应一个线程。但是,每个新线程都会消耗系统资源:创建一个线程会占用 CPU 周期,而且每个线程都会建立自己的数据结构(如,栈),也要消耗系统内存,另外,当一个线程阻塞时,JVM 将保存其状态,选择另外一个线程运行,并在上下文转换(context switch)时恢复阻塞线程的状态。
在传输消息时,用 Java 内置的方法和工具确实很用,如:对象序列化,RMI 远程调用等。但有时候,针对要传输的特定类型的数据,实现自己的方法可能更简单、容易或有效。下面给出一个实现了自定义构建和解析协议消息的 Demo。该例子是一个简单的投票协议。这里,一个客户端向服务器发送一个请求消息,消息中包含了一个候选人的 ID,范围在 0~1000。
程序间达成的某种包含了信息交换的形式和意义的共识称为协议,用来实现特定应用程序的协议叫做应用程序协议。大部分应用程序协议是根据由字段序列组成的离散信息定义的,其中每个字段中都包含了一段以位序列编码(即二进制字节编码,也可以使用基于文本编码的方式,但常用协议如:TCP、UDP、HTTP 等在传输数据时,都是以位序列编码的)的特定信息。
UDP 的 Java 支持UDP 协议提供的服务不同于 TCP 协议的端到端服务,它是面向非连接的,属不可靠协议,UDP 套接字在使用前不需要进行连接。实际上,UDP 协议只实现了两个功能:在 IP 协议的基础上添加了端口;对传输过程中可能产生的数据错误进行了检测,并抛弃已经损坏的数据。
TCP 的 Java 支持协议相当于相互通信的程序间达成的一种约定,它规定了分组报文的结构、交换方式、包含的意义以及怎样对报文所包含的信息进行解析,TCP/IP 协议族有 IP 协议、TCP 协议和 UDP 协议。现在 TCP/IP 协议族中的主要 socket 类型为流套接字(使用 TCP 协议)和数据报套接字(使用 UDP 协议)。 TCP 协议提供面向连接的服务,通过它建立的是可靠地连接。
协议简介协议相当于相互通信的程序间达成的一种约定,它规定了分组报文的结构、交换方式、包含的意义以及怎样对报文所包含的信息进行解析。TCP/IP 协议族有 IP 协议、TCP 协议和 UDP 协议。TCP 协议和 UDP 协议使用的地址叫做端口号,用来区分同一主机上的不同应用程序。
本书由浅入深,全面讲解了 Java Socket 方面的网络编程知识,包括 TCP、UDP、自定义协议、协议成帧、解析、多线程、线程池、NIO、死锁、Socket 套接字的底层实现机制等。通过本书的学习,能够让读者了解通过 Socket 技术实现服务器与客户端的通信,全面了解 Java 网络编程中的技术难点。适用人群本书适合作为 Java Socket 编程的入门教程,可供从事网络编程的技术人员参考。
以下是一些建议,当你的代码库日益壮大或者应用需要规划时可以参考。阅读源代码Werkzeug ( WSGI )和 Jinja (模板)是两个被广泛使用的工具,而 Flask 起源就是 用于展示如何基于这两个工具创建你自己的框架。随着不断地开发, Flask 被越来越多 的人认可了。当你的代码库日益壮大时,不应当仅仅是使用 Flask ,而更应当理解它。 阅读 Flask 的源代码吧。
Flask 应用可以采用多种方式部署。在开发时,你可以使用内置的服务器,但是在生产环境 下你就应当选择功能完整的服务器。下面为你提供几个可用的选择。除了下面提到的服务器之外,如果你使用了其他的 WSGI 服务器,那么请阅读其文档中与使用 WSGI 应用相关的部分。因为 Flask 应用对象的实质就是一个 WSGI 应用。
有一些东西是大多数网络应用都会用到的。比如许多应用都会使用关系型数据库和用户 验证,在请求之前连接数据库并得到当前登录用户的信息,在请求之后关闭数据库连接。更多用户贡献的代码片断和方案参见 Flask 代码片断归档 。
New in version 0.3.喜欢 Python 的原因之一是交互式的 shell ,它可以让你实时运行 Python 命令,并且立即得到结果。 Flask 本身不带交互 shell ,因为它不需要特定的前期设置,只要在 shell 中导入你的应用就可以开始使用了。有些辅助工具可以让你在 shell 中更舒服。在交互终端中最大的问题是你不会像浏览器一样触发一个请求,这就意味着无法使用 g 和 request 等对象。
Flask 扩展以各种方式扩展了 Flask 的功能,比如增强对数据库的支持等等。查找扩展Flask 扩展都列在 Flask 扩展注册 中,并且可以使用 easy_install 或 pip 下载。如果你把一个扩展作为依赖添加到你的 requirements.rst 或 setup.py 文件,那么它们可以使用一个简单的命令安装或随着应用一起安装。使用扩展扩展一般都有说明如何使用的文档,这些文档应该和扩展一起发行。
New in version 0.7.为了在一个或多个应用中,使应用模块化并且支持常用方案, Flask 引入了 蓝图 概念。蓝图可以极大地简化大型应用并为扩展提供集中的注册入口。 Blueprint 对象与 Flask 应用对象的工作方式类似,但不是一个真正 的应用。它更像一个用于构建和扩展应用的 蓝图 。为什么使用蓝图?Flask 中蓝图有以下用途:把一个应用分解为一套蓝图。
本文讲述 Flask 0.7 版本的运行方式,与旧版本的运行方式基本相同,但也有一些细微的 差别。建议你在阅读本文之前,先阅读应用环境 。深入本地环境假设有一个工具函数,这个函数返回用户重定向的 URL (包括 URL 的 next 参数、 或 HTTP 推荐和索引页面):from flask import request, url_fordef redirect_url(): return request.args.
New in version 0.9.Flask 的设计思路之一是代码有两种不同的运行“状态”。一种是“安装”状态,从 Flask 对象被实例化后开始,到第一个请求到来之前。在这种状态下,以下规则 成立:可以安全地修改应用对象。还没有请求需要处理。没有应用对象的引用,因此无法修改应用对象。相反,在请求处理时,以下规则成立:当请求活动时,本地环境对象 ( flask.
关注时代Java