- 浏览: 2652146 次
- 来自: 杭州
文章分类
- 全部博客 (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机器学习库
public class VoteMsg { private boolean isInquiry; // true if inquiry; false if vote private boolean isResponse;// true if response from server private int candidateID; // in [0,1000] private long voteCount; // nonzero only in response public static final int MAX_CANDIDATE_ID = 1000; public VoteMsg(boolean isResponse, boolean isInquiry, int candidateID, long voteCount) throws IllegalArgumentException { // check invariants if (voteCount != 0 && !isResponse) { throw new IllegalArgumentException("Request vote count must be zero"); } if (candidateID < 0 || candidateID > MAX_CANDIDATE_ID) { throw new IllegalArgumentException("Bad Candidate ID: " + candidateID); } if (voteCount < 0) { throw new IllegalArgumentException("Total must be >= zero"); } this.candidateID = candidateID; this.isResponse = isResponse; this.isInquiry = isInquiry; this.voteCount = voteCount; } public void setInquiry(boolean isInquiry) { this.isInquiry = isInquiry; } public void setResponse(boolean isResponse) { this.isResponse = isResponse; } public boolean isInquiry() { return isInquiry; } public boolean isResponse() { return isResponse; } public void setCandidateID(int candidateID) throws IllegalArgumentException { if (candidateID < 0 || candidateID > MAX_CANDIDATE_ID) { throw new IllegalArgumentException("Bad Candidate ID: " + candidateID); } this.candidateID = candidateID; } public int getCandidateID() { return candidateID; } public void setVoteCount(long count) { if ((count != 0 && !isResponse) || count < 0) { throw new IllegalArgumentException("Bad vote count"); } voteCount = count; } public long getVoteCount() { return voteCount; } public String toString() { String res = (isInquiry ? "inquiry" : "vote") + " for candidate " + candidateID; if (isResponse) { res = "response to " + res + " who now has " + voteCount + " vote(s)"; } return res; } }
import java.io.IOException; public interface VoteMsgCoder { byte[] toWire(VoteMsg msg) throws IOException; VoteMsg fromWire(byte[] input) throws IOException; }
基于文本的表示方法
该协议指定使用 US-ASCII 字符集对文本进行编码。消息的开头是一个所谓的"魔术字符串",即一个字符序列,用于接收者快速将投票协议的消息和网络中随机到来的垃圾消息区分开。投票/查询布尔值被编码成字符形式,'v'表示投票消息,'i'表示查询消息。消息的状态,即是否为服务器的响应,由字符'R'指示。状态标记后面是候选人 ID,其后跟的是选票总数,它们都编码成十进制字符串。
VoteMsgTextCoder 类提供了一种基于文本的 VoteMsg 编码方法。
VoteMsgTextCoder.java
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Scanner; public class VoteMsgTextCoder implements VoteMsgCoder { /* * Wire Format "VOTEPROTO" <"v" | "i"> [<RESPFLAG>] <CANDIDATE> [<VOTECNT>] * Charset is fixed by the wire format. */ // Manifest constants for encoding public static final String MAGIC = "Voting"; public static final String VOTESTR = "v"; public static final String INQSTR = "i"; public static final String RESPONSESTR = "R"; public static final String CHARSETNAME = "US-ASCII"; public static final String DELIMSTR = " "; public static final int MAX_WIRE_LENGTH = 2000; public byte[] toWire(VoteMsg msg) throws IOException { String msgString = MAGIC + DELIMSTR + (msg.isInquiry() ? INQSTR : VOTESTR) + DELIMSTR + (msg.isResponse() ? RESPONSESTR + DELIMSTR : "") + Integer.toString(msg.getCandidateID()) + DELIMSTR + Long.toString(msg.getVoteCount()); byte data[] = msgString.getBytes(CHARSETNAME); return data; } public VoteMsg fromWire(byte[] message) throws IOException { ByteArrayInputStream msgStream = new ByteArrayInputStream(message); Scanner s = new Scanner(new InputStreamReader(msgStream, CHARSETNAME)); boolean isInquiry; boolean isResponse; int candidateID; long voteCount; String token; try { token = s.next(); if (!token.equals(MAGIC)) { throw new IOException("Bad magic string: " + token); } token = s.next(); if (token.equals(VOTESTR)) { isInquiry = false; } else if (!token.equals(INQSTR)) { throw new IOException("Bad vote/inq indicator: " + token); } else { isInquiry = true; } token = s.next(); if (token.equals(RESPONSESTR)) { isResponse = true; token = s.next(); } else { isResponse = false; } // Current token is candidateID // Note: isResponse now valid candidateID = Integer.parseInt(token); if (isResponse) { token = s.next(); voteCount = Long.parseLong(token); } else { voteCount = 0; } } catch (IOException ioe) { throw new IOException("Parse error..."); } return new VoteMsg(isResponse, isInquiry, candidateID, voteCount); } }
fromWire()方法首先检查"魔术"字符串,如果在消息最前面没有魔术字符串,则抛出一个异常。这里说明了在实现协议时非常重要的一点:永远不要对从网络来的任何输入进行任何假设。你的程序必须时刻为任何可能的输入做好准备,并能够很好地对其进行处理。在这个例子中,如果接收到的不是期望的消息,fromWire()方法将抛出一个异常,否则,就使用 Scanner 实例,根据空白符一个一个地获取字段。注意,消息的字段数与其是请求消息(由客户端发送)还是响应消息(由服务器发送)有关。如果输入流提前结束或格式错误,fromWire()方法将抛出一个异常。
二进制表示方法
下面我们将展示另一种对投票协议消息进行编码的方法。与基于文本的格式相反,二进制格式使用固定大小的消息。每条消息由一个特殊字节开始,该字节的最高六位为一个"魔术"值 010101。这一点少量的冗余信息为接收者收到适当的投票消息提供了一定程度的保证。该字节的最低两位对两个布尔值进行了编码。消息的第二个字节总是 0,第三、第四个字节包含了 candidateID 值。只有响应消息的最后 8 个字节才包含了选票总数信息。
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; /* Wire Format * 1 1 1 1 1 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | Magic |Flags| ZERO | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | Candidate ID | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | | * | Vote Count (only in response) | * | | * | | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ public class VoteMsgBinCoder implements VoteMsgCoder { // manifest constants for encoding public static final int MIN_WIRE_LENGTH = 4; public static final int MAX_WIRE_LENGTH = 16; public static final int MAGIC = 0x5400; public static final int MAGIC_MASK = 0xfc00; public static final int MAGIC_SHIFT = 8; public static final int RESPONSE_FLAG = 0x0200; public static final int INQUIRE_FLAG = 0x0100; public byte[] toWire(VoteMsg msg) throws IOException { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(byteStream); // converts ints short magicAndFlags = MAGIC; if (msg.isInquiry()) { magicAndFlags |= INQUIRE_FLAG; } if (msg.isResponse()) { magicAndFlags |= RESPONSE_FLAG; } out.writeShort(magicAndFlags); // We know the candidate ID will fit in a short: it's > 0 && < 1000 out.writeShort((short) msg.getCandidateID()); if (msg.isResponse()) { out.writeLong(msg.getVoteCount()); } out.flush(); byte[] data = byteStream.toByteArray(); return data; } public VoteMsg fromWire(byte[] input) throws IOException { // sanity checks if (input.length < MIN_WIRE_LENGTH) { throw new IOException("Runt message"); } ByteArrayInputStream bs = new ByteArrayInputStream(input); DataInputStream in = new DataInputStream(bs); int magic = in.readShort(); if ((magic & MAGIC_MASK) != MAGIC) { throw new IOException("Bad Magic #: " + ((magic & MAGIC_MASK) >> MAGIC_SHIFT)); } boolean resp = ((magic & RESPONSE_FLAG) != 0); boolean inq = ((magic & INQUIRE_FLAG) != 0); int candidateID = in.readShort(); if (candidateID < 0 || candidateID > 1000) { throw new IOException("Bad candidate ID: " + candidateID); } long count = 0; if (resp) { count = in.readLong(); if (count < 0) { throw new IOException("Bad vote count: " + count); } } // Ignore any extra bytes return new VoteMsg(resp, inq, candidateID, count); } }
发送和接收
通过流发送消息非常简单,只需要创建消息,调用 toWire()方法,添加适当的成帧信息,再写入流。当然,接收消息就要按照相反的顺序执行。这个过程适用于 TCP 协议,而对于 UDP 协议,不需要显式地成帧,因为 UDP 协议中保留了消息的边界信息,
首先我们实现一个投票服务器所用到的服务。当接收到投票消息时,投票服务器将调用 VoteService 类的 handleRequest() 方法对请求进行处理。
import java.util.HashMap; import java.util.Map; public class VoteService { // Map of candidates to number of votes private Map<Integer, Long> results = new HashMap<Integer, Long>(); public VoteMsg handleRequest(VoteMsg msg) { if (msg.isResponse()) { // If response, just send it back return msg; } msg.setResponse(true); // Make message a response // Get candidate ID and vote count int candidate = msg.getCandidateID(); Long count = results.get(candidate); if (count == null) { count = 0L; // Candidate does not exist } if (!msg.isInquiry()) { results.put(candidate, ++count); // If vote, increment count } msg.setVoteCount(count); return msg; } }
import java.io.OutputStream; import java.net.Socket; public class VoteClientTCP { public static final int CANDIDATEID = 888; public static void main(String args[]) throws Exception { if (args.length != 2) { // Test for correct # of args throw new IllegalArgumentException("Parameter(s): <Server> <Port>"); } String destAddr = args[0]; // Destination address int destPort = Integer.parseInt(args[1]); // Destination port Socket sock = new Socket(destAddr, destPort); OutputStream out = sock.getOutputStream(); // Change Bin to Text for a different framing strategy VoteMsgCoder coder = new VoteMsgBinCoder(); // Change Length to Delim for a different encoding strategy Framer framer = new LengthFramer(sock.getInputStream()); // Create an inquiry request (2nd arg = true) VoteMsg msg = new VoteMsg(false, true, CANDIDATEID, 0); byte[] encodedMsg = coder.toWire(msg); // Send request System.out.println("Sending Inquiry (" + encodedMsg.length + " bytes): "); System.out.println(msg); framer.frameMsg(encodedMsg, out); // Now send a vote msg.setInquiry(false); encodedMsg = coder.toWire(msg); System.out.println("Sending Vote (" + encodedMsg.length + " bytes): "); framer.frameMsg(encodedMsg, out); // Receive inquiry response encodedMsg = framer.nextMsg(); msg = coder.fromWire(encodedMsg); System.out.println("Received Response (" + encodedMsg.length + " bytes): "); System.out.println(msg); // Receive vote response msg = coder.fromWire(framer.nextMsg()); System.out.println("Received Response (" + encodedMsg.length + " bytes): "); System.out.println(msg); sock.close(); } }
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class VoteServerTCP { public static void main(String args[]) throws Exception { if (args.length != 1) { // Test for correct # of args throw new IllegalArgumentException("Parameter(s): <Port>"); } int port = Integer.parseInt(args[0]); // Receiving Port ServerSocket servSock = new ServerSocket(port); // Change Bin to Text on both client and server for different encoding VoteMsgCoder coder = new VoteMsgBinCoder(); VoteService service = new VoteService(); while (true) { Socket clntSock = servSock.accept(); System.out.println("Handling client at " + clntSock.getRemoteSocketAddress()); // Change Length to Delim for a different framing strategy Framer framer = new LengthFramer(clntSock.getInputStream()); try { byte[] req; while ((req = framer.nextMsg()) != null) { System.out.println("Received message (" + req.length + " bytes)"); VoteMsg responseMsg = service.handleRequest(coder.fromWire(req)); framer.frameMsg(coder.toWire(responseMsg), clntSock.getOutputStream()); } } catch (IOException ioe) { System.err.println("Error handling client: " + ioe.getMessage()); } finally { System.out.println("Closing connection"); clntSock.close(); } } } }
发表评论
-
TCP滑动窗口
2014-06-04 16:10 843目前建立在TCP协议上的网络协议特别多,有telnet,ss ... -
TCP 滑动窗口协议
2013-11-07 18:36 5541TCP滑动窗口机制 我们可以大概看一下上图的模型 ... -
关于JAVA取本机ip的一些总结
2013-09-13 14:29 8227通常绑定本机ip地址 一般如下 I ... -
网络编程中Nagle算法和Delayed ACK的测试
2013-07-28 22:44 946网络编程中Nagle算法和Delayed ACK的测试 -
NFS-RPC框架优化过程(从37k到168k)
2013-07-18 22:17 1515NFS-RPC框架从编写之初,到现在为止(应该还会有些提升, ... -
Java程序员也应该知道的一些网络知识
2013-07-18 22:11 912对于需要编写网络通 ... -
深入理解JDBC的超时(timeout)设置
2013-06-26 15:27 6333真实案例:应用服务器在遭到DDos攻击后无法响应 在遭到 ... -
socket InputStream available()lock的问题
2013-03-28 18:45 3213在socket InputStream读取数据的问题记录一 ... -
socket参数对性能的影响
2013-03-26 14:51 1108今天发现线上一台机器的cilent端很慢,通过打点记录相关 ... -
socket InputStream读取数据的问题记录
2013-03-13 17:42 2409在用java写socket client的发现一个问题,如 ... -
java socket参数详解:TcpNoDelay
2012-12-14 19:28 1557TcpNoDelay=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 970原文参考: http://blog.csdn.net/spar ... -
java socket 参数说明
2012-11-10 16:19 1707Socket 的 I/O 调用可 ... -
Socket send函数和recv函数详解
2012-11-09 12:17 1073int send( SOCKET s, c ... -
python struct
2012-11-07 14:03 784在使用python向java发送数据的时候一般是需要记录数据长 ... -
Frame实现
2012-11-06 21:01 867这里讨论Frame的实现问题。 -
Java Socket codec
2012-11-06 20:08 1154要写好java的网络编程并 ... -
Java网络编程--Socket编程
2012-11-03 23:07 1022原文:http://blog.sina.com.c ...
相关推荐
接下来,我们通过一个具体的例子来详细解释如何使用`struct`模块来实现一个简单的自定义协议。 ##### 3.1 定义异常类 首先,我们需要定义一个异常类`E`,用于在协议解析过程中遇到错误时抛出异常: ```python ...
在Netty协议栈中,TCP自定义通讯协议可以被实现为一个ChannelHandler,处理各种消息类型的解析和编码。字节传输过程中,由于采用UTF-8字符集和网络字节序(Big-Endian),确保了跨平台的兼容性。此外,心跳机制的...
总的来说,Mina自定义协议通信示例是一个很好的学习资源,它涵盖了网络编程的核心概念,如事件驱动模型、非阻塞I/O和自定义编解码。通过深入理解并实践这个示例,开发者能更好地掌握Mina框架,并有能力解决复杂网络...
在IT行业中,网络通信是至关重要的一个领域,而Socket编程是构建网络应用程序的基础。本教程主要聚焦于如何使用C语言实现基于Socket的自定义协议通信,涵盖了客户端和服务端的实现。我们将深入理解Socket编程的基本...
标题和描述中提到的自定义协议,其结构以特定的起始标识符0x5A 0xA5开始,然后紧接着一个字节指示后续数据的长度,这种设计具有明确的数据边界和简单的解析规则。 首先,0x5A和0xA5是十六进制数,它们组合在一起...
首先,自定义协议是Objective-C和Swift中的一个重要特性,它允许我们定义一套方法和属性,然后让不同的类去遵循(Adopt)这些协议。这样,遵循协议的类就必须实现协议中定义的所有方法,从而实现特定的功能。创建...
这通常涉及到在`HKEY_CLASSES_ROOT`下创建一个新的键,键名就是你的自定义协议,例如`myapp`。然后,在这个键下创建一个`Default`字符串值,指向你的应用程序路径,例如`"C:\Program Files\MyApp\MyApp.exe"`。 2. ...
这个"cordova ios 自定义插件例子"是一个适合新手入门的学习资源,它会引导你了解如何为 iOS 平台创建和使用自定义 Cordova 插件。 在 Cordova 中,插件是连接 JavaScript 世界与原生平台代码的桥梁。它们使你能...
在“自定义协议解析demo”中,我们可能会先定义一个结构体来存储协议的数据格式,比如: ```c typedef struct { char header[8]; // 协议头 int length; // 数据长度 char* data; // 数据体 } CustomProtocol; `...
自定义协议意味着我们需要为ns2提供一个新的模块,该模块将处理特定的传输层操作,比如在这个例子中,是UDP(User Datagram Protocol)的定制版本。 1. **创建自定义协议类**:在ns2中,我们首先需要定义一个新的...
SuperSocket是一个轻量级且高度可扩展的网络通信框架,适用于开发各种类型的TCP服务,如聊天应用、游戏服务器或者数据传输服务。通过自定义命令行协议,我们可以更好地管理和解析客户端发送的数据,实现更高效、更...
首先,自定义一个UITableViewCell类。在Swift中,你可以创建一个新的Swift文件,例如`CustomTableViewCell.swift`,并继承自`UITableViewCell`。在这个类中,你可以定义你需要的UI元素,比如UILabel、UIImageView或...
要创建自定义事件,你需要编写一个ESL(Event Socket Library)事件处理器。通过这个库,你可以发送和接收事件,与FreeSwitch进行交互。事件的定义通常在C语言的源代码文件中完成,包括事件名称、数据结构和处理函数...
总的来说,“CustomProtocolHandlerSample_Firefox”提供了一个很好的起点,对于想要在Firefox中实现自定义协议处理的开发者来说,这是一个宝贵的参考资料。通过学习和实践,开发者不仅可以提升技能,还能为用户提供...
在项目"JniText"中,我们可以期待看到一个结合了JNI本地函数调用和自定义开关控件的示例。这个项目可以帮助开发者了解如何将C/C++代码与Java代码相结合,以及如何设计和实现自定义UI元素。对于想要深入学习Android ...
- 在这个例子中,自定义协议由一系列预定义的字符串组成,这些字符串代表了认证过程的不同阶段。这种方式简单但有限,实际应用中可能需要更复杂的数据结构和加密机制来确保安全性和可靠性。 6. **错误处理和重试...
此解决方案包含4个工程 1)工程 yanzisoft.COMFTP 串口与以太网 文件传送协议(编译生成dll库文件:yanzisoft.COMFTP.dll) 2)工程 CECOMDebug 测试yanzisoft.COMFTP.dll在嵌入式wince系统测式使用的例子 3)工程 ...
例如,我们的自定义过滤器在验证成功后可以创建一个`Authentication`对象并将其设置到`SecurityContextHolder`中。 ```java public class CustomAuthenticationFilter extends GenericFilterBean { private final ...