状态机详解(一段式、二段式、三段式)

一、有限状态机FSM(Finite State Machine)

  • 组成元素

        输入、状态、状态转移条件、输出。

  • 可以分为两类

        Mealy状态机:时序逻辑的输出不仅取决于当前状态,还与输入有关;

        Moore状态机:时序逻辑的输出只与当前状态有关。

  • 描述方式

        ① 状态转移图:设计分析时使用,工具自动翻译的代码效率不高,适合规模小的设计;对于大规模设计,HDL更好;

        ② 状态转移表;

        ③ HDL描述。

  • 设计步骤

        ① 逻辑抽象,得到状态转移图:确定输入、输出、状态变量、画状态转移图;

        ② 状态简化,得到最简的状态转移图:合并等价状态(它们的输入相同,转换到的次态和输出也相同的两个或两个以上的状态);

        ③ 状态编码:binary、gray、one-hot编码方式;

        ④ 用HDL描述。

二、Coding Style

  • 一段式

        只有一个always block,把所有的逻辑(输入、输出、状态)都在一个always block的时序逻辑中实现。这种写法看起来很简洁,但是不利于维护,如果状态复杂一些就很容易出错,不推荐这种方法

        在简单的状态机可以使用。

  • 二段式

        有两个always block,把时序逻辑和组合逻辑分隔开来。时序逻辑里进行当前状态和下一状态的切换,组合逻辑实现各个输入、输出以及状态判断。这种写法不仅便于阅读、理解、维护,而且利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。在两段式描述中,当前状态的输出用组合逻辑实现,可能存在竞争和冒险,产生毛刺

        要求对状态机的输出用寄存器打一拍,但很多情况不允许插入寄存器节拍,此时使用三段式描述。其优势在于能够根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而不需要额外插入时钟节拍。

  • 三段式

        有三个always block,一个时序逻辑采用同步时序的方式描述状态转移,一个采用组合逻辑的方式判断状态转移条件、描述状态转移规律,第三个模块使用同步时序的方式描述每个状态的输出。代码容易维护,时序逻辑的输出解决了两段式组合逻辑的毛刺问题,但是从资源消耗的角度上看,三段式的资源消耗多一些。

        模板如下:

always @ ( posedge clk or negedge rst_n ) 
    begin  
        if ( !rst_n )  
            CS <= IDLE;  
        else  
            CS <= NS;  
    end  
  
always @*  
    begin  
        NS = 'b0;                   //初始化寄存器,避免生成latch  
        case (CS)                   //注意为CS  
            IDLE: begin  
            end;  
            S1: begin  
            end;  
            default:  
                NS = 'b0;           //与硬件电路一致  
        endcase  
    end  
  
always @ (posedge clk or negedge rst_n) 
    begin  
        if(!rst_n) begin  
        end  
        else begin 
            case (CS/NS)        //这里有2种写法,推荐NS写法(moore型写法) 
                ...  
                default: ;  
            endcase  
        end  
    end  

下面,举例说明:

        状态转换图如下所示:

  • 一段式:
    //时序逻辑电路
	always @(posedge clk or negedge rst_n)
		begin
			if(!rst_n)begin
			    cstate <= IDLE;
	            cmd <= 3'b000;
			end
			else
				case(cstate)
					IDLE:
						if(wr_req)begin
                            cstate <= WR_S1;
							cmd <= 3'b001;
						end
						else if(rd_req)begin
							cstate <= RD_S1;
							cmd <= 3'b011;
						end
						else begin
                            cstate <= IDLE;
							cmd <= 3'b000;
						end
					WR_S1:	begin
					    cstate <= WR_S2;
						cmd <= 3'b010;
					end
					WR_S2:	begin
					    cstate <= IDLE;
						cmd <= 3'b000;
					end
					RD_S1:
						if(wr_req)begin
							cstate <= WR_S2;
							cmd <= 3'b010;
						end
						else begin
							cstate <= RD_S2;
							cmd <= 3'b100;
						end
					RD_S2:
						if(wr_req) begin
							cstate <= WR_S1;
							cmd <= 3'b001;
						end
						else begin
							cstate <= IDLE;
							cmd <= 3'b000;
							end
					default:cstate <= IDLE;
				endcase
		end

testbench如下: 

`timescale 1 ns/ 100 ps

module fsm1_vlg_tst();

	reg clk;
	reg rd_req;
	reg rst_n;
	reg wr_req;                                             
	wire [2:0]  cmd;
	wire [2:0]  cstate;
                          
	fsm1 i1 (   
		.clk(clk),
		.cmd(cmd),
		.cstate(cstate),
		.rd_req(rd_req),
		.rst_n(rst_n),
		.wr_req(wr_req)
	);
	always #10 clk = ~clk;
	
	initial                                                
		begin
			clk = 0;rst_n = 1;
			wr_req = 0;rd_req = 0;
			#2 rst_n = 0;
			#10 rst_n = 1;
			repeat(100)
				begin
					#20 wr_req = {$random}%2;
						rd_req = {$random}%2;
				end
			#100 $stop;
		end                                                    
                                                    
endmodule

功能仿真波形图:

 三段式:

always block①:时序逻辑

//1st always block, sequential logic, store current state
always @(posedge clk or negedge rst_n)
		if(!rst_n)
			cstate <= IDLE;
		else
			cstate <= nstate;

always block②:组合逻辑 

//2nd always block, combinational logic, decide next state
always @(cstate or wr_req or rd_req)
		begin
            nstate = 3'b0;
			case(cstate)
				IDLE:
                    if(wr_req)
						nstate = WR_S1;
					else if(rd_req)
						nstate = RD_S1;
					else
						nstate = IDLE;
				WR_S1:nstate = WR_S2;
				WR_S2:nstate = IDLE;
				RD_S1:
                    if(wr_req)
						nstate = WR_S2;
					else
						nstate = RD_S2;
				RD_S2:
                    if(wr_req)
						nstate = WR_S1;
					else
						nstate = IDLE;
				default:nstate = 3'b0;
			endcase
		end
  •  注意

        always @(敏感电平信号)需要列举完全,可以用“@*”或者“@(*)”代替;

       初始值设置避免组合逻辑条件不全生成latch,但不一定符合设计。

        case(表达式)中的表达式为“cstate”,即现态

        阻塞赋值“=”;

        default项必须设置,与实际电路一致。

always block③:时序逻辑 

//3rd always block, FSM sequential output

  • Mealy型写法
always @(posedge clk or negedge rst_n)
		if(!rst_n)
			cmd <= 3'b000;
		else
			case(cstate)
				IDLE:
                    if(wr_req)
						cmd <= 3'b001;
					else if(rd_req)
						cmd <= 3'b011;
					else
						cmd <= 3'b000;
				WR_S1:cmd <= 3'b010;
				WR_S2:cmd <= 3'b000;
				RD_S1:
                    if(wr_req)
						cmd <= 3'b010;
					else
						cmd <= 3'b100;
				RD_S2:
                    if(wr_req)
						cmd <= 3'b001;
					else
						cmd <= 3'b000;
				default:;
			endcase
  • 注意

        case(表达式)中的表达式为“cstate”,即现态

        非阻塞赋值“<=”; 

        default项必须设置。

  • Moore型写法
always @(posedge clk or negedge rst_n)
		if(!rst_n)
			cmd <= 3'b000;
		else
			case(nstate)
				IDLE:	cmd <= 3'b000;
				WR_S1:	cmd <= 3'b001;
				WR_S2:	cmd <= 3'b010;
				RD_S1:	cmd <= 3'b011;
				RD_S2:	cmd <= 3'b100;
				default:;
			endcase

endmodule
  • 注意

        case(表达式)中的表达式为“nstate”,即次态,这里使用nextstate和state的区别在于,当状态跳转时,基于nextstate的输   出是立刻变化的,而基于state输出会延迟一个周期,其他情况都一样,应该根据自己的时序要求,选择用nextstate还是state。

        非阻塞赋值“<=”; 

        default项必须设置。

参考状态机详解,以及三段式状态机的思维陷阱

  • 79
    点赞
  • 447
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
该文件共分12个压缩包,必须下载到同一个文件夹后解压。 简介: 《TCP/IP详解,卷1:协议》是一本完整而详细的TCP/IP协议指南。描述了属于每一层的各个协议以及它们如何在不同操作系统中运行。作者用Lawrence Berkeley实验室的tcpdump程序来捕获不同操作系统和TCP/IP实现之间传输的不同分组。对tcpdump输出的研究可以帮助理解不同协议如何工作。 本书适合作为计算机专业学生学习网络的教材和教师参考书。也适用于研究网络的技术人员。 目 录 译者序 前言 第1章 概述 1 1.1 引言 1 1.2 分层 1 1.3 TCP/IP的分层 4 1.4 互联网的地址 5 1.5 域名系统 6 1.6 封装 6 1.7 分用 8 1.8 客户-服务器模型 8 1.9 端口号 9 1.10 标准化过程 10 1.11 RFC 10 1.12 标准的简单服务 11 1.13 互联网 12 1.14 实现 12 1.15 应用编程接口 12 1.16 测试网络 13 1.17 小结 13 第2章 链路层 15 2.1 引言 15 2.2 以太网和IEEE 802封装 15 2.3 尾部封装 17 2.4 SLIP:串行线路IP 17 2.5 压缩的SLIP 18 2.6 PPP:点对点协议 18 2.7 环回接口 20 2.8 最大传输单元MTU 21 2.9 路径MTU 21 2.10 串行线路吞吐量计算 21 2.11 小结 22 第3章 IP:网际协议 24 3.1 引言 24 3.2 IP首部 24 3.3 IP路由选择 27 3.4 子网寻址 30 3.5 子网掩码 32 3.6 特殊情况的IP地址 33 3.7 一个子网的例子 33 3.8 ifconfig命令 35 3.9 netstat命令 36 3.10 IP的未来 36 3.11 小结 37 第4章 ARP:地址解析协议 38 4.1 引言 38 4.2 一个例子 38 4.3 ARP高速缓存 40 4.4 ARP的分组格 40 4.5 ARP举例 41 4.5.1 一般的例子 41 4.5.2 对不存在主机的ARP请求 42 4.5.3 ARP高速缓存超时设置 43 4.6 ARP代理 43 4.7 免费ARP 45 4.8 arp命令 45 4.9 小结 46 第5章 RARP:逆地址解析协议 47 5.1 引言 47 5.2 RARP的分组格 47 5.3 RARP举例 47 5.4 RARP服务器的设计 48 5.4.1 作为用户进程的RARP服务器 49 5.4.2 每个网络有多个RARP服务器 49 5.5 小结 49 第6章 ICMP:Internet控制报文协议 50 6.1 引言 50 6.2 ICMP报文的类型 50 6.3 ICMP地址掩码请求与应答 52 6.4 ICMP时间戳请求与应答 53 6.4.1 举例 54 6.4.2 另一种方法 55 6.5 ICMP端口不可达差错 56 6.6 ICMP报文的4.4BSD处理 59 6.7 小结 60 第7章 Ping程序 61 7.1 引言 61 7.2 Ping程序 61 7.2.1 LAN输出 62 7.2.2 WAN输出 63 7.2.3 线路SLIP链接 64 7.2.4 拨号SLIP链路 65 7.3 IP记录路由选项 65 7.3.1 通常的例子 66 7.3.2 异常的输出 68 7.4 IP时间戳选项 69 7.5 小结 70 第8章 Traceroute程序 71 8.1 引言 71 8.2 Traceroute 程序的操作 71 8.3 局域网输出 72 8.4 广域网输出 75 8.5 IP源站选路选项 76 8.5.1 宽松的源站选路的traceroute 程序示例 78 8.5.2 严格的源站选路的traceroute 程序示例 79 8.5.3 宽松的源站选路traceroute程序 的往返路由 80 8.6 小结 81 第9章 IP选路 83 9.1 引言 83 9.2 选路的原理 84 9.2.1 简单路由表 84 9.2.2 初始化路由表 86 9.2.3 较复杂的路由表 87 9.2.4 没有到达目的地的路由 87 9.3 ICMP主机与网络不可达差错 88 9.4 转发或不转发 89 9.5 ICMP重定向差错 89 9.5.1 一个例子 90 9.5.2 更多的细节 91 9.6 ICMP路由器发现报文 92 9.6.1 路由器操作 93 9.6.2 主机操作 93 9.6.3 实现 93 9.7 小结 94 第10章 动态选路协议 95 10.1 引言 95 10.2 动态选路 95 10.3 Unix选路守护程序 96 10.4 RIP:选路信息协议 96 10.4.1 报文格 96 10.4.2 正常运行 97 10.4.3 度量 98 10.4.4 问题 98 10.4.5 举例 98 10.4.6 另一个例子 100 10.5 RIP版本2 102 10.6 OSPF:开放最短路径优先 102 10.7 BGP:边界网关协议 103 10.8 CIDR:无类型域间选路 104 10.9 小结 105 第11章 UDP:用户数据报协议 107 11.1 引言 107 11.2 UDP首部 107 11.3 UDP检验和 108 11.3.1 tcpdump输出 109 11.3.2 一些统计结果 109 11.4 一个简单的例子 110 11.5 IP分片 111 11.6 ICMP不可达差错(需要分片) 113 11.7 用Traceroute确定路径MTU 114 11.8 采用UDP的路径MTU发现 116 11.9 UDP和ARP之间的交互作用 118 11.10 最大UDP数据报长度 119 11.11 ICMP源站抑制差错 120 11.12 UDP服务器的设计 122 11.12.1 客户IP地址及端口号 122 11.12.2 目标IP地址 122 11.12.3 UDP输入队列 122 11.12.4 限制本地IP地址 124 11.12.5 限制远端IP地址 125 11.12.6 每个端口有多个接收者 125 11.13 小结 126 第12章 广播和多播 128 12.1 引言 128 12.2 广播 129 12.2.1 受限的广播 129 12.2.2 指向网络的广播 129 12.2.3 指向子网的广播 129 12.2.4 指向所有子网的广播 130 12.3 广播的例子 130 12.4 多播 132 12.4.1 多播组地址 133 12.4.2 多播组地址到以太网地址的转换 133 12.4.3 FDDI和令牌环网络中的多播 134 12.5 小结 134 第13章 IGMP:Internet组管理协议 136 13.1 引言 136 13.2 IGMP报文 136 13.3 IGMP协议 136 13.3.1 加入一个多播组 136 13.3.2 IGMP报告和查询 137 13.3.3 实现细节 137 13.3.4 生存时间字段 138 13.3.5 所有主机组 138 13.4 一个例子 138 13.5 小结 141 第14章 DNS:域名系统 142 14.1 引言 142 14.2 DNS基础 142 14.3 DNS的报文格 144 14.3.1 DNS查询报文中的问题部分 146 14.3.2 DNS响应报文中的资源记录部分 147 14.4 一个简单的例子 147 14.5 指针查询 150 14.5.1 举例 151 14.5.2 主机名检查 151 14.6 资源记录 152 14.7 高速缓存 153 14.8 用UDP还是用TCP 156 14.9 另一个例子 156 14.10 小结 157 第15章 TFTP:简单文件传送协议 159 15.1 引言 159 15.2 协议 159 15.3 一个例子 160 15.4 安全性 161 15.5 小结 162 第16章 BOOTP: 引导程序协议 163 16.1 引言 163 16.2 BOOTP的分组格 163 16.3 一个例子 164 16.4 BOOTP服务器的设计 165 16.5 BOOTP穿越路由器 167 16.6 特定厂商信息 167 16.7 小结 168 第17章 TCP:传输控制协议 170 17.1 引言 170 17.2 TCP的服务 170 17.3 TCP的首部 171 17.4 小结 173 第18章 TCP连接的建立与终止 174 18.1 引言 174 18.2 连接的建立与终止 174 18.2.1 tcpdump的输出 174 18.2.2 时间系列 175 18.2.3 建立连接协议 175 18.2.4 连接终止协议 177 18.2.5 正常的tcpdump输出 177 18.3 连接建立的超时 178 18.3.1 第一次超时时间 178 18.3.2 服务类型字段 179 18.4 最大报文段长度 179 18.5 TCP的半关闭 180 18.6 TCP的状态变迁图 182 18.6.1 2MSL等待状态 183 18.6.2 平静时间的概念 186 18.6.3 FIN_WAIT_2状态 186 18.7 复位报文段 186 18.7.1 到不存在的端口的连接请求 187 18.7.2 异常终止一个连接 187 18.7.3 检测半打开连接 188 18.8 同时打开 189 18.9 同时关闭 191 18.10 TCP选项 191 18.11 TCP服务器的设计 192 18.11.1 TCP服务器端口号 193 18.11.2 限定的本地IP地址 194 18.11.3 限定的远端IP地址 195 18.11.4 呼入连接请求队列 195 18.12 小结 197 第19章 TCP的交互数据流 200 19.1 引言 200 19.2 交互输入 200 19.3 经受时延的确认 201 19.4 Nagle算法 203 19.4.1 关闭Nagle算法 204 19.4.2 一个例子 205 19.5 窗口大小通告 207 19.6 小结 208 第20章 TCP的成块数据流 209 20.1 引言 209 20.2 正常数据流 209 20.3 滑动窗口 212 20.4 窗口大小 214 20.5 PUSH标志 215 20.6 慢启动 216 20.7 成块数据的吞吐量 218 20.7.1 带宽时延乘积 220 20.7.2 拥塞 220 20.8 紧急方 221 20.9 小结 224 第21章 TCP的超时与重传 226 21.1 引言 226 21.2 超时与重传的简单例子 226 21.3 往返时间测量 227 21.4 往返时间RTT的例子 229 21.4.1 往返时间RTT的测量 229 21.4.2 RTT估计器的计算 231 21.4.3 慢启动 233 21.5 拥塞举例 233 21.6 拥塞避免算法 235 21.7 快速重传与快速恢复算法 236 21.8 拥塞举例(续) 237 21.9 按每条路由进行度量 240 21.10 ICMP的差错 240 21.11 重新分组 243 21.12 小结 243 第22章 TCP的坚持定时器 245 22.1 引言 245 22.2 一个例子 245 22.3 糊涂窗口综合症 246 22.4 小结 250 第23章 TCP的保活定时器 251 23.1 引言 251 23.2 描述 252 23.3 保活举例 253 23.3.1 另一端崩溃 253 23.3.2 另一端崩溃并重新启动 254 23.3.3 另一端不可达 254 23.4 小结 255 第24章 TCP的未来和性能 256 24.1 引言 256 24.2 路径MTU发现 256 24.2.1 一个例子 257 24.2.2 大分组还是小分组 258 24.3 长肥管道 259 24.4 窗口扩大选项 262 24.5 时间戳选项 263 24.6 PAWS:防止回绕的序号 265 24.7 T/TCP:为事务用的TCP扩展 265 24.8 TCP的性能 267 24.9 小结 268 第25章 SNMP:简单网络管理协议 270 25.1 引言 270 25.2 协议 270 25.3 管理信息结构 272 25.4 对象标识符 274 25.5 管理信息库介绍 274 25.6 实例标识 276 25.6.1 简单变量 276 25.6.2 表格 276 25.6.3 字典排序 277 25.7 一些简单的例子 277 25.7.1 简单变量 278 25.7.2 get-next操作 278 25.7.3 表格的访问 279 25.8 管理信息库(续) 279 25.8.1 system组 279 25.8.2 interface组 280 25.8.3 at组 281 25.8.4 ip组 282 25.8.5 icmp组 285 25.8.6 tcp组 285 25.9 其他一些例子 288 25.9.1 接口MTU 288 25.9.2 路由表 288 25.10 trap 290 25.11 ASN.1和BER 291 25.12 SNMPv2 292 25.13 小结 292 第26章 Telnet和Rlogin:远程登录 293 26.1 引言 293 26.2 Rlogin协议 294 26.2.1 应用进程的启动 295 26.2.2 流量控制 295 26.2.3 客户的中断键 296 26.2.4 窗口大小的改变 296 26.2.5 服务器到客户的命令 296 26.2.6 客户到服务器的命令 297 26.2.7 客户的转义符 298 26.3 Rlogin的例子 298 26.3.1 初始的客户-服务器协议 298 26.3.2 客户中断键 299 26.4 Telnet协议 302 26.4.1 NVT ASCII 302 26.4.2 Telnet命令 302 26.4.3 选项协商 303 26.4.4 子选项协商 304 26.4.5 半双工、一次一字符、一次 一行或行方 304 26.4.6 同步信号 306 26.4.7 客户的转义符 306 26.5 Telnet举例 306 26.5.1 单字符方 306 26.5.2 行方 310 26.5.3 一次一行方(准行方) 312 26.5.4 行方:客户中断键 313 26.6 小结 314 第27章 FTP:文件传送协议 316 27.1 引言 316 27.2 FTP协议 316 27.2.1 数据表示 316 27.2.2 FTP命令 318 27.2.3 FTP应答 319 27.2.4 连接管理 320 27.3 FTP的例子 321 27.3.1 连接管理:临时数据端口 321 27.3.2 连接管理:默认数据端口 323 27.3.3 文本文件传输:NVT ASCII 表示还是图像表示 325 27.3.4 异常中止一个文件的传输: Telnet同步信号 326 27.3.5 匿名FTP 329 27.3.6 来自一个未知IP地址的匿名FTP 330 27.4 小结 331 第28章 SMTP:简单邮件传送协议 332 28.1 引言 332 28.2 SMTP协议 332 28.2.1 简单例子 332 28.2.2 SMTP命令 334 28.2.3 信封、首部和正文 335 28.2.4 中继代理 335 28.2.5 NVT ASCII 337 28.2.6 重试间隔 337 28.3 SMTP的例子 337 28.3.1 MX记录:主机非直接连到 Internet 337 28.3.2 MX记录:主机出故障 339 28.3.3 VRFY和EXPN命令 340 28.4 SMTP的未来 340 28.4.1 信封的变化:扩充的SMTP 341 28.4.2 首部变化:非ASCII字符 342 28.4.3 正文变化:通用Internet邮件 扩充 343 28.5 小结 346 第29章 网络文件系统 347 29.1 引言 347 29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS实例 356 29.6.1 简单的例子:读一个文件 356 29.6.2 简单的例子:创建一个目录 357 29.6.3 无状态 358 29.6.4 例子:服务器崩溃 358 29.6.5 等幂过程 360 29.7 第3版的NFS 360 29.8 小结 361 第30章 其他的TCP/IP应用程序 363 30.1 引言 363 30.2 Finger协议 363 30.3 Whois协议 364 30.4 Archie、WAIS、Gopher、Veronica 和WWW 366 30.4.1 Archie 366 30.4.2 WAIS 366 30.4.3 Gopher 366 30.4.4 Veronica 366 30.4.5 万维网WWW 367 30.5 X窗口系统 367 30.5.1 Xscope程序 368 30.5.2 LBX: 低带宽X 370 30.6 小结 370 附录A tcpdump程序 371 附录B 计算机时钟 376 附录C sock程序 378 附录D 部分习题的解答 381 附录E 配置选项 395 附录F 可以免费获得的源代码 406 参考文献 409 缩略语 420 目 录 译者序 前言 第1章 概述 1 1.1 引言 1 1.2 源代码表示 1 1.2.1 将拥塞窗口设置为1 1 1.2.2 印刷约定 2 1.3 历史 2 1.4 应用编程接口 3 1.5 程序示例 4 1.6 系统调用和库函数 6 1.7 网络实现概述 6 1.8 描述符 7 1.9 mbuf与输出处理 11 1.9.1 包含插口地址结构的mbuf 11 1.9.2 包含数据的mbuf 12 1.9.3 添加IP和UDP首部 13 1.9.4 IP输出 14 1.9.5 以太网输出 14 1.9.6 UDP输出小结 14 1.10 输入处理 15 1.10.1 以太网输入 15 1.10.2 IP输入 15 1.10.3 UDP输入 16 1.10.4 进程输入 17 1.11 网络实现概述(续) 17 1.12 中断级别与并发 18 1.13 源代码组织 20 1.14 测试网络 21 1.15 小结 22 第2章 mbuf:存储器缓存 24 2.1 引言 24 2.2 代码介绍 27 2.2.1 全局变量 27 2.2.2 统计 28 2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 34 2.6.2 mtod和dtom宏 36 2.6.3 m_pullup函数和连续的协议首部 36 2.6.4 m_pullup和IP的分片与重组 37 2.6.5 TCP重组避免调用m_pullup 39 2.6.6 m_pullup使用总结 40 2.7 mbuf宏和函数的小结 40 2.8 Net/3联网数据结构小结 42 2.9 m_copy和簇引用计数 43 2.10 其他选择 47 2.11 小结 47 第3章 接口层 49 3.1 引言 49 3.2 代码介绍 49 3.2.1 全局变量 49 3.2.2 SNMP变量 50 3.3 ifnet结构 51 3.4 ifaddr结构 57 3.5 sockaddr结构 58 3.6 ifnet与ifaddr的专用化 59 3.7 网络初始化概述 60 3.8 以太网初始化 61 3.9 SLIP初始化 64 3.10 环回初始化 65 3.11 if_attach函数 66 3.12 ifinit函数 72 3.13 小结 73 第4章 接口:以太网 74 4.1 引言 74 4.2 代码介绍 75 4.2.1 全局变量 75 4.2.2 统计量 75 4.2.3 SNMP变量 76 4.3 以太网接口 77 4.3.1 leintr函数 79 4.3.2 leread函数 79 4.3.3 ether_input函数 81 4.3.4 ether_output函数 84 4.3.5 lestart函数 87 4.4 ioctl系统调用 89 4.4.1 ifioctl函数 90 4.4.2 ifconf函数 91 4.4.3 举例 94 4.4.4 通用接口ioctl命令 95 4.4.5 if_down和if_up函数 96 4.4.6 以太网、SLIP和环回 97 4.5 小结 98 第5章 接口:SLIP和环回 100 5.1 引言 100 5.2 代码介绍 100 5.2.1 全局变量 100 5.2.2 统计量 101 5.3 SLIP接口 101 5.3.1 SLIP线路规程:SLIPDISC 101 5.3.2 SLIP初始化:slopen和slinit 103 5.3.3 SLIP输入处理:slinput 105 5.3.4 SLIP输出处理:sloutput 109 5.3.5 slstart函数 111 5.3.6 SLIP分组丢失 116 5.3.7 SLIP性能考虑 117 5.3.8 slclose函数 117 5.3.9 sltioctl函数 118 5.4 环回接口 119 5.5 小结 121 第6章 IP编址 123 6.1 引言 123 6.1.1 IP地址 123 6.1.2 IP地址的印刷规定 123 6.1.3 主机和路由器 124 6.2 代码介绍 125 6.3 接口和地址小结 125 6.4 sockaddr_in结构 126 6.5 in_ifaddr结构 127 6.6 地址指派 128 6.6.1 ifioctl函数 130 6.6.2 in_control函数 130 6.6.3 前提条件:SIOCSIFADDR、 SIOCSIFNETMASK和 SIOCSIFDSTADDR 132 6.6.4 地址指派:SIOCSIFADDR 133 6.6.5 in_ifinit函数 133 6.6.6 网络掩码指派:SIOCSIFNETMASK 136 6.6.7 目的地址指派:SIOCSIFDSTADDR 137 6.6.8 获取接口信息 137 6.6.9 每个接口多个IP地址 138 6.6.10 附加IP地址:SIOCAIFADDR 139 6.6.11 删除IP地址:SIOCDIFADDR 140 6.7 接口ioctl处理 141 6.7.1 leioctl函数 141 6.7.2 slioctl函数 142 6.7.3 loioctl函数 143 6.8 Internet实用函数 144 6.9 ifnet实用函数 144 6.10 小结 145 第7章 域和协议 146 7.1 引言 146 7.2 代码介绍 146 7.2.1 全局变量 147 7.2.2 统计量 147 7.3 domain结构 147 7.4 protosw结构 148 7.5 IP 的domain和protosw结构 150 7.6 pffindproto和pffindtype函数 155 7.7 pfctlinput函数 157 7.8 IP初始化 157 7.8.1 Internet传输分用 157 7.8.2 ip_init函数 158 7.9 sysctl系统调用 159 7.10 小结 161 第8章 IP:网际协议 162 8.1 引言 162 8.2 代码介绍 163 8.2.1 全局变量 163 8.2.2 统计量 163 8.2.3 SNMP变量 164 8.3 IP分组 165 8.4 输入处理:ipintr函数 167 8.4.1 ipintr概观 167 8.4.2 验证 168 8.4.3 转发或不转发 171 8.4.4 重装和分用 173 8.5 转发:ip_forward函数 174 8.6 输出处理:ip_output函数 180 8.6.1 首部初始化 181 8.6.2 路由选择 182 8.6.3 源地址选择和分片 184 8.7 Internet检验和:in_cksum函数 186 8.8 setsockopt和getsockopt系统调用 190 8.8.1 PRCO_SETOPT的处理 192 8.8.2 PRCO_GETOPT的处理 193 8.9 ip_sysctl函数 193 8.10 小结 194 第9章 IP选项处理 196 9.1 引言 196 9.2 代码介绍 196 9.2.1 全局变量 196 9.2.2 统计量 197 9.3 选项格 197 9.4 ip_dooptions函数 198 9.5 记录路由选项 200 9.6 源站和记录路由选项 202 9.6.1 save_rte函数 205 9.6.2 ip_srcroute函数 206 9.7 时间戳选项 207 9.8 ip_insertoptions函数 210 9.9 ip_pcbopts函数 214 9.10 一些限制 217 9.11 小结 217 第10章 IP的分片与重装 218 10.1 引言 218 10.2 代码介绍 219 10.2.1 全局变量 220 10.2.2 统计量 220 10.3 分片 220 10.4 ip_optcopy函数 223 10.5 重装 224 10.6 ip_reass函数 227 10.7 ip_slowtimo函数 237 10.8 小结 238 第11章 ICMP:Internet控制报文协议 239 11.1 引言 239 11.2 代码介绍 242 11.2.1 全局变量 242 11.2.2 统计量 242 11.2.3 SNMP变量 243 11.3 icmp结构 244 11.4 ICMP 的protosw结构 245 11.5 输入处理:icmp_input函数 246 11.6 差错处理 249 11.7 请求处理 251 11.7.1 回显询问:ICMP_ECHO和 ICMP_ECHOREPLY 252 11.7.2 时间戳询问:ICMP_TSTAMP和 ICMP_TSTAMPREPLY 253 11.7.3 地址掩码询问:ICMP_MASKREQ和 ICMP_MASKREPLY 253 11.7.4 信息询问:ICMP_IREQ和ICMP_ IREQREPLY 255 11.7.5 路由器发现:ICMP_ROUTERADVERT 和ICMP_ROUTERSOLICIT 255 11.8 重定向处理 255 11.9 回答处理 257 11.10 输出处理 257 11.11 icmp_error函数 258 11.12 icmp_reflect函数 261 11.13 icmp_send函数 265 11.14 icmp_sysctl函数 266 11.15 小结 266 第12章 IP多播 268 12.1 引言 268 12.2 代码介绍 269 12.2.1 全局变量 270 12.2.2 统计量 270 12.3 以太网多播地址 270 12.4 ether_multi结构 271 12.5 以太网多播接收 273 12.6 in_multi结构 273 12.7 ip_moptions结构 275 12.8 多播的插口选项 276 12.9 多播的TTL值 277 12.9.1 MBONE 278 12.9.2 扩展环搜索 278 12.10 ip_setmoptions函数 278 12.10.1 选择一个明确的多播接口:IP_ MULTICAST_IF 280 12.10.2 选择明确的多播TTL: IP_ MULTICAST_TTL 281 12.10.3 选择多播环回:IP_MULTICAST_ LOOP 281 12.11 加入一个IP多播组 282 12.11.1 in_addmulti函数 285 12.11.2 slioctl和loioctl函数:SIOCADDMULTI和SIOCDELMULTI 287 12.11.3 leioctl函数:SIOCADDMULTI和 SIOCDELMULTI 288 12.11.4 ether_addmulti函数 288 12.12 离开一个IP多播组 291 12.12.1 in_delmulti函数 292 12.12.2 ether_delmulti函数 293 12.13 ip_getmoptions函数 295 12.14 多播输入处理:ipintr函数 296 12.15 多播输出处理:ip_output函数 298 12.16 性能的考虑 301 12.17 小结 301 第13章 IGMP:Internet组管理协议 303 13.1 引言 303 13.2 代码介绍 304 13.2.1 全局变量 304 13.2.2 统计量 304 13.2.3 SNMP变量 305 13.3 igmp结构 305 13.4 IGMP的protosw的结构 306 13.5 加入一个组:igmp_joingroup函数 306 13.6 igmp_fasttimo函数 308 13.7 输入处理:igmp_input函数 311 13.7.1 成员关系查询:IGMP_HOST_ MEMBERSHIP_QUERY 312 13.7.2 成员关系报告:IGMP_HOST_ MEMBERSHIP_REPORT 313 13.8 离开一个组:igmp_leavegroup函数 314 13.9 小结 315 第14章 IP多播选路 316 14.1 引言 316 14.2 代码介绍 316 14.2.1 全局变量 316 14.2.2 统计量 317 14.2.3 SNMP变量 317 14.3 多播输出处理(续) 317 14.4 mrouted守护程序 318 14.5 虚拟接口 321 14.5.1 虚拟接口表 322 14.5.2 add_vif函数 324 14.5.3 del_vif函数 326 14.6 IGMP(续) 327 14.6.1 add_lgrp函数 328 14.6.2 del_lgrp函数 329 14.6.3 grplst_member函数 330 14.7 多播选路 331 14.7.1 多播选路表 334 14.7.2 del_mrt函数 335 14.7.3 add_mrt函数 336 14.7.4 mrtfind函数 337 14.8 多播转发:ip_mforward函数 338 14.8.1 phyint_send函数 343 14.8.2 tunnel_send函数 344 14.9 清理:ip_mrouter_done函数 345 14.10 小结 346 第15章 插口层 348 15.1 引言 348 15.2 代码介绍 349 15.3 socket结构 349 15.4 系统调用 354 15.4.1 举例 355 15.4.2 系统调用小结 355 15.5 进程、描述符和插口 357 15.6 socket系统调用 358 15.6.1 socreate函数 359 15.6.2 超级用户特权 361 15.7 getsock和sockargs函数 361 15.8 bind系统调用 363 15.9 listen系统调用 364 15.10 tsleep和wakeup函数 365 15.11 accept系统调用 366 15.12 sonewconn和soisconnected 函数 369 15.13 connect系统调用 372 15.13.1 soconnect函数 374 15.13.2 切断无连接插口和外部地址的 关联 375 15.14 shutdown系统调用 375 15.15 close系统调用 377 15.15.1 soo_close函数 377 15.15.2 soclose函数 378 15.16 小结 380 第16章 插口I/O 381 16.1 引言 381 16.2 代码介绍 381 16.3 插口缓存 381 16.4 write、writev、sendto和sendmsg 系统调用 384 16.5 sendmsg系统调用 387 16.6 sendit函数 388 16.6.1 uiomove函数 389 16.6.2 举例 390 16.6.3 sendit代码 391 16.7 sosend函数 392 16.7.1 可靠的协议缓存 393 16.7.2 不可靠的协议缓存 393 16.7.3 sosend函数小结 401 16.7.4 性能问题 401 16.8 read、readv、recvfrom和recvmsg 系统调用 401 16.9 recvmsg系统调用 402 16.10 recvit函数 403 16.11 soreceive函数 405 16.11.1 带外数据 406 16.11.2 举例 406 16.11.3 其他的接收操作选项 407 16.11.4 接收缓存的组织:报文边界 407 16.11.5 接收缓存的组织:没有报文边界 408 16.11.6 控制信息和带外数据 409 16.12 soreceive代码 410 16.13 select系统调用 421 16.13.1 selscan函数 425 16.13.2 soo_select函数 425 16.13.3 selrecord函数 427 16.13.4 selwakeup函数 428 16.14 小结 429 第17章 插口选项 431 17.1 引言 431 17.2 代码介绍 431 17.3 setsockopt系统调用 432 17.4 getsockopt系统调用 437 17.5 fcntl和ioctl系统调用 440 17.5.1 fcntl代码 441 17.5.2 ioctl代码 443 17.6 getsockname系统调用 444 17.7 getpeername系统调用 445 17.8 小结 447 第18章 Radix树路由表 448 18.1 引言 448 18.2 路由表结构 448 18.3 选路插口 456 18.4 代码介绍 456 18.4.1 全局变量 458 18.4.2 统计量 458 18.4.3 SNMP变量 459 18.5 Radix结点数据结构 460 18.6 选路结构 463 18.7 初始化:route_init和rtable_init 函数 465 18.8 初始化:rn_init和rn_inithead 函数 468 18.9 重复键和掩码列表 471 18.10 rn_match函数 473 18.11 rn_search函数 480 18.12 小结 481 第19章 选路请求和选路消息 482 19.1 引言 482 19.2 rtalloc和rtalloc1函数 482 19.3 宏RTFREE和rtfree函数 484 19.4 rtrequest函数 486 19.5 rt_setgate函数 491 19.6 rtinit函数 493 19.7 rtredirect函数 495 19.8 选路消息的结构 498 19.9 rt_missmsg函数 501 19.10 rt_ifmsg函数 503 19.11 rt_newaddrmsg函数 504 19.12 rt_msg1函数 505 19.13 rt_msg2函数 507 19.14 sysctl_rtable函数 510 19.15 sysctl_dumpentry函数 514 19.16 sysctl_iflist函数 515 19.17 小结 517 第20章 选路插口 518 20.1 引言 518 20.2 routedomain和protosw结构 518 20.3 选路控制块 519 20.4 raw_init函数 520 20.5 route_output函数 520 20.6 rt_xaddrs函数 530 20.7 rt_setmetrics函数 531 20.8 raw_input函数 532 20.9 route_usrreq函数 534 20.10 raw_usrreq函数 535 20.11 raw_attach、raw_detach和raw_disconnect函数 539 20.12 小结 540 第21章 ARP:地址解析协议 542 21.1 介绍 542 21.2 ARP和路由表 542 21.3 代码介绍 544 21.3.1 全局变量 544 21.3.2 统计量 544 21.3.3 SNMP变量 546 21.4 ARP结构 546 21.5 arpwhohas函数 548 21.6 arprequest函数 548 21.7 arpintr函数 551 21.8 in_arpinput函数 552 21.9 ARP定时器函数 557 21.9.1 arptimer函数 557 21.9.2 arptfree函数 557 21.10 arpresolve函数 558 21.11 arplookup函数 562 21.12 代理ARP 563 21.13 arp_rtrequest函数 564 21.14 ARP和多播 569 21.15 小结 570 第22章 协议控制块 572 22.1 引言 572 22.2 代码介绍 573 22.2.1 全局变量 574 22.2.2 统计量 574 22.3 inpcb的结构 574 22.4 in_pcballoc和in_pcbdetach函数 575 22.5 绑定、连接和分用 577 22.6 in_pcblookup函数 581 22.7 in_pcbbind函数 584 22.8 in_pcbconnect函数 589 22.9 in_pcbdisconnect函数 594 22.10 in_setsockaddr和in_setpeeraddr 函数 595 22.11 in_pcbnotify、in_rtchange和in_losing函数 595 22.11.1 in_rtchange函数 598 22.11.2 重定向和原始插口 599 22.11.3 ICMP差错和UDP插口 600 22.11.4 in_losing函数 601 22.12 实现求精 602 22.13 小结 602 第23章 UDP:用户数据报协议 605 23.1 引言 605 23.2 代码介绍 605 23.2.1 全局变量 606 23.2.2 统计量 606 23.2.3 SNMP变量 607 23.3 UDP 的protosw结构 607 23.4 UDP的首部 608 23.5 udp_init函数 609 23.6 udp_output函数 609 23.6.1 在前面加上IP/UDP首部和mbuf簇 612 23.6.2 UDP检验和计算和伪首部 612 23.7 udp_input函数 616 23.7.1 对收到的UDP数据报的一般确认 616 23.7.2 分用单播数据报 619 23.7.3 分用多播和广播数据报 622 23.7.4 连接上的UDP插口和多接口主机 625 23.8 udp_saveopt函数 625 23.9 udp_ctlinput函数 627 23.10 udp_usrreq函数 628 23.11 udp_sysctl函数 633 23.12 实现求精 633 23.12.1 UDP PCB高速缓存 633 23.12.2 UDP检验和 634 23.13 小结 635 第24章 TCP:传输控制协议 636 24.1 引言 636 24.2 代码介绍 636 24.2.1 全局变量 636 24.2.2 统计量 637 24.2.3 SNMP变量 640 24.3 TCP 的protosw结构 641 24.4 TCP的首部 641 24.5 TCP的控制块 643 24.6 TCP的状态变迁图 645 24.7 TCP的序号 646 24.8 tcp_init函数 650 24.9 小结 652 第25章 TCP的定时器 654 25.1 引言 654 25.2 代码介绍 655 25.3 tcp_canceltimers函数 657 25.4 tcp_fasttimo函数 657 25.5 tcp_slowtimo函数 658 25.6 tcp_timers函数 659 25.6.1 FIN_WAIT_2和2MSL定时器 660 25.6.2 持续定时器 662 25.6.3 连接建立定时器和保活定时器 662 25.7 重传定时器的计算 665 25.8 tcp_newtcpcb算法 666 25.9 tcp_setpersist函数 668 25.10 tcp_xmit_timer函数 669 25.11 重传超时:tcp_timers函数 673 25.11.1 慢起动和避免拥塞 675 25.11.2 精确性 677 25.12 一个RTT的例子 677 25.13 小结 679 第26章 TCP输出 680 26.1 引言 680 26.2 tcp_output概述 680 26.3 决定是否应发送一个报文段 682 26.4 TCP选项 691 26.5 窗口大小选项 692 26.6 时间戳选项 692 26.6.1 哪个时间戳需要回显,RFC1323 算法 694 26.6.2 哪个时间戳需要回显,正确的 算法 695 26.6.3 时间戳与延迟ACK 695 26.7 发送一个报文段 696 26.8 tcp_template函数 707 26.9 tcp_respond函数 708 26.10 小结 710 第27章 TCP的函数 712 27.1 引言 712 27.2 tcp_drain函数 712 27.3 tcp_drop函数 712 27.4 tcp_close函数 713 27.4.1 路由特性 713 27.4.2 资源释放 716 27.5 tcp_mss函数 717 27.6 tcp_ctlinput函数 722 27.7 tcp_notify函数 723 27.8 tcp_quench函数 724 27.9 TCP_REASS宏和tcp_reass函数 724 27.9.1 TCP_REASS宏 725 27.9.2 tcp_reass函数 727 27.10 tcp_trace函数 732 27.11 小结 736 第28章 TCP的输入 737 28.1 引言 737 28.2 预处理 739 28.3 tcp_dooptions函数 745 28.4 首部预测 747 28.5 TCP输入:缓慢的执行路径 752 28.6 完成被动打开或主动打开 752 28.6.1 完成被动打开 753 28.6.2 完成主动打开 756 28.7 PAWS:防止序号回绕 760 28.8 裁剪报文段使数据在窗口内 762 28.9 自连接和同时打开 768 28.10 记录时间戳 770 28.11 RST处理 770 28.12 小结 772 第29章 TCP的输入(续) 773 29.1 引言 773 29.2 ACK处理概述 773 29.3 完成被动打开和同时打开 774 29.4 快速重传和快速恢复的算法 775 29.5 ACK处理 778 29.6 更新窗口信息 784 29.7 紧急方处理 786 29.8 tcp_pulloutofband函数 788 29.9 处理已接收的数据 789 29.10 FIN处理 791 29.11 最后的处理 793 29.12 实现求精 795 29.13 首部压缩 795 29.13.1 引言 796 29.13.2 首部字段的压缩 799 29.13.3 特殊情况 801 29.13.4 实例 802 29.13.5 配置 803 29.14 小结 803 第30章 TCP的用户需求 805 30.1 引言 805 30.2 tcp_usrreq函数 805 30.3 tcp_attach函数 814 30.4 tcp_disconnect函数 815 30.5 tcp_usrclosed函数 816 30.6 tcp_ctloutput函数 817 30.7 小结 820 第31章 BPF:BSD 分组过滤程序 821 31.1 引言 821 31.2 代码介绍 821 31.2.1 全局变量 821 31.2.2 统计量 822 31.3 bpf_if结构 822 31.4 bpf_d结构 825 31.4.1 bpfopen函数 826 31.4.2 bpfioctl函数 827 31.4.3 bpf_setif函数 830 31.4.4 bpf_attachd函数 831 31.5 BPF的输入 832 31.5.1 bpf_tap函数 832 31.5.2 catchpacket函数 833 31.5.3 bpfread函数 835 31.6 BPF的输出 837 31.7 小结 838 第32章 原始IP 839 32.1 引言 839 32.2 代码介绍 839 32.2.1 全局变量 839 32.2.2 统计量 840 32.3 原始 IP的protosw结构 840 32.4 rip_init函数 842 32.5 rip_input函数 842 32.6 rip_output函数 844 32.7 rip_usrreq函数 846 32.8 rip_ctloutput函数 850 32.9 小结 852 结束语 853 附录A 部分习题的解答 854 附录B 源代码的获取 872 附录C RFC 1122 的有关内容 874 参考文献 895 目 录 译者序 前言 第一部分 TCP事务协议 第1章 T/TCP概述 1 1.1 概述 1 1.2 UDP上的客户-服务器 1 1.3 TCP上的客户-服务器 6 1.4 T/TCP上的客户-服务器 12 1.5 测试网络 15 1.6 时间测量程序 15 1.7 应用 17 1.8 历史 19 1.9 实现 20 1.10 小结 21 第2章 T/TCP协议 23 2.1 概述 23 2.2 T/TCP中的新TCP选项 23 2.3 T/TCP实现所需变量 25 2.4 状态变迁图 27 2.5 T/TCP的扩展状态 28 2.6 小结 30 第3章 T/TCP使用举例 31 3.1 概述 31 3.2 客户重新启动 31 3.3 常规的T/TCP事务 33 3.4 服务器收到过时的重复SYN 34 3.5 服务器重启动 35 3.6 请求或应答超出报文段最大长度MSS 36 3.7 向后兼容性 39 3.8 小结 41 第4章 T/TCP协议(续) 43 4.1 概述 43 4.2 客户的端口号和TIME_WAIT状态 43 4.3 设置TIME_WAIT状态的目的 45 4.4 TIME_WAIT状态的截断 48 4.5 利用TAO跳过三次握手 51 4.6 小结 55 第5章 T/TCP协议的实现:插口层 56 5.1 概述 56 5.2 常量 56 5.3 sosend函数 56 5.4 小结 58 第6章 T/TCP的实现:路由表 59 6.1 概述 59 6.2 代码介绍 59 6.3 radix_node_head结构 60 6.4 rtentry结构 61 6.5 rt_metrics结构 61 6.6 in_inithead函数 61 6.7 in_addroute函数 62 6.8 in_matroute函数 63 6.9 in_clsroute函数 63 6.10 in_rtqtimo函数 64 6.11 in_rtqkill函数 66 6.12 小结 69 第7章 T/TCP实现:协议控制块 70 7.1 概述 70 7.2 in_pcbladdr函数 71 7.3 in_pcbconnect函数 71 7.4 小结 72 第8章 T/TCP实现: TCP概要 73 8.1 概述 73 8.2 代码介绍 73 8.3 TCP的protosw结构 74 8.4 TCP控制块 74 8.5 tcp_init函数 75 8.6 tcp_slowtimo函数 75 8.7 小结 76 第9章 T/TCP实现:TCP输出 77 9.1 概述 77 9.2 tcp_output函数 77 9.2.1 新的自动变量 77 9.2.2 增加隐藏的状态标志 77 9.2.3 在SYN_SENT状态不要重传SYN 78 9.2.4 发送器的糊涂窗口避免机制 78 9.2.5 有RST或SYN标志时强制发送报文段 79 9.2.6 发送MSS选项 80 9.2.7 是否发送时间戳选项 80 9.2.8 发送T/TCP的CC选项 80 9.2.9 根据TCP选项调整数据长度 83 9.3 小结 83 第10章 T/TCP实现:TCP函数 84 10.1 概述 84 10.2 tcp_newtcpcb函数 84 10.3 tcp_rtlookup函数 85 10.4 tcp_gettaocache函数 86 10.5 重传超时间隔的计算 86 10.6 tcp_close函数 89 10.7 tcp_msssend函数 90 10.8 tcp_mssrcvd函数 91 10.9 tcp_dooptions函数 96 10.10 tcp_reass函数 98 10.11 小结 99 第11章 T/TCP实现:TCP输入 101 11.1 概述 101 11.2 预处理 103 11.3 首部预测 104 11.4 被动打开的启动 105 11.5 主动打开的启动 108 11.6 PAWS:防止序号重复 114 11.7 ACK处理 115 11.8 完成被动打开和同时打开 115 11.9 ACK处理(续) 116 11.10 FIN处理 118 11.11 小结 119 第12章 T/TCP实现:TCP用户请求 120 12.1 概述 120 12.2 PRU_CONNECT请求 120 12.3 tcp_connect函数 120 12.4 PRU_SEND和PRU_SEND_EOF请求 124 12.5 tcp_usrclosed函数 125 12.6 tcp_sysctl函数 126 12.7 T/TCP的前景 126 12.8 小结 127 第二部分 TCP的其他应用 第13章 HTTP:超文本传送协议 129 13.1 概述 129 13.2 HTTP和HTML概述 130 13.3 HTTP 132 13.3.1 报文类型:请求与响应 132 13.3.2 首部字段 133 13.3.3 响应代码 133 13.3.4 各种报文头举例 134 13.3.5 例子:客户程序缓存 135 13.3.6 例子:服务器重定向 136 13.4 一个例子 136 13.5 HTTP的统计资料 138 13.6 性能问题 139 13.7 小结 141 第14章 在HTTP服务器上找到的分组 142 14.1 概述 142 14.2 多个HTTP服务器 144 14.3 客户端SYN的到达间隔时间 145 14.4 RTT的测量 149 14.5 用listen设置入连接队列的容量 150 14.6 客户端的SYN选项 154 14.7 客户端的SYN重传 156 14.8 域名 157 14.9 超时的持续探测 157 14.10 T/TCP路由表大小的模拟 160 14.11 mbuf的交互 162 14.12 TCP的PCB高速缓存和首部预测 163 14.13 小结 165 第15章 NNTP:网络新闻传送协议 166 15.1 概述 166 15.2 NNTP 167 15.3 一个简单的新闻客户 170 15.4 一个复杂的新闻客户 171 15.5 NNTP的统计资料 172 15.6 小结 173 第三部分 Unix域协议 第16章 Unix域协议:概述 175 16.1 概述 175 16.2 用途 176 16.3 性能 177 16.4 编码举例 177 16.5 小结 179 第17章 Unix域协议:实现 180 17.1 概述 180 17.2 代码介绍 180 17.3 Unix domain和protosw结构 181 17.4 Unix域插口地址结构 182 17.5 Unix域协议控制块 183 17.6 uipc_usrreq函数 185 17.7 PRU_ATTACH请求和unp_attach函数 186 17.8 PRU_DETACH请求和unp_detach函数 187 17.9 PRU_BIND请求和unp_bind函数 189 17.10 PRU_CONNECT请求和unp_connect 函数 191 17.11 PRU_CONNECT2请求和unp_connect2 函数 195 17.12 socketpair系统调用 198 17.13 pipe系统调用 202 17.14 PRU_ACCEPT请求 203 17.15 PRU_DISCONNECT请求和 unp_disconnect函数 204 17.16 PRU_SHUTDOWN请求和unp_shutdown 函数 205 17.17 PRU_ABORT请求和unp_drop函数 206 17.18 其他各种请求 207 17.19 小结 209 第18章 Unix域协议:I/O和描述符的传递 210 18.1 概述 210 18.2 PRU_SEND和PRU_RCVD请求 210 18.3 描述符的传递 214 18.4 unp_internalize函数 218 18.5 unp_externalize函数 220 18.6 unp_discard函数 221 18.7 unp_dispose函数 222 18.8 unp_scan函数 222 18.9 unp_gc函数 223 18.10 unp_mark函数 230 18.11 性能(再讨论) 231 18.12 小结 231 附录A 测量网络时间 232 附录B 编写T/TCP应用程序 242 参考文献 246 缩略语 251
1.安装与启动 第1步、一卡通系统硬件的安装及网络组建 确保一卡通(消费)系统设备、网络已按要求安装布建完毕。有关更多网络布建及设备安装信息,请参见随机光盘内附有设备的《硬件说明书》及《快速操作手册》,请先按说明书内所述内容进行设备的安装与组网。 第2步、安装数据库平台 您使用的一卡通系统兼容Microsoft® SQL Server™和Microsoft® Office Access两种数据库格。若您想软件拥有多人联网控制功能,那请先在服务器上安装好Microsoft® SQL Server™ 2000或2005版数据库管理软件。 如果您想软件具备联网控制功能,请先在主机上安装Microsoft SQL Server数据库。Microsoft SQL Server的具体安装说明请查看:SQL Server安装光盘内《SQL Server安装帮助》:\books\ setupsql。 第3步、安装一卡通系统软件 1) 将一卡通软件安装光盘插入 CD-ROM 驱动器,该光盘不自动运行,双击该光盘根目录中的 图标,进入安装程序。 2) 进入安装程序界面,点下一步可进入安装目录选择区域。09版一卡通软件的默认安装路径为“C:\Program File\一卡通09\”,您可根据您的使用习惯和实际使用需要更改安装目录。选择好安装目录后点下一步,再点安装。安装程序将自动运行安装。 注意: 1、一卡通管理系统及SQL Server数据库尽量不要安装在系统盘; 2、SQL Server不建议使用空密码。 3) 全部安装完毕后,运行桌面快捷方启动软件。 2.快速配置系统参数 进入系统配置向导模块,可协助用户快速对系统进行配置。 系统快速配置指南与常见配置问题解释 1) 数据库配置:可自选择使用Access或MS-SQL数据库,默认为Access。当选择为MS-SQL时,需要在数据源处输入SQL Server服务器IP(本机使用默认的local则可)、用户ID数据SQL Server用户名、用户密码输入SQL Server密码完成配置。注意,在客户端远程访问服务器数据库时,可能出现能PING通,但连接数据库时提示连接超时或数据库不存在,这时可通过windows命令行模下输入网络命令:“telnet 服务器IP地址 1433”,回车后若看到黑色一片,则网络设置正常,可能是SQL本身没有安装好或者没有打SP4补丁;若提示连接失败,则可能是路由器、防火墙限制了网络访问; 2) 一卡通管理系统软件要求系统识别码必须正确,否则无法正常使用。用户如不清楚系统识别码,可向设备供应商询问; 3) 通讯配置:通讯端口设置默认为1表示使用COM1通讯(串口通讯时才有效),用户可根据实际情况自行修改。通讯波特率固定有线系统为19200,无线系统为38400; 4) 卡型号与发卡器:发卡器型号默认R100CU2(匹配USB读卡器使用),若是串口读卡器,型号则选择R100C。发卡器端口为对应串口,一般串口读卡器选择电脑串口(一般是COM1),若是USB读卡器,安装驱动程序后,可以在 “我的电脑”右键→“管理”→“设备管理器”→“端口(COM与LPT)” 内,看到一个USB-Serial CH341(COM X),X代表一个COM号,假设为COM3,则在发卡器端口内设置为端口3。注意,某些客户在安装USB读卡器时,可能出现无法识别的USB设备,这是由于主板USB供电不足造成的,可尝试把电脑所有USB设备拔掉,再使用电脑后方的主USB口。如果还是提示无法识别的USB设备,请更换电脑; 5) 发卡类型:通常默认为一卡通卡。若使用门禁读头发卡才选择 “门禁卡”; 6) 大功能选择:可选消费、考勤、门禁三大系统,若不选择,则该功能完全屏蔽无法使用; 7) 消费模:可选储值、补贴、挂帐、计次、订餐五大类,请正确选择。 3.人事资料与发卡操作 输入用户名密码,运行软件。 3.1人事资料的添加及发卡操作 人事资料的添加及发卡操作指南 1) 点 “资料设定”→“人事资料”→“添加” 进入人员信息添加界面。里面的编号默认为系统中人员的唯一识别号,系统默认自动以递增编号的方自动进行编号,您可根据您的实际情况修改和填写,但注意人员编号必须唯一不能重复; 2) 人事资料添加窗口内的部门、职位等信息可通过点击 “..” 按钮直接添加; 3) 点下一个按钮完成一个人的人卡资料添加并继续操作下一个,全部完成后点确认退出; 4) 人事资料添加完毕后,可直接选择未发卡人员,点鼠标右键→发卡,或通过 “卡片中心”→“发卡”,选择未发卡人员,点鼠标右键→发卡完成操作。 3.2人事资料的导入 点 “资料设定”→ “资料导入”,进入导入参数设置,根据您的Excel格的人事资料文档实际情况填写对应的Excel的列。如Excel表内列A是姓名,B是编号,则只需要在人员编号里输入B,在姓名里输入A则可。 Excel表格 导入数据文件支持格:XLS。系统必须安装Microsoft Office 2000或以上版本才能完成数据导入操作。软件不支持WPS办公软件,也不支持Excel 2007的XLSX格。 必选项 人员编号、姓名、部门三项信息为必选项,导入数据前应准备的表格也需至少包含这四类信息对应的列。 起始行 导入前还需确认表格文件内信息起始行,假设表格内含有表头等其它非相关信息的行,需在资料是从第_____行开始内输入起始行再进行导入。 3.3批量发卡 点 “卡片中心”→“批量发卡” 进入人员信息添加界面。在批量发卡功能模块内,默认会把所有未发卡人员添加到待发卡列表,用户只需要点击 “开始发卡” 按钮就可以按列表顺序,一次过把所有未发卡直接发完。 如果未发卡人员较多,需要按部门为顺序(或自定义顺序)进行发卡,则可以先点 “移除全部”按钮,把所有待发卡人员移去,再点部门,把本次需要发卡的人员重新添加到待发卡人员列表中,点 “开始发卡” 按钮就可以按列表顺序进行发卡操作。 4.设备配置 1) 点 “设备管理”→“设备配置” 进入设备配置界面;注意,在设备配置前,消费系统建议先把消费机编号修改成唯一编号,修改方法请详细参见《消费机硬件说明书》或《消费机快速操作指南》; 2) 在“默认通讯”页面,先配置好通讯参数。通讯参数包括: 串口通讯 通讯端口选择好电脑用于通讯的串口的号码 通讯波特率固定为有线19200,无线38400 串口连接注意 设置不正确的通讯端口在通讯时可能导致系统无法正常通讯及采集数据 TCP/IP通讯 输入TCP/IP-RS485转换器IP地址(IP地址可通过专门软件获取) 端口一般默认为50000,用户可通过配置软件修改转换器通讯端口,一般建议使用默认 TCP/IP连接 注意事项 在TCP/IP通讯时,同样可能出现能PING通,但连接数据库时提示连接超时或数据库不存在,这时可通过windows命令行模下输入网络命令:“telnet 转换器IP地址 50000”,若提示连接失败,则与路由器、防火墙配置有关 3) 配置完毕后,可输入设备编号,通过 “通讯测试” 功能进行设备通讯情况调试,具体操作方及描述见下表: RS485及TCP/IP网络质量测试操作指南 所有消费机组网联网、修改好设备编号、配置好上述通讯配置后,把消费机全部连接到网络上,然后进行设备通讯情况测试,测试时把每一台消费机设备编号在“机号”处输入,然后点通讯测试进行联网通讯(布线质量)测试,测试一般发送1000个包,点停止后可看到通讯质量。若通讯质量无法达到100%,请遵循下表整改建议: 通讯质量 布线整改建议 0.00% 网络完全不通,建议: 1、 检查计算机通讯端口与收发器端口是否相符、通讯波特率是否正确; 2、 检查设备类型、设备编号是否正确; 3、 RS485线路是否符合规范,网络有没有短路或开路现象; 4、 RS485转换器与电脑串口间接线是否有问题; 5、 RS485与设备通讯接口是否已经接好,设备是否在开机状态 95%以下 网络不稳定,建议: 1、 RS485线路是否符合规范,网络有没有短路(铜线毛刺造成的短路)现象; 2、 RS485转换器与电脑串口间接线是否有问题(端口是否接紧了); 3、 设备RS485通讯端口(水晶头)制作是否符号568B标准(检查压好了没); 4、 检查通讯线路是否过远,请调整网络结构并在末端接上120Ω终端电阻; 5、 网络接线时,采用了非标准总线接线方 95%以上 网络不太理想,但还可以接受。建议在网络末端接上120Ω终端电阻或更换更好的RS485转换器 100% 网络稳定没通讯丢包现象 无线网络质量测试操作指南 所有消费机修改好设备编号,收发器、中继器通好电,配置好上述通讯配置后,进行设备通讯情况测试,测试时把每一台消费机设备编号在“机号”处输入,路由信息配置好(配置方法见下表),然后点通讯测试进行联网通讯(布线质量)测试,测试一般发送1000个包,点停止后可看到通讯质量。若通讯质量无法达到90%,请遵循下表整改建议。 A、路由信息配置方法:在路由信息输入框里有10个“0”,其中每两位为一组,即:00 00 00 00 00。其中第一组的为第一个中继编号,第二组为第二个中继编号,依此类推。设置时,例如现有一台无线收发器和一台无线一卡通终端设备,从收发器到一卡通终端设备必须经过一个编号为1的无线中继器,那么路由信息数字第一组的00改为01;从收发器到一卡通终端设备必须先经过一个编号为1的无线中继器再经过一个编号为11的无线中继器,那么路由信息数字第一组的00改为01,第二组的00改为11,如右图所示;依此类推。 B、通讯优化整改建议表: 通讯质量 建议 0.00% 网络完全不通,建议: 1、 检查计算机通讯端口与收发器端口是否相符、通讯波特率是否正确; 2、 检查设备类型、设备编号是否正确; 3、 检查无线设备是否已经全部接好且处于正常通电状态; 4、 检查无线路由设置信息有没有设好; 5、 检查通讯距离是否过远 75%以下 网络不稳定,建议: 1、 检查无线路由设置信息有没有设好; 2、 检查通讯距离是否符合标准; 3、 检查设备安装位置是否符合标准 75%-90% 网络不够理想,建议: 1、 检查并调整无线设备安装位置; 4) 所有网络调整完毕,设备通讯达到要求后,可通过 “自动搜索新设备” 页面,把所有设备自动搜索出来并完成设备添加工作; 5) 设备添加完毕后,请立即点击 “连接测试”、“校对时间”、“下载密码” 三个按钮进行时间校对及IC卡密码下载工作; 6) 设备添加完毕后,消费机默认名称为“消费机+设备编号”,如1号消费机则默认名字消费机1,建议所有消费机名称都修改好,比如1号窗、2号窗等,这样有利于优化报表查询,分类统计信息也更为丰富,为食堂老板提供有效的决策支持。 5.消费管理 5.1消费场所设置 消费场所主要体现于消费系统中。系统内默认消费场所名称为“食堂1”。我们建议用户在安装调试好消费机后,根据不同地方餐厅或消费点划分为各个不同区域的消费点,如1楼食堂、2楼食堂、超市等都可以单独划分消费场所。划分后有利于优化报表查询,分类统计信息也更为丰富,方便您在日后生成对消费报表的各类统计。 1) 点 “消费管理”→“消费场所设置” 进入消费场所设置界面,点添加按钮,输入消费场所名字,确认后完成添加操作; 2) 把该场所内对应消费机添加进去,若刚刚的消费机名字为1号窗口、2号窗口等,添加后立即可在各消费报表内看到效果:场所(1楼食堂),下属消费机(1号窗、2号窗)。 5.2餐别资料设置 餐别资料设置用餐时间及每个餐别对应的收费价格类别。每个餐别最大可设置3个金额类别,每天可设置最多4个餐别(早餐、中餐、晚餐、宵夜)。餐别时间系统根据常规使用自动创建,用户也可根据自己使用情况自行修改。 1) 点 “消费管理”→“餐别资料设置” 进入设置界面,双击修改,按实际情况输入金额及开餐时间,修改后点保存关闭。 注意,有时候用户反映营业收入统计表内金额与消费机内当天统计金额不符,这是由于餐别时间设置有误造成的,错误原因为两点,见下表: 错误设置1 餐别时间设置范围为00:00-23:59,不能跨日设置。因此有时候设置成20:00-03:00等时间时,因设置无效导致报表错误。 错误设置2 假设早餐在系统内设置时间为07:00-09:00,但实际食堂07:00前开餐,此时采集数据后,在营业收入统计表内07:00前的消费不纳入早餐统计范围。 5.3补贴设置 09版消费系统支持补贴发放功能。补贴发放功能可使用读卡器进行发放,或使用专门补贴机进行发放。 1) 点 “消费管理”→“补贴设置” 进入补贴设置界面,在补贴类型处右键→ “增加” ,输入补贴名称、补贴金额,设置补贴有效期及选择补贴钱包类型(可选主钱包追加、副钱包追加、副钱包覆盖三种),设置后点保存退出; 设置项 项描述 主钱包追加 设置补贴金额追加进主钱包内(领取补贴时,已追加形追加到主钱包中,此时实际存款与补贴金额可能无法区分) 副钱包追加 设置补贴金额追加进主钱包内 副钱包覆盖 设置补贴金额覆盖副钱包内原有金额 注意,副钱包补贴默认最大650.00元,可通过消费设备参数设置,把补贴单位从分改为角,则可支持最大6500.0元。一般建议使用副钱包补贴。消费设备参数设置具体内容,详见本文6。 2) 增加补贴类型后,需要进行人员绑定操作。单击补贴类型、选取可领取补贴的人,双击鼠标左键(或选择部门、全体,点添加所有按钮),点保存完成设置; 3) 在人员列表处选择人员右键→查看补贴情况,可看到该人员所有补贴领取情况。 4) 补贴设置完毕后,持卡人可领取补贴。领取补贴方法有两种:1、通过软件补贴数据上传功能把补贴上传至补贴机,然后人员持卡到补贴机上刷卡补贴;2、通过软件领取补贴功能,在读卡器上读卡领取补贴。 补贴数据的上传(有补贴机时) 选择消费补贴管理菜单补贴名单上传,选择要上传的补贴机及补贴类型,点上传即可。 注意:  每次设置补贴前请先进行数据采集;  上传补贴有覆盖和增加两个按钮,覆盖是先清空补贴机上原有补贴再把本次补贴上传至设备。增加上传不改变原有补贴情况下把本次补贴上传至设备;  补贴上传时,若遇到通讯超时,可再次上传该补贴,但必须注意此时不能使用覆盖上传,只能使用增加上传;  已上传的补贴,在未领取补贴人员名单内可看到状态“已上传补贴机”,点解冻按钮,状态回到原本的“未领取”状态,可重新进行上传。 补贴的领取(没补贴机时) “卡片中心”→“领取补贴”→“读卡”→“补贴”。 6.消费参数配置 消费机参数设置对系统至关重要。消费机参数设置模块内,可对所有消费设备及消费扩展设备包括消费机、订餐机、补贴机、充值机等进行功能配置。新设备进行系统配置、联网调试、完成设备添加、编号修改、下载密码后,在使用前应先进行消费机参数设置,通过配置定义消费机各功能组合项目。 1) 点 “消费管理”→“消费设备参数设置” 进入设置界面; 2) 在右侧设备列表栏点选一台消费机或任意,然后点读取数据,设置完毕后点写入设备完成设置。注意,读取数据与写入设备按钮有两组,其中上方的读取数据与写入设备按钮功能为读取/写入机能内全部可设置数据,下方的按钮则只读取当页信息。 6.1消费设备参数设置项详解 项 项描述 限制方 可选择限餐及按日、按周、按月进行消费限制 注意:限餐只允许每餐次消费一次,按日、按周、按月三类限制可设置限期内最大消费次数0-255,最大消费金额0-650,其中0为不限制 按餐别时间规则定义消费机允许消费餐别时间段; 按日限制时间以当天0:00-23:59为有效限制时间; 按周限制时间为从消费限制设置当天开始计算后推7天为有效限制时间; 按月限制时间为当月为有效限制时间。 当选择为限餐时,请启用刷卡时段检查,否则设置无效 重复刷卡检查 定义IC卡多少秒内不允许重复刷卡,可防止定额状态时多刷卡情况 卡内最大允许金额 可设置限制数值0-650 当设置项为0时,消费机不限制卡内余额 刷卡分组检查及分组标识 若启用刷卡分组检查,请选择消费机对应允许刷卡的分组标识 刷卡分组功能可通过预先定义好的分组资料对吃饭人员进行分组操作,假设A员工定义分组为A,B员工定义分组为B,在消费机上启用刷卡分组后,A员工只能在分组为A的消费机上刷卡,B员工只能在分组为B的消费机上刷卡。 系统支持最大可定义15个分组。 刷卡时段检查 若启动刷卡时段检查,请切换到消费时段,并选择消费机允许消费的餐别时间段。 启用刷卡时段检查后,消费机自动进入定额消费模且锁键盘,到预定时间后消费机显示金额自动切换改变,时段外消费机不工作。 钱包设置 仅主钱包(读卡时只读取主钱包内金额,不读取副钱包内金额;消费时只消费主钱包内金额,主钱包内余额不够扣款也不消费副钱包内金额) 主钱包优先(读卡时先读取主钱包内金额,再读取副钱包内金额;消费时优先消费主钱包内金额,主钱包内余额不够扣款后再消费副钱包内金额) 仅副钱包(读卡时先读取副钱包内金额,再读取主钱包内金额;消费时先消费副钱包内金额,副钱包内余额不够扣款也不消费主钱包内金额) 副钱包优先(读卡时先读取副钱包内金额,再读取主钱包内金额;消费时优先消费副钱包内金额,副钱包内余额不够扣款后再消费主钱包内金额) 消费类型 可选正常消费、订餐消费两项。 若系统内有订餐,请选择订餐消费,其余选择正常消费 名单类型 可切换名单类型。 当前为黑名单:消费名单被视为黑名单,不允许消费 当前为白名单:消费名单被视为白名单,允许消费 黑名单检查 检查(名单类型当前为黑名单时必选) 白名单检查 检查(名单类型当前为白名单时必选) 消费模 可选金额消费、计次消费两项目切换。 选择为计次消费模时,消费机为计次消费模,消费只记录次数,不进行扣款 刷卡时间间隔 两张不同卡刷卡时,之间的时间间隔,建议不检查 挂帐标志 是否允许挂帐,挂帐消费模时,请选择允许挂帐 操作密码 修改消费机管理密码 最大挂帐金额 最大允许挂帐金额限制,仅在挂帐模时有效 消费时段 按要求设置可进行允许消费的时段,时段外消费机将不工作。 普通消费模下启用消费时段检查,消费机将变成定额消费模,时段内餐次金额自动切换无需人手调整。 订餐模下则必须启用消费时段检查。 消费时段设置注意: 1、设置前请先设置后餐别资料; 2、可设置四个不同餐别,每个餐别只允许设置一个金额类型,不能重复。 菜单消费 设置菜单消费项,每一(菜单)项可对应一个金额。正常消费模、补贴消费模、挂帐消费模有效 设备功能 可选择消费机及读卡器两个功能。当选择为读卡器功能时,消费机屏幕显示全F,把消费机直接通过COM口连接后,可作为串口读卡器使用。切换读卡器模后后重启消费机即自动切换回消费机状态。 无线消费机不支持读卡器模切换。 管理卡号 通过写入10位10进制卡号到设备后,可使用该卡作为管理卡进行锁机、解锁操作(此功能充值机有效)。 6.2各模下消费机功能组合配置指南 1、正常消费 必要设置项 项目描述及设置建议 钱包设置 仅主钱包 消费类型 正常消费 消费模 金额消费 黑名单检查 检查(名单类型当前为黑名单时必选) 2、按餐别时间定值消费 必要设置项 项目描述及设置建议 钱包设置 仅主钱包 消费类型 正常消费 消费模 金额消费 黑名单检查 检查(名单类型当前为黑名单时必选) 刷卡时段检查 检查 消费时段 按要求设置可进行订餐消费的时段 消费时段设置注意: 1、设置前请先设置后餐别资料; 2、可设置四个不同餐别,每个餐别只允许设置一个金额类型,不能重复。 3、挂帐消费 关键设置项 项目描述及设置建议 钱包设置 主钱包优先 注意:挂帐消费模不能选择副钱包优先,否则消费机先挂帐,再扣款 消费类型 正常消费 消费模 金额消费 黑名单检查 检查 挂帐标志 允许挂帐 最大挂帐金额 可设置0-650,其中0为挂帐无效,选择挂帐后默认最大挂帐金额650 4、补贴消费 关键设置项 项目描述及设置建议 钱包设置 副钱包优先 消费类型 正常消费 消费模 金额消费 卡有效期检查 检查(设为检查后,补贴金额过期不能使用并自动切换本金消费) 黑名单检查 检查(名单类型当前为黑名单时必选) 5、计次消费 关键设置项 项目描述及设置建议 消费类型 正常消费 消费模 计次消费 黑名单检查 检查(名单类型当前为黑名单时必选) 钱包设置 仅主钱包 刷卡时段检查 检查 消费时段 按要求设置可进行订餐消费的时段 消费时段设置注意: 1、设置前请先设置后餐别资料; 2、可设置四个不同餐别,每个餐别只允许设置一个金额类型,不能重复。 限制方 限餐 6、订餐消费 关键设置项 项目描述及设置建议 消费类型 订餐消费 消费模 金额消费 黑名单检查 检查(名单类型当前为黑名单时必选) 刷卡时段检查 检查 限制方 限餐 消费时段 按要求设置可进行订餐消费的时段 消费时段设置注意: 1、设置前请先设置后餐别资料; 注意,消费机在订餐模下,可选择两种设定: 正常订餐 正常订餐模下,设定该消费机订餐消费的金额类别后,假设设置消费机金额类别为1,若订餐选择金额为1类,则可消费,若订其余2、3类别金额,则不能消费 非固定订餐 非固定订餐模下,设定该消费机无论任何订餐餐别金额,都允许消费。消费时屏幕显示人员订餐金额。使用非固定订餐,需要切换到“消费金额”下,点一下刷新按钮,然后写入数据 6.3订餐机功能组合配置指南 1、常规快捷键订餐、时间段订餐 关键设置项 项目描述及设置建议 液晶屏欢迎文字 可自定义八个中文字符 刷卡时段检查 不检查 黑名单检查 检查 订餐时段限制 刷新时段 2、时段刷卡订餐(设置指定什么时间刷卡订哪一餐) 关键设置项 项目描述及设置建议 液晶屏欢迎文字 可自定义八个中文字符 刷卡时段检查 检查 黑名单检查 检查 订餐时段限制 刷新时段 订餐时段 按要求设置什么时间刷卡订哪一个餐 消费时段设置注意: 1、设置前请先设置后餐别资料; 2、可设置最多为今天早、中、晚、宵,明天早、中、晚、宵八个不同餐别,每个餐别只允许设置一个金额类型,不能重复。 7.挂失与补卡 挂失卡与上传黑名单操作 1) 点 “卡片中心”→“挂失管理” 进入卡挂失界面; 2) 鼠标选择部门、人员(也可以输入编号或姓名查询),双击人员进行挂失(解挂)操作; 3) 挂失操作后,点关闭按钮,直接提示是否上传黑名单,点“是”; 4) 对话框提示“黑名单请按是,白名单请按否,自定义按取消”,按实际情况选择,一般默认使用黑名单,选“是”; 注意:上传名单时,有“上传全部名单”和“增加名单”两个按钮可选择,上传全部是重新上传所有名单。增加上传是直接把本次操作的名单追加上去;同样,“清除全部名单”和“删除名单”功能也相类似,清除全部名单就是把消费机内已上传名单全部删除,删除名单只把本次进行解挂失的卡删除。 补卡操作 1) 点 “卡片中心”→“补办新卡” 进入补卡; 2) 双击需要补卡人员,点“读卡”→“补卡”,即完成补卡工作,补卡后原来旧卡为注销状态不能使用,旧卡内所有金额已注入新卡中。 注意:补卡有补发挂失卡与补发坏卡两个选项,补发挂失卡要求该卡必须挂失后才能补发。补发坏卡则可把已挂失或未挂失卡人员重新进行补卡工作,建议补发坏卡时要求坏卡没收; 8.消费报表的查看 经典消费系统报表分为三类人服务。第一类为食堂老板,他所关心的是他的食堂营业收入状态;第二类是持卡人,他所关心的是他某天的消费清单,是不是扣错款啦;第三类是出纳,他管钱的,他关心的是他每天的现金收支情况。 每一类系统使用人员,我们都有对应其专用的报表。食堂老板有营业收入统计表,持卡人有个人消费统计表,出纳有现金收支日报表。下面简单介绍一下报表查看操作: 8.1营业收入统计表 1) 点 “消费管理”→“营业收入统计表” 进入营业收入统计表界面; 2) 用户可按意愿选择日期、消费点、所属消费机、部门、餐次等,选择完毕后点查询可看到报表内容。 营业收入统计表用于日常食堂营业收入统计,表内可按时间、餐别、消费点、消费机、部门等不同条件进行组合查询,查询结果可汇总、可按日显示、也可显示明细。 营业收入统计表拥有自定义报表功能,可通过自定义按钮选择您需要的报表信息。 输出报表后,可通过导出功能把报表结果导出至Excel表格。 注意:营业收入统计表内有一项为未处理非确定交易,非确定交易意思就是消费机未知道当次刷卡是否已经正确完成扣款操作,因此消费机内保存该卡卡号、消费时间、金额,并标记该记录为非确定交易。注意,当出现非确定交易记录时,该卡进行存款或取款、退卡等操作时,软件自动提示是否处理,点处理则自动判断非确定交易记录是否正确扣款,若没有正确扣款,则在卡上重新抵扣。 8.2个人消费统计表 1) 点 “消费管理”→“个人消费统计表” 进入个人消费统计表界面; 2) 用户可按意愿选择日期、部门、人员、餐次等,选择完毕后点查询可看到报表内容。 个人消费统计表用于查询个人消费记录、状态,表内可按时间、餐别、人员、部门等不同条件进行组合查询,查询结果一般为个人消费明细及汇总(报表若不输入人员时,默认显示全部)。 个人消费统计表拥有自定义报表功能,可通过自定义按钮选择您需要的报表信息。 输出报表后,可通过导出功能把报表结果导出至Excel表格。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值