整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

CAD中单行文字和多行文字的互换技巧

CAD中单行文字和多行文字的互换技巧

AD也疯狂

首先我们来了解一下CAD单行文字和多行文字各自的优势。

单行文字优势:格式简单、控制容易,还可以输入钢筋符号的特殊符号;

多行文字优势:支持换行,支持段落、制表位,编写大段文字有明显优势。

我们知道,多行文字用X炸开就可以变成单行文字,那如果希望将单行文字变成多行文字怎么办呢?

其实,CAD自带有这样一个合并的功能,命令为:TXT2MTXT。只是目前只有CAD高版本才有,想知道你的CAD版本是否支持,可以输入这个命令,回车一下,看是否能执行就可以了,如果显示是未知命令,那就是不支持了。

如果显示是未知命令,那就是不支持了。

这个命令的操作很简单,和平常命令操作一样,执行命令后选择要合并的单行文字就可以了。并且,在执行命令后,命令行会提供了一个选项:设置(SE),可以设置合并时单行文字的排序方式,默认是从上往下排序,也可以设置成按选择的顺序排序。

如果没有特殊需要,就不需要修改设置。

下面来看看效果

转换前

转换前的效果是三个独立的单行文字。

输入命令选择文字会提示

转换后会提示

最后的效果

不过最后的效果也可能是另外一种情况

不过最后的效果也可能是这种情况

出现这种情况时,可以尝试在设置(SE)时勾选“自动换行文字”或者手动对多行文字进行调整

勾选“自动换行文字”

本期的技巧就分享到这了,如果你有其它更好的方法,欢迎留言和大家分享哦,谢谢关注!

口调试

串口调试主要有 根据/proc系统信息确认串口状态,stty命令,编程调试 三种调试方法,下面我们分别具体介绍下。

根据设备节点确认串口是否正常

系统上电时,默认会使能串口,我们可以通过dmesg | grep ttyS 查看系统加载的串口设备。

也可以通过 cat /proc/tty/driver/serial 查看串口信息。

如果执行 echo "123" > /dev/ttyS4 ,则会发送数据到ttyS4,通过串口线将串口接到PC 串口助手,确认是否收到数据。

如果此时再去查看串口设备,会看到uart4 的tx 发送了5个字符。

stty 命令

stty语法

stty --help

Usage: stty [-F DEVICE] [--file=DEVICE] [SETTING]...
  or: stty [-F DEVICE] [--file=DEVICE] [-a|--all]
  or: stty [-F DEVICE] [--file=DEVICE] [-g|--save]
[选项]
-a, --all :   以容易阅读的方式打印当前的所有配置;
-g, --save: 以stty终端可读方式打印当前的所有配置。
-F, --file:   打印当前的所有设置打开指定的设备,并用此设备作为输入来代替标准输入
[参数]
终端设置:指定终端命令行的设置选项。  

串口配置

stty -F /dev/ttyS0 speed 115200 cs8 -parenb -cstopb

设置串口ttyS0波特率为115200,8位数据位,1位停止位,无校验位。

查看串口属性

stty -a -F /dev/ttyS0
speed 9600 baud; rows 0; columns 0; line=0;
intr=^C; quit=^\; erase=^?; kill=^U; eof=^D; eol=<undef>;
eol2=<undef>; swtch=<undef>; start=^Q; stop=^S; susp=^Z; rprnt=^R;
werase=^W; lnext=^V; discard=^O; min=1; time=0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke -flusho -extproc

stty参数含义

特殊字符:
  dsusp 字符   每当输入刷新时会发送一个用于终端阻塞信号的字符
   eof  字符    表示文件末尾而发送的字符(用于终止输入)
   eol  字符    为表示行尾而发送的字符
  eol2 字符    为表示行尾而发送的另一个可选字符
   erase 字符   擦除前一个输入文字的字符
   intr 字符    用于发送中断信号的字符
   kill 字符    用于擦除当前终端行的字符
  lnext 字符   用于输入下一个引用文字的字符
   quit 字符    用于发送退出信号的字符
  rprnt 字符   用于重绘当前行的字符
   start 字符   在停止后重新开启输出的字符
   stop 字符    停止输出的字符
   susp 字符    发送终端阻断信号的字符
  swtch 字符   在不同的shell 层次间切换的字符
  werase 字符  擦除前一个输入的单词的字符
 
特殊设置:
   N            设置输入输出速度为N 波特
  cols N       统治内核终端上有N 栏
  columns N    等于cols N
   ispeed N     设置输入速度为N 波特
  line N       设置行约束规则为N
   min N        和 -icanon 配合使用,设置每次一完整读入的最小字符数为<N>
   ospeed N     设置输出速度为N 波特
  rows N       向内核通告此终端有N 行
  size         根据内核信息输出当前终端的行数和列数
   speed        输出终端速度(单位为波特)
   time N       和-icanon 配合使用,设置读取超时为N 个十分之一秒
 
控制设置:
   [-]clocal    禁用调制解调器控制信号
   [-]cread     允许接收输入
  [-]crtscts   启用RTS/CTS 握手
   csN          设置字符大小为N 位,N 的范围为5 到8
   [-]cstopb    每个字符使用2 位停止位 (要恢复成1 位配合"-"即可)
   [-]hup       当最后一个进程关闭标准终端后发送挂起信号
   [-]hupcl     等于[-]hup
   [-]parenb    对输出生成奇偶校验位并等待输入的奇偶校验位
   [-]parodd    设置校验位为奇数 (配合"-"则为偶数)
 
输入设置:
   [-]brkint    任务中断会触发中断信号
   [-]icrnl     将回车转换为换行符
   [-]ignbrk    忽略中断字符
   [-]igncr     忽略回车
   [-]ignpar    忽略含有奇偶不对称错误的字符
  [-]imaxbel   发出终端响铃但不刷新字符的完整输入缓冲
   [-]inlcr     将换行符转换为回车
   [-]inpck     启用输入奇偶性校验
   [-]istrip    剥除输入字符的高8 位比特
  [-]iutf8     假定输入字符都是UTF-8 编码
  [-]iuclc     将大写字母转换为小写
  [-]ixany     使得任何字符都会重启输出,不仅仅是起始字符
   [-]ixoff     启用开始/停止字符传送
   [-]ixon      启用XON/XOFF 流控制
   [-]parmrk    标记奇偶校验错误 (结合255-0 字符序列)
   [-]tandem    等于[-]ixoff
 
输出设置:
  bsN          退格延迟的风格,N 的值为0 至1
  crN          回车延迟的风格,N 的值为0 至3
  ffN          换页延迟的风格,N 的值为0 至1
  nlN          换行延迟的风格,N 的值为0 至1
  [-]ocrnl     将回车转换为换行符
  [-]ofdel     使用删除字符代替空字符作填充
  [-]ofill     延迟时使用字符填充代替定时器同步
  [-]olcuc     转换小写字母为大写
  [-]onlcr     将换行符转换为回车
  [-]onlret    使得换行符的行为表现和回车相同
  [-]onocr     不在第一列输出回车
   [-]opost     后续进程输出
  tabN         水平制表符延迟的风格,N 的值为0 至3
  tabs         等于tab0
  -tabs        等于tab3
  vtN          垂直制表符延迟的风格,N 的值为0 至1
 
本地设置:
   [-]crterase  擦除字符回显为退格符
  crtkill      依照echoprt 和echoe 的设置清除所有行
  -crtkill     依照echoctl 和echol 的设置清除所有行
  [-]ctlecho   在头字符中输出控制符号("^c")
   [-]echo      回显输入字符
  [-]echoctl   等于[-]ctlecho
   [-]echoe     等于[-]crterase
   [-]echok     在每清除一个字符后输出一次换行
  [-]echoke    等于[-]crtkill 意义相同
   [-]echonl    即使没有回显任何其它字符也输出换行
  [-]echoprt   在"\"和"/"之间向后显示擦除的字符
   [-]icanon    启用erase、kill、werase 和rprnt 等特殊字符
   [-]iexten    允许POSIX 标准以外的特殊字符
   [-]isig      启用interrupt、quit和suspend 等特殊字符
   [-]noflsh    在interrupt 和 quit 特殊字符后禁止刷新
  [-]prterase  等于[-]echoprt
  [-]tostop    中止尝试向终端写入数据的后台任务
  [-]xcase     和icanon 配合使用,用转义符"\"退出大写状态
 
综合设置:
  [-]LCASE     等于[-]lcase
   cbreak       等于-icanon
   -cbreak      等于icanon
   cooked       等于brkint ignpar istrip icrnl ixon opost isig icanon eof eol 等的默认值
   -cooked      等于-raw
   crt          等于echoe echoctl echoke
   dec          等于echoe echoctl echoke -ixany intr ^c erase 0177 kill ^u
  [-]decctlq   等于[-]ixany
   ek           清除所有字符,将它们回溯为默认值
   evenp        等于parenb -parodd cs7
   -evenp       等于-parenb cs8
  [-]lcase     等于xcase iuclc olcuc
   litout       等于-parenb -istrip -opost cs8
   -litout      等于parenb istrip opost cs7
   nl           等于-icrnl -onlcr
   -nl          等于icrnl -inlcr -igncr onlcr -ocrnl -onlret
   oddp         等于parenb parodd cs7
   -oddp        等于-parenb cs8
   [-]parity    等于[-]evenp
   pass8        等于-parenb -istrip cs8
   -pass8       等于parenb istrip cs7
   raw          等于-ignbrk -brkint -ignpar -parmrk -inpck -istrip
                 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany
                 -imaxbel -opost -isig -icanon -xcase min 1 time 0
   -raw         等于cooked
   sane         等于cread -ignbrk brkint -inlcr -igncr icrnl -iutf8
                -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr
                -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
                isig icanon iexten echo echoe echok -echonl -noflsh
                -xcase -tostop -echoprt echoctl echoke,
                所有特殊字符均使用默认值

串口编程调试

串口相关操作

在Linux下,除了网络设备,其余的都是文件的形式,串口设备也一样在/dev下。

打开串口

示例:

fd=open("/dev/ttyUSB0",O_RDWR|O_NOCTTY|O_NDELAY);

在打开串口时,除了需要用到 O_RDWR (可读写)选项标志外,

O_NOCTTY:告诉 Linux “本程序不作为串口的‘控制终端’”。如果不使用该选项,会有一些输入字符影响进程运行(如一些产生中断信号的键盘输入字符等)。

O_NDELAY:``标志则是告诉Linux,这个程序并不关心DCD信号线的状态——也就是不关心端口另一端是否已经连接。

关闭串口:

close(fd)

读写串口:

与普通文件一样,使用read,write函数。 示例:

read(fd,buff,8);
write(fd,buff,8);

串口属性设置

很多系统都支持POSIX终端(串口)接口.程序可以利用这个接口来改变终端的参数,比如,波特率,字符大小等等.要使用这个端口的话,你必须将<termios.h>头文件包含到你的程序中。这个头文件中定义了终端控制结构体和POSIX控制函数。

termios 结构体:

struct termios {
  tcflag_t c_cflag    / 控制标志
  tcflag_t c_iflag;   / 输入标志
  tcflag_t c_oflag;   / 输出标志
  tcflag_t c_lflag;   / 本地标志
  tcflag_t c_cc[NCCS]; / 控制字符
};

其中我们更关注的是c_cflag控制选项。其中包含了波特率、数据位、校验位、停止位的设置。

c_cflag 控制标志常量

  • CBAUD   (不属于 POSIX) 波特率掩码 (4+1 位)。
  • CBAUDEX  (不属于 POSIX) 扩展的波特率掩码 (1 位),包含在 CBAUD 中。(POSIX 规定波特率存储在 termios 结构中,并未精确指定它的位置,而是提供了函数 cfgetispeed() 和 cfsetispeed() 来存取它。一些系统使用 c_cflag 中 CBAUD 选择的位,其他系统使用单独的变量,例如 sg_ispeed 和 sg_ospeed 。)
  • CSIZE   字符长度掩码。取值为 CS5, CS6, CS7, 或 CS8。
  • CSTOPB 设置两个停止位,而不是一个。
  • CREAD 打开接受者。
  • PARENB  允许输出产生奇偶信息以及输入的奇偶校验。
  • PARODD 输入和输出是奇校验。
  • HUPCL   在最后一个进程关闭设备后,降低 modem 控制线 (挂断)。(?)
  • CLOCAL 忽略 modem 控制线。
  • LOBLK   (不属于 POSIX) 从非当前 shell 层阻塞输出(用于 shl )。(?)
  • CIBAUD (不属于 POSIX) 输入速度的掩码。CIBAUD 各位的值与 CBAUD 各位相同,左移了 IBSHIFT 位。
  • CRTSCTS  (不属于 POSIX) 启用 RTS/CTS (硬件) 流控制。

c_iflag 输入标志常量

  • IGNBRK   忽略输入中的 BREAK 状态。
  • BRKINT   如果设置了 IGNBRK,将忽略 BREAK。如果没有设置,但是设置了 BRKINT,那么 BREAK 将使得输入和输出队列被刷新,如果终端是一个前台进程组的控制终端,这个进程组中所有进程将收到 SIGINT 信号。如果既未设置 IGNBRK 也未设置 BRKINT,BREAK 将视为与 NUL 字符同义,除非设置了 PARMRK,这种情况下它被视为序列 7 >BRKINT   如果设置了 IGNBRK,将忽略 BREAK。如果没有设置,但是设置了 BRKINT,那么 BREAK 将使得输入和输出队列被刷新,如果终端是一个前台进程组的控制终端,这个进程组中所有进程将收到 SIGINT 信号。如果既未设置 IGNBRK 也未设置 BRKINT,BREAK 将视为与 NUL 字符同义,除非设置了 PARMRK,这种情况下它被视为序列 \377 \0 \0。< >BRKINT   如果设置了 IGNBRK,将忽略 BREAK。如果没有设置,但是设置了 BRKINT,那么 BREAK 将使得输入和输出队列被刷新,如果终端是一个前台进程组的控制终端,这个进程组中所有进程将收到 SIGINT 信号。如果既未设置 IGNBRK 也未设置 BRKINT,BREAK 将视为与 NUL 字符同义,除非设置了 PARMRK,这种情况下它被视为序列 \377 \0 \0。<。
  • IGNPAR   忽略桢错误和奇偶校验错。
  • PARMRK  如果没有设置 IGNPAR,在有奇偶校验错或桢错误的字符前插入 7 >PARMRK  如果没有设置 IGNPAR,在有奇偶校验错或桢错误的字符前插入 \377 \0。如果既没有设置 IGNPAR 也没有设PARMRK,将有奇偶校验错或桢错误的字符视为 \0。<。如果既没有设置 IGNPAR 也没有设PARMRK,将有奇偶校验错或桢错误的字符视为 >PARMRK  如果没有设置 IGNPAR,在有奇偶校验错或桢错误的字符前插入 \377 \0。如果既没有设置 IGNPAR 也没有设PARMRK,将有奇偶校验错或桢错误的字符视为 \0。<。
  • INPCK   启用输入奇偶检测。
  • ISTRIP  去掉第八位。
  • INLCR   将输入中的 NL 翻译为 CR。
  • IGNCR   忽略输入中的回车。
  • ICRNL   将输入中的回车翻译为新行 (除非设置了 IGNCR)。
  • IUCLC   (不属于 POSIX) 将输入中的大写字母映射为小写字母。
  • IXON    启用输出的 XON/XOFF 流控制。
  • IXANY  (不属于 POSIX.1;XSI) 允许任何字符来重新开始输出。(?)
  • IXOFF  启用输入的 XON/XOFF 流控制。
  • IMAXBEL (不属于 POSIX) 当输入队列满时响零。Linux 没有实现这一位,总是将它视为已设置。

c_oflag 输出标志常量

  • OPOST   启用具体实现自行定义的输出处理。其余 c_oflag 标志常量定义在 POSIX 1003.1-2001 中,除非另外说明。
  • OLCUC   (不属于 POSIX) 将输出中的小写字母映射为大写字母。
  • ONLCR   (XSI) 将输出中的新行符映射为回车-换行。
  • OCRNL   将输出中的回车映射为新行符
  • ONOCR 不在第 0 列输出回车。
  • ONLRET 不输出回车。
  • OFILL 发送填充字符作为延时,而不是使用定时来延时。
  • OFDEL   (不属于 POSIX) 填充字符是 ASCII DEL (0177)。如果不设置,填充字符则是 ASCII NUL。
  • NLDLY   新行延时掩码。取值为 NL0 和 NL1。
  • CRDLY   回车延时掩码。取值为 CR0, CR1, CR2, 或 CR3。
  • TABDLY  水平跳格延时掩码。取值为 TAB0, TAB1, TAB2, TAB3 (或 XTABS)。取值为 TAB3,即 XTABS,将扩展跳格为空格 (每个跳格符填充 8 个空格)。(?)
  • BSDLY   回退延时掩码。取值为 BS0 或 BS1。(从来没有被实现过)
  • VTDLY   竖直跳格延时掩码。取值为 VT0 或 VT1。
  • FFDLY   进表延时掩码。取值为 FF0 或 FF1。

c_lflag 本地标志常量

  • ISIG    当接受到字符 INTR, QUIT, SUSP, 或 DSUSP 时,产生相应的信号。
  • ICANON   启用标准模式 (canonical mode)。允许使用特殊字符 EOF, EOL, EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS, 和 WERASE,以及按行的缓冲。
  • XCASE   (不属于 POSIX; Linux 下不被支持) 如果同时设置了 ICANON,终端只有大写。输入被转换为小写,除了以 \ 前缀的字符。输出时,大写字符被前缀 \,小写字符被转换成大写。
  • ECHO    回显输入字符。
  • ECHOE  如果同时设置了 ICANON,字符 ERASE 擦除前一个输入字符,WERASE 擦除前一个词。
  • ECHOK  如果同时设置了 ICANON,字符 KILL 删除当前行。
  • ECHONL  如果同时设置了 ICANON,回显字符 NL,即使没有设置 ECHO。
  • ECHOCTL (不属于 POSIX) 如果同时设置了 ECHO,除了 TAB, NL, START, 和 STOP 之外的 ASCII 控制信号被回显为 ^X, 这里 X 是比控制信号大 0x40 的 ASCII 码。例如,字符 0x08 (BS) 被回显为 ^H。
  • ECHOPRT (不属于 POSIX) 如果同时设置了 ICANON 和 IECHO,字符在删除的同时被打印。
  • ECHOKE   (不属于 POSIX) 如果同时设置了 ICANON,回显 KILL 时将删除一行中的每个字符,如同指定了 ECHOE 和 ECHOPRT 一样。
  • DEFECHO (不属于 POSIX) 只在一个进程读的时候回显。
  • FLUSHO   (不属于 POSIX; Linux 下不被支持) 输出被刷新。这个标志可以通过键入字符 DISCARD 来开关。
  • NOFLSH   禁止在产生 SIGINT, SIGQUIT 和 SIGSUSP 信号时刷新输入和输出队列。
  • TOSTOP   向试图写控制终端的后台进程组发送 SIGTTOU 信号。IEXTEN   启用实现自定义的输入处理。这个标志必须与ICANON 同时使用,才能解释特殊字符 EOL2,LNEXT,REPRINT 和 WERASE,IUCLC 标志才有效。

c_cc 特殊的控制字符

  • VINTR   (003, ETX, Ctrl-C, or also 0177, DEL, rubout) 中断字符。发出 SIGINT 信号。当设置 ISIG 时可被识别,不再作为输入传递。
  • VQUIT   (034, FS, Ctrl-) 退出字符。发出 SIGQUIT 信号。当设置 ISIG 时可被识别,不再作为输入传递。
  • VERASE  (0177, DEL, rubout, or 010, BS, Ctrl-H, or also #) 删除字符。删除上一个还没有删掉的字符,但不删除上一个 EOF 或行首。当设置 ICANON 时可被识别,不再作为输入传递。
  • VKILL   (025, NAK, Ctrl-U, or Ctrl-X, or also @) 终止字符。删除自上一个 EOF 或行首以来的输入。当设置 ICANON 时可被识别,不再作为输入传递。
  • VEOF   (004, EOT, Ctrl-D) 文件尾字符。更精确地说,这个字符使得 tty 缓冲中的内容被送到等待输入的用户程序中,而不必等到 EOL。如果它是一行的第一个字符,那么用户程序的 read() 将返回 0,指示读到了 EOF。当设置 ICANON 时可被识别,不再作为输入传递。
  • VMIN   非 canonical 模式读的最小字符数。
  • VEOL   (0, NUL) 附加的行尾字符。当设置 ICANON 时可被识别。
  • VTIME  非 canonical 模式读时的延时,以十分之一秒为单位。
  • VEOL2  (not in POSIX; 0, NUL) 另一个行尾字符。当设置 ICANON 时可被识别。
  • VSWTCH (not in POSIX; not supported under Linux; 0, NUL) 开关字符。(只为 shl 所用。)
  • VSTART (021, DC1, Ctrl-Q) 开始字符。重新开始被 Stop 字符中止的输出。当设置 IXON 时可被识别,不再作为输入传递。
  • VSTOP   (023, DC3, Ctrl-S) 停止字符。停止输出,直到键入 Start 字符。当设置 IXON 时可被识别,不再作为输入传递。
  • VSUSP   (032, SUB, Ctrl-Z) 挂起字符。发送 SIGTSTP 信号。当设置 ISIG 时可被识别,不再作为输入传递。
  • VDSUSP (not in POSIX; not supported under Linux; 031, EM, Ctrl-Y) 延时挂起信号。当用户程序读到这个字符时,发送 SIGTSTP 信号。当设置 IEXTEN 和 ISIG,并且系统支持作业管理时可被识别,不再作为输入传递。
  • VLNEXT  (not in POSIX; 026, SYN, Ctrl-V) 字面上的下一个。引用下一个输入字符,取消它的任何特殊含义。当设置 IEXTEN 时可被识别,不再作为输入传递。
  • VWERASE (not in POSIX; 027, ETB, Ctrl-W) 删除词。当设置 ICANON 和 IEXTEN 时可被识别,不再作为输入传递。
  • VREPRINT (not in POSIX; 022, DC2, Ctrl-R) 重新输出未读的字符。当设置 ICANON 和 IEXTEN 时可被识别,不再作为输入传递。
  • VDISCARD  (not in POSIX; not supported under Linux; 017, SI, Ctrl-O) 开关:开始/结束丢弃未完成的输出。当设置 IEXTEN 时可被识别,不再作为输入传递。

调用read 函数读取串口数据时, 返回读取数据的数量需要考虑两个变量: MIN 和 TIME 。

MIN 和 TIME 在 termios 结构的 c_cc 成员的数组 下标名为 VMIN 和 VTIME 。MIN是指一次 read 调用期望返回的最小字节数 。 VTIME 说明等待数据到达的分秒数(秒的 1/10 为分秒) 。 TIME 与 MIN 组合使用的 具体含义分 为 以下四种情形:

  1. 当 MIN > 0 TIME > 0 时计时器在收到第一个字节后启动,在计时器超时之前 TIME 的时间到) ),若已收到 MIN个字节,则 read 返回 MIN 个字节,否则,在计时器超时后返回实际接收到的字节。注意:因为只有在接收到第一个字节时才开始计时,所以至少可以返回1个字节。这种情形中,在接到第一个字节之前,调用者阻塞。如果在调用read时数据已经可用,则如同在read后数据立即被接到一样。
  2. 当 MIN > 0 TIME=0 时MIN个字节完整接收后, read 才返回,这可能会造成 read 无限期地阻塞。
  3. 当 MIN=0, TIME > 0 时TIME为允许等待的最大时间,计 时器在调用 read 时立即启动,在串口接到 1 字节数据或者计时器超时后即返回,如果是计时器超时,则返回 0 。
  4. 当 MIN=0 TIME=0 时如果有数据可用,则read 最多返回所要求的字节数,如果无数据可用,则 read 立即返回 0 。

终端api函数接口

tcgetattr

tcgetattr() 得到与 fd 指向的对象相关的参数,将它们保存于 termios_p 引用的 termios 结构中。函数可以从后台进程中调用;但是,终端属性可能被后来的前台进程所改变。

tcsetattr

tcsetattr() 设置与终端相关的参数 (除非需要底层支持却无法满足),使用 termios_p 引用的 termios 结构。optional_actions 指定了什么时候改变会起作用:

  • TCSANOW   改变立即发生
  • TCSADRAIN   改变在所有写入 fd 的输出都被传输后生效。这个函数应当用于修改影响输出的参数时使用。
  • TCSAFLUSH  改变在所有写入 fd 引用的对象的输出都被传输后生效,所有已接受但未读入的输入都在改变发生前丢弃。

tcsendbreak

tcsendbreak() 传送连续的 0 值比特流,持续一段时间,如果终端使用异步串行数据传输的话。如果 duration 是 0,它至少传输 0.25 秒,不会超过 0.5 秒。如果 duration 非零,它发送的时间长度由实现定义。如果终端并非使用异步串行数据传输,tcsendbreak() 什么都不做。

tcdrain

tcdrain() 等待直到所有写入 fd 引用的对象的输出都被传输。

tcflush

tcflush() 丢弃要写入 引用的对象,但是尚未传输的数据,或者收到但是尚未读取的数据,取决于 queue_selector 的值:

  • TCIFLUSH   刷新收到的数据但是不读
  • TCOFLUSH 刷新写入的数据但是不传送
  • TCIOFLUSH  同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送

tcflow

tcflow() 挂起 fd 引用的对象上的数据传输或接收,取决于 action 的值:

  • TCOOFF   挂起输出、
  • TCOON    重新开始被挂起的输出
  • TCIOFF   发送一个 STOP 字符,停止终端设备向系统传送数据
  • TCION    发送一个 START 字符,使终端设备向系统传输数据

串口属性设置示例

设置串口属性主要是配置termios结构体中的各个变量,大致流程如下:

  1. 使用函数tcgetattr保存原串口属性
struct termios newtio,oldtio;
tcgetattr(fd,&oldtio);
  1. 通过位掩码的方式激活本地连接和接受使能选项:CLOCAL和CREAD
newtio.c_cflag |=CLOCAL | CREAD;
  1. 使用函数cfsetispeed和cfsetospeed设置数据传输率
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
  1. 通过位掩码设置字符大小。
newtio.c_cflag &=~CSIZE;
newtio.c_cflag |=CS8;
  1. 设置奇偶效验位需要用到两个termios中的成员:c_cflag和c_iflag。首先要激活c_cflag中的校验位使能标志PARENB和是否进行奇偶效验,同时还要激活c_iflag中的奇偶效验使能。 设置奇校验:
newtio.c_cflag |=PARENB;
newtio.c_cflag |=PARODD;
newtio.c_iflag |=(INPCK | ISTRIP);
设置偶校验:
newtio.c_iflag |=(INPCK|ISTRIP);
newtio.c_cflag |=PARENB;
newtio.c_cflag |=~PARODD;
  1. 激活c_cflag中的CSTOPB设置停止位。若停止位为1,则清除CSTOPB;若停止位为0,则激活CSTOPB。
newtio.c_cflag &=~CSTOPB;
  1. 设置最少字符和等待时间。在对接收字符和等待时间没有特别要求的情况下,可以将其设置为0。
newtio.c_cc[VTIME]=0;
newtio.c_cc[VMIN]=0;
  1. 调用函数”tcflush(fd,queue_selector)”来处理要写入引用的对象,queue_selector可能的取值有以下几种。
  • TCIFLUSH:刷新收到的数据但是不读
  • TCOFLUSH:刷新写入的数据但是不传送
  • TCIOFLUSH:同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送。
  1. 激活配置。在完成配置后,需要激活配置使其生效。使用tcsetattr()函数。
int tcsetattr(int filedes,int opt,const struct termios termptr);

串口编程实例

/@file      main.c
  @brief       串口应用编程测试
  @details
  @author      zhongyi  
  @date        2022-04-30
  @version     V1.0
 
 /

/ 包含的头文件 /
#include <stdio.h>        //标准输入输出,如printf、scanf以及文件操作
#include <stdlib.h>        //标准库头文件,定义了五种类型、一些宏和通用工具函数
#include <unistd.h>        //定义 read write close lseek 等Unix标准函数
#include <sys/types.h>    //定义数据类型,如 ssiz e_t off_t 等
#include <sys/stat.h>    //文件状态
#include <fcntl.h>        //文件控制定义
#include <termios.h>    //终端I/O
#include <errno.h>        //与全局变量 errno 相关的定义
#include <getopt.h>        //处理命令行参数
#include <string.h>        //字符串操作
#include <time.h>        //时间
#include <sys/select.h>    //select函数

#define DEV_NAME    "/dev/ttyS4"    ///< 串口设备


/@brief   设置串口参数:波特率,数据位,停止位和效验位
  @param[in]  fd         类型  int      打开的串口文件句柄
  @param[in]  nSpeed     类型  int     波特率
  @param[in]  nBits     类型  int     数据位   取值 为 7 或者8
  @param[in]  nParity     类型  int     停止位   取值为 1 或者2
  @param[in]  nStop      类型  int      效验类型 取值为N,E,O,,S
  @return     返回设置结果
  - 0         设置成功
  - -1     设置失败
 /
int setOpt(int fd, int nSpeed, int nBits, int nParity, int nStop)
{
    struct termios newtio, oldtio;

    // 保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息
    if (tcgetattr(fd, &oldtio) !=0)
    {
        perror("SetupSerial 1");
        return -1;
    }

    bzero(&newtio, sizeof(newtio));        //新termios参数清零
    newtio.c_cflag |=CLOCAL | CREAD;    //CLOCAL--忽略 modem 控制线,本地连线, 不具数据机控制功能, CREAD--使能接收标志
    // 设置数据位数
    newtio.c_cflag &=~CSIZE;    //清数据位标志
    switch (nBits)
    {
        case 7:
            newtio.c_cflag |=CS7;
        break;
        case 8:
            newtio.c_cflag |=CS8;
        break;
        default:
            fprintf(stderr, "Unsupported data size\n");
            return -1;
    }
    // 设置校验位
    switch (nParity)
    {
        case 'o':
        case 'O':                     //奇校验
            newtio.c_cflag |=PARENB;
            newtio.c_cflag |=PARODD;
            newtio.c_iflag |=(INPCK | ISTRIP);
            break;
        case 'e':
        case 'E':                     //偶校验
            newtio.c_iflag |=(INPCK | ISTRIP);
            newtio.c_cflag |=PARENB;
            newtio.c_cflag &=~PARODD;
            break;
        case 'n':
        case 'N':                    //无校验
            newtio.c_cflag &=~PARENB;
            break;
        default:
            fprintf(stderr, "Unsupported parity\n");
            return -1;
    }
    // 设置停止位
    switch (nStop)
    {
        case 1:
            newtio.c_cflag &=~CSTOPB;
        break;
        case 2:
            newtio.c_cflag |=CSTOPB;
        break;
        default:
            fprintf(stderr,"Unsupported stop bits\n");
            return -1;
    }
    // 设置波特率 2400/4800/9600/19200/38400/57600/115200/230400
    switch (nSpeed)
    {
        case 2400:
            cfsetispeed(&newtio, B2400);
            cfsetospeed(&newtio, B2400);
            break;
        case 4800:
            cfsetispeed(&newtio, B4800);
            cfsetospeed(&newtio, B4800);
            break;
        case 9600:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
        case 19200:
            cfsetispeed(&newtio, B19200);
            cfsetospeed(&newtio, B19200);
            break;
        case 38400:
            cfsetispeed(&newtio, B38400);
            cfsetospeed(&newtio, B38400);
            break;
        case 57600:
            cfsetispeed(&newtio, B57600);
            cfsetospeed(&newtio, B57600);
            break;
        case 115200:
            cfsetispeed(&newtio, B115200);
            cfsetospeed(&newtio, B115200);
            break;
        case 230400:
            cfsetispeed(&newtio, B230400);
            cfsetospeed(&newtio, B230400);
            break;
        default:
            printf("\tSorry, Unsupported baud rate, set default 9600!\n\n");
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
    }
    // 设置read读取最小字节数和超时时间
    newtio.c_cc[VTIME]=1;     // 读取一个字符等待1(1/10)s
    newtio.c_cc[VMIN]=1;        // 读取字符的最少个数为1

      tcflush(fd,TCIFLUSH);         //清空缓冲区
      if (tcsetattr(fd, TCSANOW, &newtio) !=0)    //激活新设置
      {
        perror("SetupSerial 3");
          return -1;
     }
      printf("Serial set done!\n");
    return 0;
}

/@brief 串口读取函数
  @param[in]  fd         打开的串口文件句柄
  @param[in]  rcv_buf 接收缓存指针
  @param[in]  data_len    要读取数据长度
  @param[in]  timeout     接收等待超时时间,单位ms
  @return     返回设置结果
  - >0      设置成功
  - 其他      读取超时或错误
 /
int UART_Recv(int fd, char rcv_buf, int data_len, int timeout)
{
    int len, fs_sel;
    fd_set fs_read;
    struct timeval time;

    time.tv_sec=timeout / 1000;              //set the rcv wait time
    time.tv_usec=timeout % 1000  1000;    //100000us=0.1s

    FD_ZERO(&fs_read);        //每次循环都要清空集合,否则不能检测描述符变化
    FD_SET(fd, &fs_read);    //添加描述符

    // 超时等待读变化,>0:就绪描述字的正数目, -1:出错, 0 :超时
    fs_sel=select(fd + 1, &fs_read, NULL, NULL, &time);
//    printf("fs_sel=%d\n", fs_sel);
    if(fs_sel)
    {
        len=read(fd, rcv_buf, data_len);
        return len;
    }
    else
    {
//        printf("Sorry,I am wrong!");
        return -1;
    }
}

/@brief 串口发送函数
  @param[in]  fd            打开的串口文件句柄
  @param[in]  send_buf     发送数据指针
  @param[in]  data_len     发送数据长度
  @return     返回结果
  - data_len    成功
  - -1            失败
 /
int UART_Send(int fd, char send_buf, int data_len)
{
    ssize_t ret=0;

    ret=write(fd, send_buf, data_len);
    if (ret==data_len)
    {
        printf("send data is %s\n", send_buf);
        return ret;
    }
    else
    {
        printf("write device error\n");
        tcflush(fd,TCOFLUSH);
        return -1;
    }
}


/@fn main
  @brief main入口函数
 /
int main (int argc, char argv[])
{
    int fdSerial;

    // 打开串口设备
    fdSerial=open(DEV_NAME, O_RDWR | O_NOCTTY | O_NDELAY);
    if(fdSerial < 0)
    {
        perror(DEV_NAME);
        return -1;
    }
    // 设置串口阻塞, 0:阻塞, FNDELAY:非阻塞
    if (fcntl(fdSerial, F_SETFL, 0) < 0)    //阻塞,即使前面在open串口设备时设置的是非阻塞的
    {
        printf("fcntl failed!\n");
    }
    else
    {
        printf("fcntl=%d\n", fcntl(fdSerial, F_SETFL, 0));
    }
    if (isatty(fdSerial)==0)
    {
        printf("standard input is not a terminal device\n");
        close(fdSerial);
        return -1;
    }
    else
    {
        printf("is a tty success!\n");
    }
    printf("fd-open=%d\n", fdSerial);


    // 设置串口参数
    if (setOpt(fdSerial, 115200, 8, 'N', 1)==-1)    //设置8位数据位、1位停止位、无校验
    {
        fprintf(stderr, "Set opt Error\n");
        close(fdSerial);
        exit(1);
    }

    tcflush(fdSerial, TCIOFLUSH);    //清掉串口缓存
    fcntl(fdSerial, F_SETFL, 0);    //串口阻塞


    char rcv_buf[100];
    int len;

    while(1)    //循环读取数据
    {
        len=UART_Recv(fdSerial, rcv_buf, 99, 10000);
        if(len > 0)
        {
            rcv_buf[len]='\0';
            printf("receive data is %s\n", rcv_buf);
            printf("len=%d\n", len);
            UART_Send(fdSerial, rcv_buf, len);
        }
        else
        {
//            printf("cannot receive data\n");
        }
        usleep(100000);    //休眠100ms
    }
}

本文参考

https://blog.csdn.net/luotuo28/article/details/125896180

https://www.cnblogs.com/silencehuan/p/11103074.html

文主要给大家分享网络七层概念之应用层,前边的章节已经给大家讲述了链路层、物理层、网络层、传输层等,欢迎学习嵌入式网络编程的朋友关注、转载和发表评论!

(绝对的好文,建议先收藏和转载!)

本文的主要讲述内容为:

1应用层常用的协议

1.1DNS

1.2FTP

1.3TFTP

1.4TELNET

1.5电子邮件

1.6万维网 WWW

2 C/S 交互模型

2.1C/S 概述

2.2C/S 模型

2.3C/S 特性

2.4 常用网络命令

应用层位于 OSI 参考模型的最高层,它通过使用下面各层所提供的服务,直接向用户提供服务,是计算机网络与用户之间的界面或接口。应用层由若干面向用户提供服务的应用程序和支持应用程序的通 信组件组成。

为了向用户提供有效的网络应用服务,应用层需要确立相互通信的应用程序或进程的有效性并提供 同步,需要提供应用程序或进程所需要的信息交换和远程操作,需要建立错误恢复的机制以保证应用层 数据的一致性。应用层为各种实际应用所提供的这些通信支持服务统称为应用服务组件(Application Service Element,简称 ASE)。

7.1 应用层常用的协议

7.1.1 DNS

每个应用层协议都是为了解决某一类应用问题,而问题的解决又往往是通过位于不同主机中的 多个应用进程之间的通信和协同工作来完成的。应用层的具体内容就是规定应用进程在通信时所遵循的 协议。

应用层的许多协议都是基于客户服务器方式。

一、域名系统概述

许多应用层软件经常直接使用域名系统 DNS (Domain Name System),但计算机的用户只是间接而不是直接使用域名系统。

因特网采用层次结构的命名树作为主机的名字,并使用分布式的域名系统 DNS。

名字到 IP 地址的解析是由若干个域名服务器程序完成的。域名服务器程序在专设的结点上运行,运行该程序的机器称为域名服务器。

二、因特网的域名结构

因特网采用了层次树状结构的命名方法。 任何一个连接在因特网上的主机或路由器,都有一个唯一的层次结构的名字,即域名。

域名的结构由若干个分量组成,各分量之间用点隔开:….三级域名.二级域名.顶级域名 各分量分别代表不同级别的域名.

(1) 国家顶级域名 nTLD:如: .cn 表示中国,.us 表示美国,.uk 表示英国,等等。

(2) 国际顶级域名 iTLD:采用.int。国际性的组织可在 .int 下注册。

(3) 通用顶级域名 gTLD:最早的顶级域名是:

.com 表示公司企业

.net 表示网络服务机构

.org 表示非赢利性组织

.edu 表示教育机构(美国专用)

.gov 表示政府部门(美国专用)

.mil 表示军事部门(美国专用)

新增加了七个通用顶级域名 :.aero 用于航空运输企业 .biz 用于公司和企业 .coop 用于合作团体 .info 适用于各种情况 .museum 用于博物馆 .name 用于个人 .pro 用于会计、律师和医师等自由职业者

图 7-1 域名结构

三、用域名服务器进行域名解析

授权域名服务器 :因特网允许各个单位根据具体情况将本单位的域名划分为若干个域名服务器管辖区(zone),并在各管辖区中设置相应的授权域名服务器。

递归查询 :

图 7-2 递归查询

递归与迭代相结合的查询 :

图 7-3 递归与迭代查询

名字的高速缓存:使用名字的高速缓存可优化查询的开销。 每个域名服务器都维护一个高速缓存, 存放最近用过的名字以及从何处获得名字映射信息的记录。

7.1.2 FTP

FTP(File Transfer Protocol, FTP)是 TCP/IP 网络上两台计算机传送文件的协议,FTP 是在 TCP/IP

网络和 INTERNET 上最早使用的协议之一,它属于网络协议组的应用层。FTP 客户机可以给服务器发出命令来下载文件,上载文件,创建或改变服务器上的目录。

一、概述

FTP 是一个 8 位的客户端-服务器协议,能操作任何类型的文件而不需要进一步处理,就像 MIME 或

Unencode 一样。但是,FTP 有着极高的延时,这意味着,从开始请求到第一次接收需求数据之间的时间会非常长,并且不时的必需执行一些冗长的登陆进程。

FTP 服务一般运行在 20 和 21 两个端口。端口 20 用于在客户端和服务器之间传输数据流,而端口

21 用于传输控制流,并且是命令通向 ftp 服务器的进口。当数据通过数据流传输时,控制流处于空闲状态。而当控制流空闲很长时间后,客户端的防火墙会将其会话置为超时,这样当大量数据通过防火墙 时,会产生一些问题。此时,虽然文件可以成功的传输,但因为控制会话会被防火墙断开,传输会产生 一些错误。

网络环境下复制文件的复杂性:(1) 计算机存储数据的格式不同。 (2) 文件的目录结构和文件命名的规定不同。 (3) 对于相同的文件存取功能,操作系统使用的命令不同。 (4) 访问控制方法不同。

FTP 特点:文件传送协议 FTP 只提供文件传送的一些基本的服务,它使用 TCP 可靠的运输服务;

FTP 的主要功能是减少或消除在不同操作系统下处理文件的不兼容性; FTP 使用客户服务器方式。

二、FTP 的基本工作原理

主进程的工作步骤如下:打开熟知端口(端口号为 21),使客户进程能够连接上; 等待客户进程发出连接请求; 启动从属进程来处理客户进程发来的请求。从属进程对客户进程的请求处理完毕后即终止,但从属进程在运行期间根据需要还可能创建其他一些子进程; 回到等待状态,继续接受其他客户进程发来的请求,主进程与从属进程的处理是并发地进行。

两个连接:控制连接在整个会话期间一直保持打开,FTP 客户发出的传送请求通过控制连接发送给服务器端的控制进程,但控制连接不用来传送文件;实际用于传输文件的是"数据连接"。

图 7-4 FTP 使用的两个 TCP 连接

两个不同的端口号 :当客户进程向服务器进程发出建立连接请求时,要寻找连接服务器进程的熟知端口(21),同时还要告诉服务器进程自己的另一个端口号码,用于建立数据传送连接。 接着,服务器进程用自己传送数据的熟知端口(20)与客户进程所提供的端口号码建立数据传送连接。由于 FTP 使用了两个不同的端口号,所以数据连接与控制连接不会发生混乱。

使用两个独立的连接的主要好处是:使协议更加简单和更容易实现; 在传输文件时还可以利用控制连接(例如,客户发送请求终止传输)。

NFS 采用另一种思路:NFS 允许应用进程打开一个远地文件,并能在该文件的某一个特定的位置上开始读写数据。 NFS 可使用户只复制一个大文件中的一个很小的片段,而不需要复制整个大文件。

7.1.3 TFTP

一、概述

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是 TCP/IP 协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为 69。

TFTP 是一个传输文件的简单协议,它基于 UDP 协议而实现,但是我们也不能确定有些 TFTP 协议是基于其它传输协议完成的。此协议设计的时候是进行小文件传输的。因此它不具备通常的 FTP 的许多功能,它只能从文件服务器上获得或写入文件,不能列出目录,不进行认证,它传输 8 位数据。传输中有三种模式:netascii,这是 8 位的 ASCII 码形式,另一种是 octet,这是 8 位源数据类型;最后一种 mail 已经不再支持,它将返回的数据直接返回给用户而不是保存为文件。

TFTP 是一个很小且易于实现的文件传送协议。 TFTP 使用客户服务器方式和使用 UDP 数据报,因此 TFTP 需要有自己的差错改正措施。 TFTP 只支持文件传输而不支持交互。 TFTP 没有一个庞大的命令集,没有列目录的功能,也不能对用户进行身份鉴别。

主要特点:(1) 每次传送的数据 PDU 中有 512 字节的数据,但最后一次可不足 512 字节。(2) 数据 PDU 也称为文件块(block),每个块按序编号,从 1 开始。 (3) 支持 ASCII 码或二进制传送。 (4) 可对文件进行读或写。 (5) 使用很简单的首部。

二、 与其它协议的联系

因为 TFTP 使用 UDP,而 UDP 使用 IP,IP 可以还使用其它本地通信方法。因此一个 TFTP 包中会有以下几段:本地媒介头,IP 头,数据报头,TFTP 头,剩下的就是 TFTP 数据了。TFTP 在 IP 头中不指定任何数据,但是它使用 UDP 中的源和目标端口以及包长度域。由 TFTP 使用的包标记(TID)在这里被用做端口,因此 TID 必须介于 0 到 65,535 之间。对它的初始化我们在后面讨论。TFTP 头中包括两上字节的操作码,这个码指出了包的类型下面我们看看大体上的 TFTP 包格式,相关的内容我们在后面的章节中进行讨论。

---------------------------------------------------

| Local Medium | Internet | Datagram | TFTP |

---------------------------------------------------

三、 初始连接

初始连接时候需要发出 WRQ(请求写入远程系统)或 RRQ( 请求读取远程系统),收到一个确定应答,一个确定可以写出的包或应该读取的第一块数据。通常确认包包括要确认的包的包号, 每个数据包都与一个块号相对应, 块号从 1 开始而且是连续的。因此对于写入请求的确定是一个比较特殊的情况,因此它的包的包号是 0。如果收到的包是一个错误的包,则这个请求被拒绝。创建连接时,通信双方随机选择一个 TID, 因此是随机选择的,因此两次选择同一个 ID 的可能性就很小了。每个包包括两个 TID, 发送者 ID 和接收者 ID。这些 ID 用于在 UDP 通信时选择端口,请求主机选择 ID 的方法上面已经说过了,在第一次请求的时候它会将请求发到 TID 69,也就是服务器的 69 端口上。应答时,服务器使用一个选择好的 TID 作为源 TID, 并用上一个包中的 TID 作为目的 ID 进行发送。这两个被选择的 ID 在随后的通信中会被一直使用。下例是一个写入的例子,其中 WRQ,ACK 和 DATA 代表写入请求,确认和数据。

四、 TFTP 支持五种类型的包

opcode operation 1.Read

request (RRQ) 2.Write

request (WRQ) 3.Data

(DATA) 4.Acknowledgment

(ACK) 5.Error (ERROR)

包头中包括了这个包所指定的操作码。

1. bytes string 1 byte string 1 byte

------------------------------------------------

| Opcode | Filename | 0 | Mode | 0 |

------------------------------------------------

RRQ/WRQ 包RRQ 和 WRQ 包(代码分别为 1 和 2)的格式如上所示。文件名是 NETASCII 码字符,以 0 结束。而MODE 域包括了字符串"netascii","octet"或"mail",名称不分大小写。接收到 NETASCII 格式数据的主机必须将数据转换为本地格式。OCTET 模式用于传输文件,这种文件在源机上以 8 位格式存储。假设每个机器都存在一个 8 位的格式,这样的假设是最一般的。比如 DEC-20,这是一种 36 位机,我们可以假设它是 4 个 8 位外加另外 4 位而构成。如果机器收到 OCTET 格式文件,返回时必须与原来文件完全一样。在使用 MAIL 模式时,用户可以在 FILE 处使用接收人地址,这个地址可以是用户名或用户名@主机的形式,如果是后一种形式,允许主机使用电子邮件传输此文件。如果使用 MAIL 类型,包必须以 WRQ 开始,否则它与 NETASCII 完全一样。我们的讨论建立在发送方和接收方都在相同模式的情况下,但是双方可以以不同的模式进行传输。例如一个机器可以是一台存储服务器,这样一台服务器需要将NETASCII 格式转换为自己的格式。另外,我们可以设想 DEC-20 这种机器,它使用 36 位字长,用户这边可以使用特殊的机制一次读取 36 位,而服务器却可以仍然使用 8 位格式。在这两种情况下,我们看到了两台机器使用不同格式的情况。可以在两台主机间定义其它的传输方式,但是定义要小心,因为这 种传输方式不为人知,而且也没有权威机构为其指定名称或定义它的模式。

2. bytes 2 bytes n bytes

----------------------------------

| Opcode | Block # | Data |

----------------------------------

DATA 包

数据在数据包中传输,其格式如上图所示。数据包的 OP 码为 3,它还包括有一个数据块号和数据。数据块号域从 1 开始编码,每个数据块加 1,这样接收方可以确定这个包是新数据还是已经接收过的数据。数据域从 0 字节到 512 字节。如果数据域是 512 字节则它不是最后一个包,如果小于 512 字节则表示这个包是最后一个包。除了 ACK 和用于中断的包外,其它的包均得到确认。发出新的数据包等于确认上次的包。WRQ 和 DATA 包由 ACK 或 ERROR 数据包确认,而 RRQ 数据包由 DATA 或 ERROR 数据包确认。下图即是一个 ACK 包,操作码为 4。其中的包号为要确认的数据包的包号。

3. bytes 2 bytes

---------------------

| Opcode | Block # |

---------------------

ACK 包

WRQ 数据包被 ACK 数据包确认,WRQ 数据包的包号为 0。4.bytes 2 bytes string 1 byte

-----------------------------------------

| Opcode | ErrorCode | ErrMsg | 0 |

-----------------------------------------

ERROR 包

一个 ERROR 包,它的操作码是 5,它的格式如上所示。此包可以被其它任何类型的包确认。错误码指定错误的类型。错误的值和错误的意义在附录中。错误信息是供程序员使用的。

图 7-5 TFTP 的五种协议数据单元 PDU

7.1.4 TELNET

一、概述

Telnet 协议是 TCP/IP 协议族中的一员,是 Internet 远程登陆服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。在终端使用者的电脑上使用 telnet 程序,用它连接到服务器。终端使用者可以在 telnet 程序中输入命令,这些命令会在服务器上运行,就像直接在服务器的控制台上输入一样。可以在本地就能控制服务器。要开始一个 telnet 会话,必须输入用户名和密码来登录服务器。Telnet 是常用的远程控制 Web 服务器的方法。

它最初是由 ARPANET 开发的,但是现在它主要用于 Internet 会话。它的基本功能是,允许用户登录进入远程主机系统。起初,它只是让用户的本地计算机与远程计算机连接,从而成为远程主机的一个 终端。它的一些较新的版本在本地执行更多的处理,于是可以提供更好的响应,并且减少了通过链路发 送到远程主机的信息数量。

Telnet 是位于 OSI 模型的第 7 层---应用层上的一种协议,是一个通过创建虚拟终端提供连接到远程主机终端仿真的 TCP/IP 协议。这一协议需要通过用户名和口令进行认证,是 Internet 远程登陆服务的标准协议。应用 Telnet 协议能够把本地用户所使用的计算机变成远程主机系统的一个终端。它提供了三种基本服务:

1) Telnet 定义一个网络虚拟终端为远程系统提供一个标准接口。客户机程序不必详细了解远程系统,他们只需构造使用标准接口的程序;

2) Telnet 包括一个允许客户机和服务器协商选项的机制,而且它还提供一组标准选项; .

3) Telnet 对称处理连接的两端,即 Telnet 不强迫客户机从键盘输入,也不强迫客户机在屏幕上显示输出。

二、适应异构

为了使多个操作系统间的 Telnet 交互操作成为可能,就必须详细了解异构计算机和操作系统。比如,一些操作系统需要每行文本用 ASCII 回车控制符(CR)结束,另一些系统则需要使用 ASCII 换行符

(LF),还有一些系统需要用两个字符的序列回车-换行(CR-LF);再比如,大多数操作系统为用户提供了一个中断程序运行的快捷键,但这个快捷键在各个系统中有可能不同(一些系统使用 CTRL+C,而另一些系统使用 ESCAPE)。如果不考虑系统间的异构性,那么在本地发出的字符或命令,传送到远地并被远程系统解释后很可能会不准确或者出现错误。因此,Telnet 协议必须解决这个问题。 为了适应异构环境,Telnet 协议定义了数据和命令在 Internet 上的传输方式,此定义被称作网络虚拟终端 NVT(Net Virtual Terminal)。它的应用过程如下: 对于发送的数据:客户机软件把来自用户终端的按键和命令序列转换为 NVT 格式,并发送到服务器,服务器软件将收到的数据和命令,从 NVT 格式转换为远地系统需要的格式; 对于返回的数据:远地服务器将数据从远地机器的格式转换为 NVT 格式,而本地客户机将将接收到的 NVT 格式数据再转换为本地的格式。 对于 NVT 格式的详细定义,有兴趣的朋友可以去查找相关资料。

三、传送远程命令

我们知道绝大多数操作系统都提供各种快捷键来实现相应的控制命令,当用户在本地终端键入这些快捷键的时候,本地系统将执行相应的控制命令,而不把这些快捷键作为输入。那么对于 Telnet 来说, 它是用什么来实现控制命令的远程传送呢? Telnet 同样使用 NVT 来定义如何从客户机将控制功能传送到服务器。我们知道 USASCII 字符集包括 95 个可打印字符和 33 个控制码。当用户从本地键入普通字符时,NVT 将按照其原始含义传送;当用户键入快捷键(组合键)时,NVT 将把它转化为特殊的 ASCII 字符在网络上传送,并在其到达远地机器后转化为相应的控制命令。

将正常 ASCII 字符集与控制命令区分的原因:

1)这种区分意味着 Telnet 具有更大的灵活性:它可在客户机与服务器间传送所有可能的 ASCII字符以及所有控制功能;

2) 这种区分使得客户机可以无二义性的指定信令,而不会产生控制功能与普通字符的混乱。

四、数据流向

上面我们提到过将 Telnet 设计为应用级软件有一个缺点,那就是:效率不高。这是为什么呢?下面给出 Telnet 中的数据流向:

数据信息被用户从本地键盘键入并通过操作系统传到客户机程序,客户机程序将其处理后返回操作系统,并由操作系统经过网络传送到远程机器,远程操作系统将所接收数据传给服务器程序,并经服务器程序再次处理后返回到操作系统上的伪终端入口点,最后,远程操作系统将数据传送到用户正在运行的应用程序,这便是一次完整的输入过程;输出将按照同一通路从服务器传送到客户机。 因为每一次的输入和输出,计算机将切换进程环境好几次,这个开销是很昂贵的。还好用户的键入速率并不算高, 这个缺点我们仍然能够接受。

五、 强制命令

我们应该考虑到这样一种情况:假设本地用户运行了远地机器的一个无休止循环的错误命令或程序,且此命令或程序已经停止读取输入,那么操作系统的缓冲区可能因此而被占满,如果这样,远程服 务器也无法再将数据写入伪终端,并且最终导致停止从 TCP 连接读取数据,TCP 连接的缓冲区最终也会被占满,从而导致阻止数据流流入此连接。如果以上事情真的发生了,那么本地用户将失去对远程机器的控制。

为了解决此问题,Telnet 协议必须使用外带信令以便强制服务器读取一个控制命令。我们知道 TCP 用紧急数据机制实现外带数据信令,那么 Telnet 只要再附加一个被称为数据标记(date mark)的保留八位组,并通过让 TCP 发送已设置紧急数据比特的报文段通知服务器便可以了,携带紧急数据的报文段将绕过流量控制直接到达服务器。作为对紧急信令的相应,服务器将读取并抛弃所有数据,直到找到了一 个数据标记。服务器在遇到了数据标记后将返回正常的处理过程。

六、 选项协商

由于 Telnet 两端的机器和操作系统的异构性,使得 Telnet 不可能也不应该严格规定每一个 telnet 连接的详细配置,否则将大大影响 Telnet 可适应异构性。因此,Telnet 采用选项协商机制来解决这一问题。

Telnet 选项的范围很广:一些选项扩充了大方向的功能,而一些选项制涉及一些微小细节。例如: 有一个选项可以控制 Telnet 是在半双工还是全双工模式下工作(大方向);还有一个选项允许远地机器上的服务器决定用户终端类型(小细节)。

Telnet 选项的协商方式也很有意思,它对于每个选项的处理都是对称的,即任何一端都可以发出协商申请;任何一端都可以接受或拒绝这个申请。另外,如果一端试图协商另一端不了解的选项,接受请求的一端可简单的拒绝协商。因此,有可能将更新,更复杂的 Telnet 客户机服务器版本与较老的, 不太复杂的版本进行交互操作。如果客户机和服务器都理解新的选项,可能会对交互有所改善。否则, 它们将一起转到效率较低但可工作的方式下运行。所有的这些设计,都是为了增强适应异构性,可见

Telnet 的适应异构性对其的应用和发展是多么重要。

7.1.5 电子邮件

一、概述

电子邮件(e-mail)是因特网上使用得最多的和最受用户欢迎的一种应用。电子邮件把邮件发送到

ISP 的邮件服务器,并放在其中的收信人邮箱中,收信人可随时上网到 ISP 的邮件服务器进行读取。电子邮件不仅使用方便,而且还具有传递迅速和费用低廉的优点。 现在电子邮件不仅可传送文字信息, 而且还可附上声音和图像。

在 1982 年制定出简单邮件传送协议 SMTP (Simple Mail Transfer Protocol) 和因特网文本报文格式,它们都已成为因特网的正式标准、1993 年提出了通用因特网邮件扩充 MIME (Multipurpose Internet Mail Extensions)。

电子邮件的最主要的组成构件 :

图 7-6 电子邮件的组成构件

应当注意:一个邮件服务器既可以作为客户,也可以作为服务器。

电子邮件的发送和接收过程 :(1) 发信人调用用户代理来编辑要发送的邮件。(2)发送端邮件服务器将邮件放入 邮件缓存队列中,等待发送。(3) 运行在发送端邮件服务器的 SMTP 客户进程,发现 在邮件缓存中有待发送的邮件,就向运行在接收端邮件 服务器的 SMTP 服务器进程发起 TCP 连接的建立。(4) TCP 连接建立后,SMTP 客户进程开始向远程的 SMTP 服务器进程发送邮件。当所有的待发送邮件发完了,SMTP 就关闭所建立的 TCP 连接。(5) 运行在接收端邮件服务器中的 SMTP 服务器进程收到邮件后,将邮件放入收信人的用户邮箱中,等待收信人在方便时进行读取。(6) 收信人在打算收信时, 调用用户代理,使用 POP3(或 IMAP)协议将自己的邮件从接收端邮件服务器的用户邮箱中的取回(如果邮箱中有来信的话)。

电子邮件由信封(envelope)和内容(content)两部分组成。

TCP/IP 体系的电子邮件系统规定电子邮件地址的格式如下:收信人邮箱名@邮箱所在主机的域名。

二、简单邮件传送协议 SMTP

SMTP 所规定的就是在两个相互通信的 SMTP 进程之间应如何交换信息。由于 SMTP 使用客户服务器方式,因此负责发送邮件的 SMTP 进程就是 SMTP 客户,而负责接收邮件的 SMTP 进程就是 SMTP 服务器。

SMTP 通信的三个阶段 :连接建立、邮件传送、连接释放。

三、电子邮件的信息格式

一个电子邮件分为信封和内容两大部分。[RFC 822]只规定了邮件内容中的首部(header)格式,而对邮件的主体(body)部分则让用户自由撰写。

四、邮件读取协议 POP3 和 IMAP

邮局协议 POP 是一个非常简单、但功能有限的邮件读取协议,现在使用的是它的第三个版本 POP3。

POP 也使用客户服务器的工作方式。

IMAP 也是按客户服务器方式工作,现在较新的版本是 IMAP4。 用户在自己的 PC 机上就可以操纵

ISP 的邮件服务器的邮箱,就像在本地操纵一样。 因此 IMAP 是一个联机协议。

IMAP 最大的好处就是用户可以在不同的地方使用不同的计算机随时上网阅读和处理自己的邮件。

IMAP 还允许收信人只读取邮件中的某一个部分。

IMAP 的缺点是如果用户没有将邮件复制到自己的 PC 机上,则邮件一直是存放在 IMAP 服务器上。因此用户需要经常与 IMAP 服务器建立连接。

五、通用因特网邮件扩充 MIME

SMTP 有以下缺点:SMTP 不能传送可执行文件或其他的二进制对象;SMTP 限于传送 7 位的 ASCII 码;SMTP 服务器会拒绝超过一定长度的邮件;某些 SMTP 的实现并没有完全按照[RFC 821]的 SMTP 标准。

MIME 的特点:MIME 并没有改动 SMTP 或取代它;MIME 的意图是继续使用目前的[RFC 822]格式, 但增加了邮件主体的结构,并定义了传送非 ASCII 码的编码规则。

图 7-7 MIME 和 SMTP 的关系 :


7.1.6 万维网 WWW

一、概述

万维网 WWW (World Wide Web)并非某种特殊的计算机网络。 万维网是一个大规模的、联机式的信息储藏所。万维网提供分布式服务 。

图 7-8 万维网站点

万维网是分布式超媒体(hypermedia)系统,它是超文本(hypertext)系统的扩充。万维网以客户服务器方式工作。

怎样标志分布在整个因特网上的万维网文档? 使用统一资源定位符 URL (Uniform Resource

Locator)来标志万维网上的各种文档。 使每一个文档在整个因特网的范围内具有唯一的标识符 URL。用何协议实现万维网上各种超链的链接? 在万维网客户程序与万维网服务器程序之间进行交互所

使用的协议,是超文本传送协议 HTTP (HyperText Transfer Protocol)。

怎样使各种万维网文档都能在因特网上的各种计算机上显示出来,同时使用户清楚地知道在什么地 方存在着超链? 超文本标记语言 HTML (HyperText Markup Language)使得万维网页面的设计者可以很方便地用一个超链从本页面的某处链接到因特网上的任何一个万维网页面,并且能够在自己的计算机屏 幕上将这些页面显示出来。

怎样使用户能够很方便地找到所需的信息? 为了在万维网上方便地查找信息,用户可使用各种的搜索工具(即搜索引擎)。

二、统一资源定位符 URL

统一资源定位符 URL 是对可以从因特网上得到的资源的位置和访问方法的一种简洁的表示。 URL 给资源的位置提供一种抽象的识别方法,并用这种方法给资源定位。 只要能够对资源定位,系统就可以对资源进行各种操作,如存取、更新、替换和查找其属性。 URL 相当于一个文件名在网络范围的扩展。

URL 的一般形式是:<URL 的访问方式>://<主机>:<端口>/<路径>

三、超文本传送协议 HTTP

万维网的工作过程 :

图 7-9 HTTP 协议

HTTP 的主要特点 : 是面向事务的客户服务器协议;HTTP 1.0 协议是无状态的;协议本身也是无连接的。

万维网高速缓存 (Web cache) :万维网高速缓存代表浏览器发出 HTTP 请求,因此又称为代理服务器(proxy server)。 万维网高速缓存将最近的一些请求和响应暂存在本地磁盘中。 使用高速缓存可减少 访问因特网服务器的时延。

HTTP 有两类报文:请求报文、响应报文

四、超文本标记语言 HTML

HTML 定义了许多用于排版的命令(标签)。 HTML 把各种标签嵌入到万维网的页面中。这样就构成了所谓的 HTML 文档。HTML 文档是一种可以用任何文本编辑器创建的 ASCII 码文件。

仅当 HTML 文档是以.html 或 .htm 为后缀时,浏览器才对此 文档的各种标签进行解释。

元素(element)是 HTML 文档结构的基本组成部分。一个 HTML 文档本身就是一个元素。每个 HTML 文档由两个主要元素组成:首部(head)和主体(body) 。文档的主体是 HTML 文档的最主要的部分。

HTML 用一对标签(即一个开始标签和一个结束标签)或几对标签来标识一个元素。 开始标签由一个小于字符"<"、一个标签名、和一个大于字符">"组成。 结束标签和开始标签的区别只是在小于字符的后面要加上一个斜线字符"/"。 虽然标签名并不区分大写和小写。 有一些标签可以将结束标签省略。

五、万维网页面中的超链

定义一个超链的标签是<A>。字符 A 表示锚(Anchor)。

在 HTML 文档中定义一个超链的语法是: <A HREF="... ">X</A>

六、动态万维网文档与 CGI 技术

静态文档是指该文档创作完毕后就存放在万维网服务器中,在被用户浏览的过程中,内容不会改变。 动态文档是指文档的内容是在浏览器访问万维网服务器时才由应用程序动态创建。 动态文档和静态文档之间的主要差别体现在服务器一端。

万维网服务器功能的扩充 :(1) 应增加另一个应用程序,用来处理浏览器发来的数据,并创建动态文档。(2) 应增加一个机制,用来使万维网服务器把浏览器发来的数据传送给这个应用程序,然后万维网服务器能够解释这个应用程序的输出,并向浏览器返回 HTML 文档。

图 7-10 CGI

CGI 是一种标准,它定义了动态文档应如何创建,输入数据应如何提供给应用程序,以及输出结果应如何使用。 万维网服务器与 CG I 的通信遵循 CGI 标准。

7.2 C/S 交互模型

7.2.1 C/S 概述

C/S 又称 Client/Server 或客户/服务器模式。C/S 型数据库应用程序由两部分组成:服务器和客户机。服务器指数据库管理系统(Database Manage System,简称 DBMS),用于描述、管理和维护数据库的程序系统,是数据库系统核心组成部分,对数据库进行统一的管理和控制。客户机则将用户的需求 送交到服务器,再从服务器返回数据给用户。

C/S 型数据库非常适合于网络应用,可以同时被多个用户所访问,并赋予不同的用户以不同的安全权限。C/S 型数据库支持的数据量一般比文件型数据库大得多,还支持分布式的数据库(即同一数据库位于多台服务器上)。同时,C/S 型数据库一般都能完善地支持 SQL 语言(所以也被称做 SQL 数据库)。这些特性决定了 C/S 型数据库适合于高端应用。

常见的 C/S 型数据库有著名的 Oracle,Sybase,Informix,微软的 Microsoft SQL server,IEM 的 DB2,以及 Delphi 自带的 InterBase 等。

C/S 的优点是能充分发挥客户端PC的处理能力,很多工作可以在客户端处理后再提交给服务器, 对应的优点就是客户端响应速度快。缺点主要有以下几个:

· 只适用于局域网。而随着互联网的飞速发展,移动办公和分布式办公越来越普及,这就需要系 统具有扩展性。

· 客户端需要安装专用的客户端软件。首先涉及到安装的工作量,其次任何一台电脑出现问题(如病毒、硬件损坏),都需要进行安装或维护。另外,系统软件升级时,每一台客户机需要重新安装,其维护和升级成本非常高。

对客户端的操作系统一般也会有限制。可能适应于 Win98,但不能用于 Win2000 或 Windows XP。或者不适用于微软新的操作系统等,更不用说 Linux、UNIX 了。

7.2.2 C/S 模型

应用程序之间为了能顺利地进行通信,一方通常需要处于守候状态,等待另一方请求的到来。 在分布式计算中,一个应用程序被动地等待,而另一个应用程序通过请求启动通信的模式就是客户/服务器模式。

客户(Client)和服务器(Server)分别是指两个应用程序。客户向服务器发出服务请求,服 务器对客户的请求作出响应。如下图所示为一个通过互联网进行交互的客户/服务器模型。在图9.1 中,服务器处于守候状态,并监视客户端的请求。客户端发出请求,并请求经互联网传输给服务器。一旦服务器接收到这个请求,就可以执行请求所指定的任务,并将执行的结果经互联网回送 给客户。

图 7-11 C/S 交互模型

7.2.3 C/S 特性

一台主机上通常可以运行多个服务器程序,每个服务器程序需要并发地处理多个客户的请求, 并将处理的结果返回给客户。在下图中,运行服务器程序的主机同时提供 Web 服务、FTP 服务和文件服务。由于客户 1、客户 2 和客户 3 分别运行访问文件服务和 Web 服务的客户端程序,因此,通过互联网,客户 1 可以访问运行文件服务主机上的文件系统,而 Web 服务器程序根据客户 2 和客户

3 的请求,同时为他们提供服务。

图 7-12 并发服务器

在互连网络中,客户发起请求完全是随机的,可能出现多个请求同时到达服务器的情况。因此,服务器 必须具备处理多个并发请求的能力,服务器有两种实现方案。

(1)重复服务器(Iterative Server)方案

服务器程序中包含一个请求队列,客户请求到达后,首先进入队列中等待,服务器按照先进先出的 原则顺序作出响应。

(2)并发服务器(Concurrent Server)方案

并发服务器是一个守护进程,在没有请求到达时它处于等待状态。一旦客户请求到达,服务器立即 再为之创建一个子进程,然后回到等待状态,由子进程响应请求。当下一个子进程到达时,服务器 再为之创建一个子进程。其中,并发服务器叫做主服务器,子进程叫做从服务器。

7.3 常用网络命令

Linux 作为一个基于网络的操作系统,它提供了很多网络调试程序,这些程序由 net-tools 包或单独的安装包中提供。

常用网络命令:

· ping 一 发送一个ICMP ECHO_REQUEST到目的主机,通常用来测试网络联通状况

· traceroute 一 搜寻一个主机到另一个手机之间经历的路由器

· ifconfig 一 查看和修改网络接口配置信息

· route 一 查看和修改路由表

· netstat 一 查看网络连接信息

· host,dig,nslookup — dns查询命令

· whois — whois目录服务客户端

· iptables 一 配置主机包过滤器和Nat透明代理

· arp 一 查看和修改系统arp缓存

· arping 一 发送arp广播,并显示回应信息

· ssh 一 安全远程login客户端,使用ssl通讯

· sftp 一 安全文件传输,使用ssl

· ftp 一 文件传输程序

· tftp 一简单的文件传输程序,使用udp协议

· telnet 一远程login客户端

下面将介绍上面列出的部分网络命令的使用方法: ifconfig

ifconfig 程序用来配置网络接口,它可以用来设置网络接口的 lP 地址,子网掩码,广播地址,以太网地址等等。同时它也能列表网络接口的配置信息,如使用-a 参数。

ifconfig 有着复杂的参数列表,这里并不详细叙述每个参数的使用方法,下面仅给出一些使用

ifconfig 命令的的实例:

· ifconfig eth0 down 关闭eth0网络接口

· ifconfig eth0 up 启用eth0网络接口

· ifconfig eth0 arp 启用eth0接口的arp能力

· ifconfig eth0 -arp 关闭eth0接口的arp能力

· ifconfig eth0 netmask 255.255.255.0 设置eth0接口的子网掩码为255.255.255.0

· ifconfig eth0 192.168.2.12 设置eth0接口IP地址为l92.168.2.12

· ifconfig eth0.broadcast l92.168.2.255 将第一块网卡的广播地址设置为

· 192.168.2.255,

· ifconfig 列出接口信息这些参数可以组合使用如:

· ifconfig eth0 192.168.2.12 netmask 255.255.255.0

route

route 命令是用来查看和设置系统的路由信息,以实现与其他网络或主机的通讯。

· route 罗列出当前路由表所有条目

· route add default gw l92.168.0.254 设置默认路由为192.168.0.254

· route del l92.168.3.19 删除路由表中到指定主机或网路的条目

ping

ping 是一个最常用的检测是否能够与远端机器建立网络通讯连接的命令。它是通过 Internet 控制报文协议 ICMP 的回射请求命令实现的。同样的,在此不罗列 ping 命令的所有可选参数,举例说明 ping 的常见用法:

· ping 192.168.2.1 检测本机到192.168.2.1的连通性。

· ping www.google.cn检测本机到www.google.cn的连通性

· ping -c 4 192.168.2.1 在Linux下,如果你不指定-c参数,ping命令将一直不断地向远 方机器发送ICMP信息。可以通过-c参数来指定发送ICMP的数量。

· ping -I eth0 l92.168.0.1 有时,我们需要检测系统的某个接口能否连接到远程系统, 需要在执行ping命令时用-I参数指出接口名

traceroute

当不能成功连接至远程主机时,traceroute 可以帮助找到在哪里出了问题,或者你想知道你的信息到远方机器都经过了哪些路由器,可以使用 traceroute 命令。

Traceroute www.google.cn 查询主机到 www.google.cn 中途经历了哪几个路由器。

netstat

在Linux 系统中,netstat 是一个功能十分强大的查看网络状态的工具。同样,我们只是列出netstat的常见用法:

· netstat -i 这个命令将输出所有网络接口信息的统计表,其中包括:

· lface:网络接口名

· MTU:最大传输单元

· RX-OK:共成功接收多少个包

· RX-ERR:接收的包中共有多少个错误包

· RX-DRP:接收时共丢失多少个包

· RX-OVR:共接收了多少个冲突包

· TX-OK:共成功发送多少个包

· TX-ERR:发送的包中共有多少个错误包

· TX-DRP:共丢失多少个包

· TX-OVR:共接收了多少个冲突的包

· netstat -s 显示网络的统计信息,使用这个命令,将会以摘要的形式统计出 IP、ICMP、TCP、UDP、

TCPEXT 形式的通信信息。

· netstat_-an 显示本机的所有连接信息。

· netstat -r 显示路由衷,输出与 route 命令的格式相同。

arp

在 IP 协议中 arp 协议用来查询子网中某个 IP 地址其对应的以太网地址,它通过发送以太网广播的方式发送查询信息,并获取对方的应答,除了查询方式,还有一种获取 arp 信息的手段,通常一台主机修改了本地接口的 I P 地址会主动以以太网广播的形式发送 arp 联编信息,以更新其他主机的 arp 条目。

arp 命令是用来查看和修改本地缓存的 arp 路由信息,下-面列举几个常见的 arp 命令用法:

· arp -a 显示本地 arp 条目

· arp -s l92.168.2.12 2a:4d:00:25:e0:3f 手动添加一条静态的 arp 条目,所谓静态,就是该信息不会被收到的动态地址联编信息所改变,该对应关系将一直保持到系统重启。

· arp -d l92.168.2.12 手动删除一个 arp 条目。