- 浏览: 2662252 次
- 来自: 杭州
文章分类
- 全部博客 (1188)
- webwork (4)
- 网摘 (18)
- java (103)
- hibernate (1)
- Linux (85)
- 职业发展 (1)
- activeMQ (2)
- netty (14)
- svn (1)
- webx3 (12)
- mysql (81)
- css (1)
- HTML (6)
- apache (3)
- 测试 (2)
- javascript (1)
- 储存 (1)
- jvm (5)
- code (13)
- 多线程 (12)
- Spring (18)
- webxs (2)
- python (119)
- duitang (0)
- mongo (3)
- nosql (4)
- tomcat (4)
- memcached (20)
- 算法 (28)
- django (28)
- shell (1)
- 工作总结 (5)
- solr (42)
- beansdb (6)
- nginx (3)
- 性能 (30)
- 数据推荐 (1)
- maven (8)
- tonado (1)
- uwsgi (5)
- hessian (4)
- ibatis (3)
- Security (2)
- HTPP (1)
- gevent (6)
- 读书笔记 (1)
- Maxent (2)
- mogo (0)
- thread (3)
- 架构 (5)
- NIO (5)
- 正则 (1)
- lucene (5)
- feed (4)
- redis (17)
- TCP (6)
- test (0)
- python,code (1)
- PIL (3)
- guava (2)
- jython (4)
- httpclient (2)
- cache (3)
- signal (1)
- dubbo (7)
- HTTP (4)
- json (3)
- java socket (1)
- io (2)
- socket (22)
- hash (2)
- Cassandra (1)
- 分布式文件系统 (5)
- Dynamo (2)
- gc (8)
- scp (1)
- rsync (1)
- mecached (0)
- mongoDB (29)
- Thrift (1)
- scribe (2)
- 服务化 (3)
- 问题 (83)
- mat (1)
- classloader (2)
- javaBean (1)
- 文档集合 (27)
- 消息队列 (3)
- nginx,文档集合 (1)
- dboss (12)
- libevent (1)
- 读书 (0)
- 数学 (3)
- 流程 (0)
- HBase (34)
- 自动化测试 (1)
- ubuntu (2)
- 并发 (1)
- sping (1)
- 图形 (1)
- freemarker (1)
- jdbc (3)
- dbcp (0)
- sharding (1)
- 性能测试 (1)
- 设计模式 (2)
- unicode (1)
- OceanBase (3)
- jmagick (1)
- gunicorn (1)
- url (1)
- form (1)
- 安全 (2)
- nlp (8)
- libmemcached (1)
- 规则引擎 (1)
- awk (2)
- 服务器 (1)
- snmpd (1)
- btrace (1)
- 代码 (1)
- cygwin (1)
- mahout (3)
- 电子书 (1)
- 机器学习 (5)
- 数据挖掘 (1)
- nltk (6)
- pool (1)
- log4j (2)
- 总结 (11)
- c++ (1)
- java源代码 (1)
- ocr (1)
- 基础算法 (3)
- SA (1)
- 笔记 (1)
- ml (4)
- zokeeper (0)
- jms (1)
- zookeeper (5)
- zkclient (1)
- hadoop (13)
- mq (2)
- git (9)
- 问题,io (1)
- storm (11)
- zk (1)
- 性能优化 (2)
- example (1)
- tmux (1)
- 环境 (2)
- kyro (1)
- 日志系统 (3)
- hdfs (2)
- python_socket (2)
- date (2)
- elasticsearch (1)
- jetty (1)
- 树 (1)
- 汽车 (1)
- mdrill (1)
- 车 (1)
- 日志 (1)
- web (1)
- 编译原理 (1)
- 信息检索 (1)
- 性能,linux (1)
- spam (1)
- 序列化 (1)
- fabric (2)
- guice (1)
- disruptor (1)
- executor (1)
- logback (2)
- 开源 (1)
- 设计 (1)
- 监控 (3)
- english (1)
- 问题记录 (1)
- Bitmap (1)
- 云计算 (1)
- 问题排查 (1)
- highchat (1)
- mac (3)
- docker (1)
- jdk (1)
- 表达式 (1)
- 网络 (1)
- 时间管理 (1)
- 时间序列 (1)
- OLAP (1)
- Big Table (0)
- sql (1)
- kafka (1)
- md5 (1)
- springboot (1)
- spring security (1)
- Spring Boot (3)
- mybatis (1)
- java8 (1)
- 分布式事务 (1)
- 限流 (1)
- Shadowsocks (0)
- 2018 (1)
- 服务治理 (1)
- 设计原则 (1)
- log (0)
- perftools (1)
最新评论
-
siphlina:
课程——基于Python数据分析与机器学习案例实战教程分享网盘 ...
Python机器学习库 -
san_yun:
leibnitz 写道hi,我想知道,无论在92还是94版本, ...
hbase的行锁与多版本并发控制(MVCC) -
leibnitz:
hi,我想知道,无论在92还是94版本,更新时(如Puts)都 ...
hbase的行锁与多版本并发控制(MVCC) -
107x:
不错,谢谢!
Latent Semantic Analysis(LSA/ LSI)算法简介 -
107x:
不错,谢谢!
Python机器学习库
要写好java的网络编程并不只是new几个Socket,get一下InputStream,write to OutStream这么简单的。如何定义高效,稳定的协议,如何处理TCP协议中字节的发送和接收,编码,解码问题?socket缓冲区又是什么?本文讲讨论这些问题。
codec
TCP/IP 协议以字节的方式传输用户数据,并没有对其进行检查和修改。这个特点使应用程序可以非常灵活地对其传输的信息进行编码。TCP/IP 协议的唯一约束是,信息必须在块(chunks)中发送和接收,而块的长度必须是 8 位(一个字节)的倍数,因此,我们可以认为在 TCP/IP 协议中传输的信息是字节序列。鉴于此,我们可以进一步把传输的信息看作byte数组,每个数字的取值范围是 0 到 255。这与 8 位编码的二进制数值范围是一致的:00000000 代表 0,00000001 代表 1,00000010 代表 2,等等,最多到 11111111,即255。
基本整型
如我们所见,TCP 和 UDP 套接字使我们能发送和接收字节序列(数组) 即范围在 0-255,之间的整数。使用这个功能,我们可以对值更大的基本整型数据进行编码,不过发送者和接收者必须先在一些方面达成共识。一是要传输的每个整数的字节大小(size)。例如,Java程序中,int 数据类型由 32 位表示,因此,我们可以使用 4 个字节来传输任意的 int 型变量或常量;short 数据类型由 16 位表示,传输 short 类型的数据只需要两个字节;同理,传输64 位的 long 类型数据则需要 8 个字节。
下面我们考虑如何对一个包含了 4 个整数的序列进行编码:
- 一个 byte 型,
- 一个 short 型,
- 一个 int 型,
- 以及一个 long 型,
按照这个顺序从发送者传输到接收者。我们总共需要 15 个字节:第一个字节存放 byte 型数据,接下来两个字节存放 short 型数据,再后面 4 个字节存放 int 型数据,最后 8 个字节存放 long 型数据。如下图:
order of transmission:传输顺序
我们已经做好深入研究的准备了吗?未必。对于需要超过一个字节来表示的数据类型,我们必须知道这些字节的发送顺序。显然有两种选择:从整数的右边开始,由低位到高位地发送,即 little-endian 顺序;或从左边开始,由高位到低位发送,即 big-endian 顺序。考虑长整型数 123456787654321L,其 64 位(以十六进制形式)表示为 0x0000704885F926B1。
如果我们以 big-endian 顺序来传输这个整数,其字节的十进制数值序列就如下所示:
如果我们以 little-endian 顺序传输,则字节的十进制数组序列为:
关键的一点是,对于任何多字节的整数,发送者和接收者必须在使用 big-endian 顺序还是使用 little-endian 顺序上达成共识。如果发送者使用了 little-endian 顺序来发送上述整数,而接收者以 big-endian 顺序对其进行接收,那么接收者将取到错误的值,它会将这个 8 字节序列的整数解析成 12765164544669515776L。
发送者和接收者需要达成共识的最后一个细节是:所传输的数值是有符号的(signed)还是无符号的(unsigned)。Java 中的四种基本整型都是有符号的,它们的值以二进制补码的方式存储,这是有符号数值的常用表示方式。
正确存入到字节数组
为了清楚地展示需要做的步骤,我们将对如何使用"位操作(bit-diddling)"(移位和屏蔽)来显式编码进行介绍。这部分内容见:各种进制基础知识
DataOutputStream和DataInputStream
如你所见,上面的强制编码方法需要程序员做很多工作:要计算和命名每个数值的偏移量和大小,并要为编码过程提供合适的参数。如果没有将 encodeIntBigEndian()方法提出来作为一个独立的方法,情况会更糟。基于以上原因,强制编码方法是不推荐使用的,而且 Java 也提供了一些更加易用的内置机制。不过,值得注意的是强制编码方法也有它的优势,除了能够对标准的 Java 整型进行编码外,encodeIntegerBigEndian() 方法对 1 到8 字节的任何整数都适用--例如,如果愿意的话,你可以对一个 7 字节的整数进行编码。
构建本例中的消息的一个相对简单的方法是使用 DataOutputStream 类和ByteArrayOutputStream 类。DataOutputStream 类允许你将基本数据类型,如上述整型,写入一个流中:它提供了 writeByte(),writeShort(),writeInt(),以及 writeLong()方法。
ByteArrayOutputStream buf = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(buf); out.writeByte(byteVal); out.writeShort(shortVal); out.writeInt(intVal); out.writeLong(longVal); out.flush(); byte[] msg = buf.toByteArray();
处理BigInteger
对于基本整型,发送者和接收者必须在使用多大空间(字节数)来表示一个数值上达成共识。但是这又与使用 BigInteger 相矛盾,因为 BigInteger 可以是任意大小。一种解决方法是使用基于长度的Frame。
字符串和文本
对于字符串只要我们指定如何对要传输的文本进行编码,我们就几乎能发送其他任何类型的数据:先将其表示成文本形式,再对文本进行编码。首先得将文本视为由符号和字符(characters)组成。实际上每个 String 实例都对应了一个字符序列(数组,char[]类型)。一个字符在 Java 内部表示为一个整数。例如,字符"a",即字母"a"的符号,与整数 97 对应;字符"X"对应了 88,而符号"!"(感叹号)则对应了 33。
在一组符号与一组整数之间的映射称为编码字符集,或许你听说过 ASCII 编码字符集。Java 使用了一种称为 Unicode 的国际标准编码字符集来表示 char 型和 String 型值。Unicode 字符集将"世界上大部分的语言和符号"[ ]映射到整数 0 至 65535 之间,能更好地适用于国际化程序。例如,日文平假名中代表音节"o"的符号映射成了整数 12362。Unicode包含了 ASCII 码:每个 ASCII 码中定义的符号在 Unicode 中所映射整数与其在 ASCII 码中映射的整数相同。这就为 ASCII 与 Unicode 之间提供了一定程度的向后兼容性。
发送者与接收者必须在符号与整数的映射方式上达成共识,才能使用文本信息进行通信。对于每个整数值都比 255小的一小组字符,则不需要其他信息,因为其每个字符都能够作为一个单独的字节进行编码。对于可能使用超过一个字节的大整数的编码方式,就有多种方式在线路上对其进行编码。因此,发送者和接收者还需要对这些整数如何表示成字节序列统一意见,即编码方案(encodingscheme)。编码字符集和字符的编码方案结合起来称为字符集(charset,见 RFC 2278)。你也可以定义自己的字符集,但没有理由这样做,世界上已经有大量不同的标准(standardized)字符集在使用。Java 提供了对任意字符集的支持,而且每种实现都必须支持以下至少一种字符集:US-ASCII(ASCII 的另一个名字) ISO-8859-1,UTF-8,UTF-16BE,UTF-16LE,UTF-16。
组合输入输出流
Java 中与流相关的类可以组合起来从而提供强大的功能。例如,我们可以将一个 Socket实例的 OutputStream 包装在一个 BufferedOutputStream 实例中,这样可以先将字节暂时缓存在一起,然后再一次全部发送到底层的通信信道中,以提高程序的性能。我们还能再将这个BufferedOutputStream 实例包裹在一个 DataOutputStream 实例中,以实现发送基本数据类型的功能。以下是实现这种组合的代码
Socket socket = new Socket(server, port); DataOutputStream out = new DataOutputStream( new BufferedOutputStream(socket.getOutputStream()));
Framing
将数据转换成在线路上传输的格式只完成了一半工作,在接收端还必须将接收到的字节序列还原成原始信息。应用程序协议通常处理的是由一组字段组成的离散的信息,Framing解决了接收端如何定位消息的首尾位置的问题。无论信息是编码成了文本、多字节二进制数、或是两者的结合,应用程序协议必须指定消息的接收者如何确定何时消息已完整接收。这是一个没有处理好Frame的例子:socket的问题
如果一条完整的消息负载在一个 DatagramPacket 中发送,这个问题就变得很简单了:DatagramPacket 负载的数据有一个确定的长度,接收者能够准确地知道消息的结束位置。然而,如果通过 TCP 套接字来发送消息,情况将变得更复杂,因为 TCP 协议中没有消息边界的概念。如果一个消息中的所有字段都有固定的长度,同时每个消息又是由固定数量的字段组成的话,消息的长度就能够确定,接收者就可以简单地将消息长度对应的字节数读到一个 byte[]缓存区中。但是如果消息的长度是可变的(例如消息中包含了一些变长的文本字符串),我们事先就无法知道需要读取多少字节。
如果接收者试图从套接字中读取比消息本身更多的字节,将可能发生以下两种情况之一:如果信道中没有其他消息,接收者将阻塞等待,同时无法处理接收到的消息;如果发送者也在等待接收端的响应信息,则会形成死锁(deadlock); 另一方面,如果信道中还有其他消息,则接收者会将后面消息的一部分甚至全部读到第一条消息中去,这将产生一些协议错误。因此,在使用 TCP 套接字时,成帧就是一个非常重要的考虑因素。
主要有两个技术使接收者能够准确地找到消息的结束位置:
- 基于定界符(Delimiter-based):消息的结束由一个唯一的标记(unique marker,)指出,即发送者在传输完数据后显式添加的一个特殊字节序列。这个特殊标记不能在传输的数据中出现。
- 显式长度(Explicit length):在变长字段或消息前附加一个固定大小的字段,用来指示该字段或消息中包含了多少字节。
关于Frame的实现,参考Frame实现
由于 TCP 提供了一种可信赖的字节流服务,任何写入 Socket 的 OutputStream 的数据复本都必须保留,直到其在连接的另一端被成功接收。向OutputStream写数据并不意味着数据实际上已经被发送--它们只是被复制到了本地缓冲区。就算在Socket 的 OutputStream 上进行 flush()操作,也不能保证数据能够立即发送到信道。
在使用 TCP socket时需要记住的最重要一点是: 不能假设在连接的一端将数据写入输出流和在另一端从输入流读出数据之间有任何一致性。尤其是在发送端由单个输出流的 write()方法传输的数据,可能会通过另一端的多个输入流的 read()方法来获取;而一个 read()方法可能会返回多个 write()方法传输的数据。下面是一个例子:
byte[] buffer0 = new byte[1000]; byte[] buffer1 = new byte[2000]; byte[] buffer2 = new byte[5000]; ... Socket s = new Socket(destAddr, destPort); OutputStream out = s.getOutputStream(); ... out.write(buffer0); ... out.write(buffer1); ... out.write(buffer2); ... s.close();
发表评论
-
TCP滑动窗口
2014-06-04 16:10 853目前建立在TCP协议上的网络协议特别多,有telnet,ss ... -
TCP 滑动窗口协议
2013-11-07 18:36 5556TCP滑动窗口机制 我们可以大概看一下上图的模型 ... -
关于JAVA取本机ip的一些总结
2013-09-13 14:29 8232通常绑定本机ip地址 一般如下 I ... -
网络编程中Nagle算法和Delayed ACK的测试
2013-07-28 22:44 950网络编程中Nagle算法和Delayed ACK的测试 -
NFS-RPC框架优化过程(从37k到168k)
2013-07-18 22:17 1518NFS-RPC框架从编写之初,到现在为止(应该还会有些提升, ... -
Java程序员也应该知道的一些网络知识
2013-07-18 22:11 917对于需要编写网络通 ... -
深入理解JDBC的超时(timeout)设置
2013-06-26 15:27 6398真实案例:应用服务器在遭到DDos攻击后无法响应 在遭到 ... -
socket InputStream available()lock的问题
2013-03-28 18:45 3226在socket InputStream读取数据的问题记录一 ... -
socket参数对性能的影响
2013-03-26 14:51 1138今天发现线上一台机器的cilent端很慢,通过打点记录相关 ... -
socket InputStream读取数据的问题记录
2013-03-13 17:42 2433在用java写socket client的发现一个问题,如 ... -
java socket参数详解:TcpNoDelay
2012-12-14 19:28 1562TcpNoDelay=false,为启用nagle算法,也是默 ... -
python高性能网络框架Twisted介绍
2012-11-12 21:48 0什麼是Twisted Twisted是一 ... -
Reactor模式,或者叫反应器模式
2012-11-12 20:58 0原文:http://daimojingde ... -
libevent源码分析
2012-11-12 20:52 978原文参考: http://blog.csdn.net/spar ... -
java socket 参数说明
2012-11-10 16:19 1716Socket 的 I/O 调用可 ... -
一个自定义协议的例子
2012-11-10 14:54 3016public class VoteMsg { pr ... -
Socket send函数和recv函数详解
2012-11-09 12:17 1083int send( SOCKET s, c ... -
python struct
2012-11-07 14:03 788在使用python向java发送数据的时候一般是需要记录数据长 ... -
Frame实现
2012-11-06 21:01 875这里讨论Frame的实现问题。 -
Java网络编程--Socket编程
2012-11-03 23:07 1028原文:http://blog.sina.com.c ...
相关推荐
Java Socket 开发框架【susu】是一个自定义的、基于异步模式的网络通信解决方案,专为Java开发者设计。在Java编程中,Socket是实现客户端与服务器之间通信的基础,它提供了进程间的网络通信能力。而将Socket编程封装...
Mina和Socket是两种常见的网络通信框架和技术,它们在Java编程环境中被广泛使用。本篇文章将深入探讨如何使用Mina与Socket实现通信,并提供客户端和服务端的实现代码概述。 Mina(全称“MINA: Minimalistic ...
在源代码中,你可能会看到自定义的 Codec 类,它们负责将应用程序对象与网络字节流之间进行转换。 8. **事件处理** Mina 的事件驱动模型允许开发者对特定的网络事件(如连接建立、数据到达、连接关闭等)做出响应...
使用开源技术搭建的TCP调试程序,Apache Mina + Swing + Apache commons-codec
import java.net.Socket; public class Server { public Server() { } public void listen() throws IOException { ServerSocket server = new ServerSocket(8002); while (true) { try { ...
12. **SimpleServer和Client**: 这可能是指简单的TCP或HTTP服务器和客户端实现,比如使用`java.net.ServerSocket`和`java.net.Socket`进行网络通信。 以上就是对标题和描述中提到的Java工具类的详细说明。这些工具...
SocketDebug是一款基于Apache MINA框架、Swing图形用户界面库以及Apache Commons Codec库开发的TCP调试工具。这个工具主要用于帮助开发者在TCP网络通信过程中进行数据包的捕获、分析和发送,是网络编程和调试过程中...
java多线程tcp socket server源码@Netty 笔记 1. 内蒂 网络应用框架 特征 设计 支持多种传输类型 事件模型 高度可定制的线程模型 表现 高吞吐量,低延迟 更少的资源消耗 最小化内存拷贝 安全SSL/TLS 支持 建筑学 核 ...
开发者可以自定义Codec实现,将应用级别的消息转换为字节流,反之亦然。这对于处理各种数据格式,如XML、JSON或二进制协议,非常有用。 除了基本的网络通信功能,Mina还提供了许多附加特性,如心跳检测、会话管理、...
SocketConnector连接器是一种在Java编程环境中广泛使用的网络通信组件,主要用于建立基于TCP/IP协议的Socket连接。这个连接器是Java的Netty框架的一部分,Netty是一个高性能、异步事件驱动的网络应用程序框架,用于...
本项目可能是通过Java的网络API(如Socket和ServerSocket类)来实现客户端与服务器端之间的数据交换,允许用户进行实时对话。 【描述】: 根据给出的链接,这是一个关于Java聊天程序的博客文章,但具体内容未提供...
5. SSL/TLS协议:在Java中,通过JSSE(Java Secure Socket Extension)实现SSL(Secure Sockets Layer)和TLS(Transport Layer Security)协议,用于创建安全的网络连接,确保数据在网络中的传输是加密的。...
NIO (Non-blocking Input/Output) 是Java中的一种I/O模型,与传统的 blocking I/O 相比,它提供了更高效的数据处理方式。在传统的Socket编程中,每个连接都会创建一个新的线程进行处理,这在连接数量较少时是可行的...
【学员信息管理系统】是一个基于Java开发的项目,旨在帮助学习者深入理解Java编程语言,并实践在实际项目中的应用。这个系统包含了对学员信息的基本操作,如增加、删除、修改和查询,是学习Java编程和软件工程实践的...
为了实现安全的数据传输,比如HTTPS,我们可以使用JSSE(Java Secure Socket Extension),它包含了SSL/TLS协议的支持。在设计加密模块时,需要考虑以下几点:选择合适的加密算法、密钥长度、以及加密模式(如CBC、...
标题中的“netty socketio全部包jar”指的是一个包含了Netty和SocketIO相关库的Java归档(JAR)文件集合。这些文件是为构建基于Web的通信解决方案而准备的,特别是针对实时通信需求。 Netty是一个高性能、异步事件...
6. 网络编程:Java提供了Socket、ServerSocket等类,用于实现TCP/IP网络通信,还有URL、URLConnection等类支持HTTP和其他网络协议。 7. 反射(Reflection):允许运行时检查类、接口、字段和方法的信息,以及动态...
3. **Java Socket**: 掌握Java Socket编程,理解网络通信的基本原理。 4. **Java线程及并发库**: 熟练使用Java中的线程控制和并发工具,如`java.util.concurrent`包下的类和接口。 #### 架构与组件 Mina的核心架构...
JNI层的`create`函数调用C/C++标准库中的`::socket`函数创建socket,并将socket号通过`SetIntField`方法传递回Java层的RtpStream实例。 总结来说,Android源码中的VoIP实现涉及了RTP协议的详细处理,包括流的创建、...
这些Transport实现了底层的I/O操作,如创建socket、发送和接收数据,将复杂的网络编程简化为对Channel的操作。 **Bootstrap引导** Bootstrap是Netty的启动配置类,用于配置服务器端或客户端的启动参数,如...