初学netcat

前几天,从网络中得知netcat这一被称为“网络瑞士军刀”的神器后,学习了一些基本的用法,现在总结一下。

使用netcat,我们可以把计算机A上的文件传到计算机B上。根据建立连接方式的不同,我们有两种方法。方法一,计算机B负责监听,A向B主动连接。这时在B上先输入“nc -l 8000 > file”,其中8000是监听的端口,然后在A上输入“nc IP 8000 < file”。方法二,计算机A负责监听,B向A主动连接。这时先在A上输入“nc -l 8080 < file”,然后在B上输入“nc IP 8080 > file”。

netcat从名字上是net+cat,但是它和cat有着本质上的不同。cat把标准输入的内容拷贝到标准输出,是单向的。然而,netcat是双向的,两台计算机的netcat建立连接后(不妨把两台计算机称为A和B),A从标准输入读到的东西,会经过网络,然后从B的标准输出出来,反之亦然。

netcat

我觉得这种I/O很像立交桥,它能同时处理两路I/O,然而,把netcat用于传文件显然只能用到其中一路I/O。如果能同时用上两路I/O,会发生什么有趣的事情呢?首先,如果两端的netcat的输入和输出都是接Terminal,那么两端的人可以用nc聊天,如上图所示。

如果把监听的一端(不妨称为计算机B)的输入输出重定向,那就更有趣。比如把B上nc的输出接到bash,然后把bash的输出又接回nc,那么B就是一个bash服务器,相当于开了个后门。具体实现可以使用命名管道和重定向,

mkfifo named_pipe; bash named_pipe | nc -l 8000 > named_pipe

同理,如果把程序换为cat,那么B就是一个echo服务器;如果把程序换为date,那么B就是一个date服务器。但和真正的服务器不一样,B只能接受一个连接,并且接受一次连接后就马上退出。

vi的缓冲区

vi的缓冲区除了保存当前文本之外,还可以完成复制、粘帖等任务。熟悉vi的缓冲区对于使用vi编辑文档有很大好处。

vi有一个保存当前文本内容的缓冲区,编辑文档的时候只是改变这个缓冲区的内容,存盘的时候vi才会把缓冲区内容拷贝到磁盘。

vi中非常有用的缓冲区是用来做复制和粘帖的。每次使用d命令(表示delete)和y命令(表示yank),其实vi就是把相应的删除内容或者复制内容放到缓冲区,使用p命令(表示paste)就会把这个无名缓冲区的内容放到光标所在位置。因此d和p组合使用就能实现剪切的效果,y和p组合使用就能实现复制的效果。

vi buffer
vi buffer

但是只有一个用来复制和粘帖的缓冲区,灵活性还不够。其实vi也考虑到这一点,因此除了这个无名缓冲区,vi还提供a到z一共26个命名的缓冲区,可以像无名缓冲区一样使用。需要使用时,先敲双引号”,然后敲a到z其中一个字母表示指定改名字的缓冲区,然后d和y命令照常输入即可。

除了英文命名缓冲区,其实vi还提供数字命名缓冲区,从1到9。这9个缓冲区不能随意存,能随意取。实际上这些缓冲区是之前的d和y命令所得的缓冲区,举个例子,如果执行d命令,那么内容会放到1号缓冲区,再执行y命令,新的内容放到1号缓冲区,而原来1号缓冲区的内容则放置在2号缓冲区,以此类推。因此可以合理猜测,1号缓冲区和无名缓冲区可能是同一回事。

初探/dev/random

以前我以为比较基本的产生随机数的方法就是用C语言中的srand()和rand()函数。但是最近我发现除了这种方法之外,还有使用起来几乎一样简单的方法,就是读取/dev/random设备文件。

以前要生成随机数,通常首先用srand()设定种子。为了要每次运行的结果不一样,种子也必须不同。所以比较简单的方法就是利用time()函数返回当前的时间作为种子。如果希望随机性更大一些,则种子设定时也可以考虑其他因素,比如目前内存的使用数目,甚至同时包含好几个因素。

/dev/random
/dev/random

最近,我发现了有一种更简便,但是效果要更好的方法,就是使用字符型设备文件/dev/random。据Wikipedia说,是Linux首先实现了这个设备文件,不过现在其他Unix-like的系统也能找到。使用这个文件产生随机数很简单,就是先打开这个文件,然后读取里面的字节就可以了。它的优点是随机数质量非常高,甚至可以用在一次性加密的环境下,我的理解是它跟伪随机数产生器还是有点区别。不过读取这个文件需要注意要使用二进制的读取方式,用fread库函数,或者read系统调用,因为字节中可能有各种字符。另外,/dev/random不能并发打开,如果要并发打开,据说可以使用/dev/urandom,u表示unlock。

Shell的jobs功能

大部分的Shell都会提供jobs的功能,之前略懂一二,但是有些地方不是很清楚,今天比较明白地搞清楚了,知道原来前台运行和后台运行的概念实际上是Shell提供的。因为我自己用的是bash,所以这里提供的命令都能在bash里用,估计其他的shell也类似。

Shell一开始时给出提示符,我们可以输入命令,程序就开始运行。程序运行完之后,我们又可以输入新的命令。但是程序运行的时候,对于同一个Shell,是没有办法输入命令的,这时就叫做在前台运行。可是有时候,有些命令的运行时间可能很长,比如find命令,这时我们就可以把程序放在后台运行,前台得到提示符,可以输入新的命令。把程序放在后台运行的方法是命令的最后加上&,比如“find . -name “foo*” -print >result &”。下图中我在后台运行Firefox。

Jobs Figure 1
Jobs Figure 1

Shell里运行后台程序后,出现两个数字。第一个中括号的数字是jobs ID,可以在相关的命令里用%号引用。第二个数字是进程号,是系统唯一的,可以用ps等命令去看。

有时候运行了程序之后才发现希望放在后台运行,这时可以按Ctrl+Z,把当前前台程序暂停,并且放在后台。在Shell的jobs功能里,第一个要介绍的命令是jobs,可以看到现在后台有多少个程序,它们的状态是怎样的。在下图中可以看到,第一列是jobs ID,第二列有些有加号,有些有减号,加号表示是最新的任务,减号是第二新的任务,其余没有符号。最后一列还有状态,一般可以看到三种,Running表示正在运行,Stopped表示暂停,Done或者Terminated表示已经做完了,通常再打一次jobs就会不再见到那个任务了。

Jobs Figure 2
Jobs Figure 2

想在暂停状态和运行状态之间切换可以用下面的命令。首先,想把前台程序暂停,就是用刚才说的Ctrl+Z,而想把后台程序暂停,可以使用stop命令加jobs ID,如“stop %1”。把程序从暂停状态切换到运行状态有两种选择,第一种是放在后台运行,用bg命令,如“bg %1”,放在前台也类似,用fg命令。

还有一条命令就是kill命令,可以把工作终止掉,关闭进程。使用的方法也是kill加上jobs ID,比如“kill %1”,上图最后也有kill命令。kill命令后面还可以直接跟程序名,比如“kill %find”,这样甚至不用先看jobs ID,如果同时有多个实例在运行的话,会关闭最新的一个。

家里用Linux

今天突发奇想,真的试试在家里用Linux,折腾了好一段时间,还蛮好玩的。

首先把启动的硬盘改为学校带回来的硬盘,这样就能进入GRUB界面了。等待了一些时间,果然,没办法进入Ubuntu的桌面。因为学校电脑用了nVidia的显卡,家里的是ATi的。于是上Google搜到重新配置的命令“sudo dpkg-reconfigue xserver-xorg”,配置完后再输入“sudo /etc/init.d/gdm restart”重新启动图形界面,果然成功了。而且还帮我自动备份原来的xorg.conf,我回到学校就不用再重新配置了。

好不容易进入到桌面,然后就是核心的上网问题了,因为既不是802.1X认证,也不是ADSL的PPPoE。我家用的视讯宽带的认证软件似乎是自己开发的,可惜没有Linux版。然而很意外,在wine下比较顺利就安装成功了。但是启动的时候还不行,加了sudo就可以用wine运行登录软件认证了。

pkuacm

这几天想试试pku的ACM系统,结果出奇地顺利,submit了8题竟然都一次AC了,稍微赞自己一下。也许是前面几题比较简单,也许是真的比以前有点进步,以后继续加油就是了,毕竟业余时间做ACM还是挺好玩的。但是中大的sicily在校外用不了,真郁闷。

Cat命令很好用

在Linux下,有一个cat命令,它的作用是显示某个文本文件的内容。比如“cat a.txt”,就会把a.txt的内容全部显示出来。它是最简单的命令之一,甚至我觉得它只用getchar()和putchar()两个函数就实现了这个功能。

事实上,我以前基本不会去使用这条命令,因为它显示完文件就结束了,这意味着如果文件很长,而终端不能保存很多字符的话,几页屏一下子就刷过去了,根本什么都看不到。使用得更多的是less命令和more命令,more命令可以向下滚屏但是不能向上,less命令既能向下滚屏也能向上,因此比纯粹的cat命令好用得多。

但是最近在学C语言的时候,发现cat命令好用之处就在于它的纯粹。在《The C Programming Language》中,尤其是第一章里,有很多处理字符文本的小程序,比如去掉C语言源文件的注释。程序被设计为键盘输入,我们当然可以手动输入几行去简单验证程序的正确性,但做完之后还是很想直接找个源文件试试。这时cat命令就派上用场了,使用cat输出源文件,再用管道传给程序作为输入,最后可以看到结果是否正确,比如“cat a.c | b.out”。其实more和less的道理也是一样的,如果要输出文本内容,还是要依靠cat,比如“cat a.txt | less”。

Notepad++

前几天用了Notepad++,发现还不错,迟点有机会再介绍。

Alt键输入ASCII码

最近在看《The C Programming Language》,在第一章的时候有一个字符流的程序,然后在测试的时候需要输入各种字符去测试。一般的可见字符当然没问题,不过有些特殊字符还真的不容易输入,因为在键盘模式下面的字符流是比较特殊的。

首先,如果在Linux下的话,要使当前输入的东西作为字符流交给程序处理,有两种办法。第一个方法是按下Enter键,它会发出命令把当前行加上’\n’作为字符流交给程序处理,第二种方法是按Ctrl+D,这是主动发送命令结束本次字符流,如果刚好在一个空行按Ctrl+D,它还会发出EOF文件结束标志。所以如果在Linux下做那本书的实验,很多情况就要按Ctrl+D。

在Windows下也类似,但是按回车的时候返回两个字符,分别是’\r’和’\n’,就是回车和换行。而结束字符流采用的是组合键Ctrl+Z。

ASCII

在Windows下还有一个好处,就是可以用Alt键输入ASCII字符,当然是可打印字符才能输出出来,像’\b’这种退格符就没有办法了。方法是先按下Alt键不放,在小键盘输入ASCII码,然后放Alt,就成功了。如上图所示,如果输入65,就会显示一个A,这种方法是在NumLock键生效的情况才有用。假如NumLock键关闭了,可以使用Alt+Fn的方式,一样可以。

据说Alt键不仅可以输入ASCII,还可以输入Unicode,记得以前QQ流行过这种游戏。准备吃饭,观赏嫦娥。