
UNIX网络编程 卷1
alenliu0621
随风飘飘天地任逍遥~~~
展开
-
《UNIX网络编程 卷1》 笔记: 服务器程序设计范式
本节也是系列的最后一节,我们讨论TCP服务器的设计范式。为了简单比较不同设计的服务器性能,我们实现了一个用于测试的客户端程序,它使用多进程建立多个连接,每个连接从服务器获取特定的字节数。使用如下:client 第一个命令行参数是hostname服务器IP,第二个参数port是服务器端口号,第三个参数children是客户要创建的子进程个数,第四个参数loops是每个子进程建原创 2017-07-28 16:41:47 · 5322 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: TCP 客户/服务器程序示例
本节我们实现一个简单的TCP回显服务器和客户程序,来说明一个典型的TCP服务器程序和客户程序如何工作。TCP回显服务器程序的功能很简单,就是将客户发送过来的数据再返回给客户。TCP回显客户程序的功能是从标准输入读取一行数据,发送给服务器,再把服务器返回的数据输出到标准输出。TCP回显客户程序的代码如下: #include "unp.h"void str_cli(FILE ...原创 2017-05-24 21:38:28 · 3789 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 使用poll函数的单进程TCP回显服务器程序
本节我们使用poll函数来实现单进程TCP回显服务器。poll函数与select函数不同,它不使用描述符集,而是使用pollfd结构体数组,pollfd结构体如下: struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short ...原创 2017-05-25 20:00:24 · 3510 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 使用select函数的单进程TCP回显服务器程序
在TCP 客户/服务器程序示例这一节中,我们编写了一个多进程的TCP回显服务器程序,本节我们使用select函数监听服务器套接字和所有的客户的套接字来实现同样的功能。具体实现就是每当一个新的客户建立连接,我们把它的套接字描述符(为了与服务器程序自身的监听描述符作区分,我称服务器程序为服务客户创建的套接字为“客户套接字”)保存在一个数组中,然后将该描述符加入select函数监听的读描述符集中,然后循...原创 2017-05-25 16:51:05 · 3566 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 基本UDP套接字编程
不同于TCP协议,UDP协议是无连接的不可靠传输协议。客户与服务器之间通信不需要建立连接,客户使用sendto函数向服务器发送UDP数据报,该函数的参数要求必须指定服务器的IP地址和端口号。服务器使用recvfrom接收客户发送的UDP数据报,在指定的参数中保存客户的IP地址和端口号(可选)。由于UDP协议使用不可靠的IP协议,而它自身也没有实现可靠传输机制,所以我们说UDP协议是不可靠的传输...原创 2017-05-25 21:27:55 · 4519 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 名字与地址转换
前几节我们一直用IP地址表示主机,用端口号表示服务,与服务器通信必须要知道服务器的IP地址和端口号,这显然不方便。对于我们来说记住主机名和服务名更容易。如下图所示:在linux系统中,/etc/hosts文件保存了本地IP地址和主机名的映射关系,/etc/service文件保存了端口号和服务名之间的映射关系。如果在/etc/hosts文件中找不到主机名对应的IP地址,则linu原创 2017-05-25 23:08:34 · 4895 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 高级I/O函数
本节我们关注称为“高级I/O”的各个函数和技术。首先是在I/O操作上设置超时。在涉及套接字的I/O操作上设置超时的方法有以下3种;1. 调用alarm函数,在定时时间超时产生SIGALRM信号,打断I/O操作。首先我们给出要使用的Signal1函数的实现,这个函数不是系统调用signal的包裹函数,而是我们自己实现的signal1函数的包裹函数。因为Linux系统上很多系统调用都是自重原创 2017-05-26 17:56:20 · 4897 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记补充内容: 高级轮询技术epoll
epoll是Linux提供的高级轮询技术,《UNIX网络编程 卷1》成书时还没有这种技术。它的效率要比单独使用poll函数高很多,非常适合监听大量的描述符,许多高性能的服务器都使用epoll。下面是epoll提供的API,具体使用请参考下面的代码和man手册。 /*创建一个epoll实例,返回其描述符*/int epoll_create(int size);int epoll_cre...原创 2017-05-26 21:09:11 · 5072 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: UNIX域协议
Unix域协议并不是一个实际的协议族,而是在单个主机上客户进程和服务器进程之间通信的一种方法。Unix域使用的套接字结构如下: struct sockaddr_un { sa_family_t sun_family; /* AF_UNIX */ char sun_path[108]; /* pathname */};Unix域中标识客户和服务器的协议地址是普通文件系统中的路径名...原创 2017-05-26 23:33:08 · 4348 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 描述符传递技术
Linux提供了一种从一个进程向另一个进程传递任意打开的描述符的技术,这两个进程可以无亲缘关系。这种技术要求首先在这两个进程之间创建一个Unix域套接字,然后使用sendmsg跨套接字发送一个特殊的消息,这个消息由内核来处理,会把打开的描述符传递到接收进程。先来看看要使用的数据结构和函数。struct msghdr { void *msg_name; /* optional addr原创 2017-05-27 14:42:56 · 4276 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 非阻塞式I/O
本节讨论非阻塞式I/O操作。默认的I/O操作如read或write函数等都是以阻塞的方式工作。比如read函数,如果没有数据可读取则进程一直阻塞直到有数据可读取。这种工作方式会带来某些问题。回到我们在I/O复用 select函数这一节实现的客户与服务器交互的str_cli函数,摘取其中处理标准输入的一段代码如下:if (FD_ISSET(fileno(fp), &rset)) { /*原创 2017-05-27 20:38:16 · 3913 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 非阻塞式connect—web客户程序
上一节我们实现了非阻塞式connect,本节我们就可以使用它来实现一个有趣的程序——web客户端。我们要实现的web客户程序名为web,用法如下:web ...conns为建立的最大连接数。hostname为服务器主机名。homepage为服务器主页,比如index.html。后面跟着一连串服务器上的文件名。先给出头文件的一些定义:#include "unp.h"原创 2017-05-28 00:13:05 · 3510 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: I/O复用 select函数
上节我们实现的TCP回显客户程序有缺陷,代码如下: void str_cli(FILE *fp, int sockfd) { char sendline[MAXLINE], recvline[MAXLINE]; while (Fgets(sendline, MAXLINE, fp) != NULL) { /*从标准输入读取一行文本*/ ...原创 2017-05-25 00:01:35 · 3575 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: readline函数 (可重入版本)
上一节实现的readline函数由于使用全局变量,在多线程环境下使用就会出现问题。为了解决这个问题,我们使用Linux提供的线程特定数据功能,它允许每个线程都有自己的特定数据,这样就不会和其他线程产生冲突了。具体使用如下: 1. 调用pthread_key_create获取一个未使用的键(索引),同时指定释放数据的函数。 2. 调用pthread_getspecific获取原创 2017-05-24 11:39:06 · 4318 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 多线程—web客户程序
在非阻塞式connect—web客户程序一节中,我们使用非阻塞式connect(对于每个待读取的文件,向服务器发起非阻塞连接)和select(监听所有的套接字描述符)实现了一个web客户程序,本节我们使用线程来实现同样的功能。我们为每个待读取的文件创建一个线程,这个线程完成从服务器上读取文件的工作。因而我们修改了之前定义的file结构体:struct file { char *f_nam原创 2017-06-02 21:54:30 · 4228 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 互斥锁与条件变量
考虑下两个线程同时对同一个全局变量i(初始值为0)进行自增操作(i++)会发生什么情况。C编译器将自增运算符转换成三条机器指令:从内存装载到寄存器、递增寄存器、从寄存器存储到内存。可能发生如下情况: 1. 线程A运行,把变量i的值0装载到一个寄存器。 2. 内核调度模块决定运行线程B,此时线程A的寄存器被保存,B的寄存器被恢复。 3. 线程B执行完自增操作的三条指令后,把新值1存...原创 2017-06-01 23:40:50 · 4520 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 线程
在非阻塞式I/O一节中,我们使用fork实现了一个多进程TCP回显客户程序,使得父进程处理标准输入到套接字的数据,子进程处理套接字到标准输出的数据。 void str_cli(FILE *fp, int sockfd) { pid_t pid; char sendline[MAXLINE], recvline[MAXLINE]; /*子进程 socket --...原创 2017-06-01 22:59:04 · 4313 阅读 · 7 评论 -
《UNIX网络编程 卷1》 笔记: 信号驱动式I/O
信号驱动式I/O是指进程预先告知内核,使得当某个描述符上发生事件时,内核使用信号通知该进程。针对一个套接字使用信号驱动式I/O(SIGIO)的步骤如下: 1. 建立SIGIO信号的处理函数 2. 设置该套接字的属主,通常使用fcntl的F_SETFL命令设置。 3. 开启套接字的信号驱动式I/O,通常使用fcntl的F_SETFL命令打开O_ASYNC标志。对于TC...原创 2017-06-01 21:03:39 · 4542 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记补充内容: 发送任意以太网帧
Linux提供了 packet 套接字,使得应用层可以从设备驱动层(链路层)接收以太网帧或者发送以太网帧到设备驱动层。 packet_socket = socket(AF_PACKET, int socket_type, int protocol);socket_type参数为SOCK_RAW或SOCK_DGRAM。两者的区别是SOCK_RAW要求用户自己构造以太网首部,而SOCK_...原创 2017-03-08 14:41:32 · 6466 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: UDP应用实现超时重传机制
UDP是不可靠的,它只是一直发送数据,而不管数据有没有被对方成功接收。怎样能确保发送的数据报被对方成功接收?这需要发送方和接收方共同协作。1. 接收方成功收到数据后发送一个确认,发送方收到这个确认后就知道接收方已成功收到数据。2. 如果发送方在一定的时间内没有收到确认,则重传数据。在我们的UDP回射客户和服务器例子中,客户发送的数据报都会被服务器回射,也就是每个数据报都对应了一个回原创 2017-05-29 23:03:11 · 5624 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 竞争条件!
本节书中将race condition翻译成竞争状态,并定义为:当有多个进程访问共享的数据,而正确的结果取决于进程的执行顺序时 ,我们称这些进程处于竞争状态。而我更喜欢将这个词称为竞争条件:如果一个程序的执行结果取决于进程(运行中的程序称为进程)的执行顺序,那么我们说这个程序包含有竞争条件。进程的执行顺序是什么意思呢?我们知道Linux是多任务操作系统,系统中同时运行着多个进程(任务)。当我们...原创 2017-05-28 21:51:52 · 3348 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 广播
之前几节我们展示的客户服务器通信方式都是单播的通信方式,也就是一台主机上的进程和另一台主机上的进程通信。本节我们讲述广播通信,这种通信方式只有UDP协议支持,它使得一台主机能够和主机所在子网上的其他所有主机同时进行通信。为了方便,这里我们只讨论IPv4地址,后面所指的IP都是IPv4地址。我们知道IP地址长度为32位,一般使用的单播IP地址由{子网ID,主机号}组成,子网ID的位数由子...原创 2017-05-28 19:26:13 · 3358 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: readn和writen函数
字节流套接字上调用read或write读取或写入的字节数可能比请求的数量少,这是正常的现象。原因在于内核中用于套接字的缓冲区可能已达到了极限(例如套接字的接收缓冲区可能没有数据或发送缓冲区没有可用空间),此时所需的是调用者再次调用read或write函数,以读取或写入剩余的字节。我们实现的从套接字上读取n字节数据的readn函数和写入n字节数据到套接字的writen函数代码如下: #...原创 2017-05-23 23:39:19 · 4848 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: readline函数 (不可重入版本)
网络编程中经常和一些基于文本行的协议打交道,典型的比如SMTP、HTTP等,所以需要一个读取文本行的操作。很缓慢的实现是每次read读取一字节然后判断是不是行尾,比较高效的实现是使用一个全局缓冲区buf,首先read一定量的数据放入buf,然后从buf中取出一行数据,具体实现如下:原创 2017-05-24 00:19:04 · 4652 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 错误处理和包裹函数
为了处理程序运行中的系统调用错误和一般性错误(比如有时候需要输出错误消息,有时候需要输出错误消息并终止进程,有时当进程以后台方式运行时需要将错误消息记录到syslog),我们定义了一些通用的错误处理函数,这些函数实现如下:#include "unp.h"#include int daemon_proc; /*后台进程标志,输出消息到syslog*/static void er原创 2017-05-24 00:55:22 · 4228 阅读 · 0 评论 -
《UNIX网络编程 卷1》 笔记: 原始套接字—ping程序
原始套接字提供普通的TCP和UDP套接字所不提供的以下3个能力: 1. 进程可以读写ICMPv4、IGMPv4、ICMPv6分组。 2. 进程可以读写内核不处理其协议字段的IPv4数据报。 3. 进程可以使用IP_HDRINCL套接字选项自行构造IPV4首部。本节我们使用原始套接字来实现一个常用的程序:ping。为了同时支持ICMPv4和ICMPv6,我们定义原创 2017-06-15 10:38:02 · 5409 阅读 · 2 评论