UNIX网络环境配置,网络编程学习前7章小结

前言

这一周开始学习UNIX网络编程了,虽然这一周项目的压力很大,不过最后还是顶住了压力,尽量平衡了实验室工作和自主学习。

不过话虽这么说,毕竟还是有一周的时间基本没怎么学习了,看我的博客发表日期就知道了,少了一篇。

好了,进入正文吧。

第一章:简介和TCP/IP

这一章一开始就展示了一个时间获取客户端程序和服务器端的程序。学过了linux程序设计之后,这部分的代码我已经可以直接看懂,也很容易的就自己编程完成了开发。不过编译的时候却出了问题。我在网上下载了该书的源码,发现加入的unp.h并不能使用,原来是这个头文件里面定义了特别多的包裹函数,即是包含了错误处理的函数。一番折腾之后,编译出了libunp.a的库文件,修改好了重定义。然后就成功的编译完成了第一个程序。并且在自己linux主机上完成了试验。


第二章:传输层:TCP、UDP和SCTP

这一章也主要是几个协议的简介,初步了解TCP,UDP,以及SCTP之间的区别,这些知识我在大学本科的时候已经学过一遍了,现在在复习了一次,所以看起来的速度还是挺快的。

最重要的TCP三次握手和4次握手终止也再复习了一次。比较重要的新知识就是TCP状态转换图了。特别是在主动关闭那端的TIME_WAIT状态,停留2个MSL长度,来保证网络中遗留的连接分节全部消失,避免新的连接接收到这些老的数据。

其他各种状态用的也非常的多,36页的TCP状态图也经常翻回来看。


第三章::套接字编程简介:

第一部分讲述的内容是套接字地址结构,现在用的是ipv4和ipv6,还有一些其他的unix上的结构,大体上就包括三个部分,sin_family, sin_port, sin_addr三个部分,ipv6的在为sin6。并且有一个通用的套接字结构,sockaddr_storage,在不确定地址的时候可以使用这个。字节排序函数用来统一网络上的字节序,避免不同的主机读取到消息后产生不同的判断。常用的函数有四个。

地址转换函数有inet_pton和inet_ntop是两个新的,ipv4和ipv6都适用的字符串转换ip地址的函数。以后的代码中尽量都使用这个新的函数。


第四章:基本的TCP套接字编程

到了这一章,总算是涉及了编程了。过程还是与之前的学习相同的,socket函数生成套接字,bind函数绑定套接字与ip和端口,listen函数改变套接字为监听模式。connect函数连接套接字,accept函数返回新的用于通信的套接字。

在这里新学到的知识就是明白了bind函数到底是用来干嘛的,之前的学习只说给套接字命名,但是不明白有什么作用,客户端可以不调用bind函数直接调用connect函数,这样系统内核就会自动给客户端的套接字分配一个ip和端口号,然后用这个ip和端口号与服务器通信,那么服务器可以不调用bind函数吗?想想就明白不可能了,因为如果服务器的ip和端口号是随机分配的,那么客户端怎么知道去连接哪一个端口号和ip呢。并且通配地址也不是指任何地址,而是由内核分配地址的。

listen函数会把创建的默认主动套接字改成被动套接字,第二个参数就是可以未完成队列和已完成队列的总数和了,不一定等于第二个参数的值,取决于系统的实现。并且在listen阶段就会和客户端完成3次握手,完成之后就进入了已完成队列了,等待accept函数的调用。

accept函数可以得到客户的ip和端口,并且返回可以与客户进行通信的sockfd,然后就可以开始通信。

服务端可以在接收到一个新的客户端请求之后调用fork函数和exec函数来建立多进程服务客户端。

最后完成了通信之后,调用close函数关闭套接字,如果关闭的是最后一个对套接字的引用时,会主动发送一个FIN信号。

getsockname与getpeername可以用来获得本地或者客户端的IP地址和端口号,一般用在子进程处理中。


第五章:TCP客户/服务器端程序实例

这一章列出了最简单的服务器与客户端程序,实现的功能就是客户端输入,服务器端回射,然后在此基础上讨论各种可能在通信过程中出现的问题。不过介于我使用的时候只能在本地上做实验,有一些情况并没能亲自测试一次。

程序运行之后调用netstat -a可以查看到端口与ip地址对应的网络状态。

正常终止的时候,输入ctrl+D就可以发送一个EOF,read调用将会返回一个0,代表到达了文件末尾了。客户端先关闭了套接字,因此会发送一个FIN给服务器端,服务器端收到EOF之后也会关闭套接字,因此发送终结连接的最后两个分节,服务器端到客户端的FIN和客户端到服务器的ACK。然后客户端进入TIME_WAIT状态,直到所有的分节都在网络中消失。

然后是关于子进程结束的信号处理,使用wait函数与waitpid函数,又有阻塞和非阻塞之分,这些内容在学习linux程序设计的时候基本已经学习到了,所以不是特别大的问题。

之后便是各种连接可能遇到的问题,accept之前收到RST信号的处理取决于各个系统的实现,所以基本上没有一个确定的答案。 服务器端关闭的时候,如果sockfd被关闭了,那么会主动发送一个FIN给客户端,客户端然后返回一个ACK,但是这时连接还没有终止,除非客户端收到FIN之后主动关闭套接字,才会完成四次握手,关闭连接,此时客户端还是可以继续往套接字里写数据的,不过由于服务器已经奔溃,所以服务器端回返回一个RST信号回来。客户端在调用玩write函数之后调用read,会由于之前收到的FIN信号立刻返回一个EOF,然后结束进程。

如果上述的情况下,客户端不管收到的RST信号,继续往套接字里写,那么内核会发送一个SIGPIPE信号给进程,默认终止进程。

服务器端奔溃,不会发送FIN信号,因此客户端什么也不会收到。客户端发送给服务器端的消息不会收到ACK,或者客户端阻塞在read调用之上,最终会导致timeout错误或者unreachable错误。

如果服务器奔溃后重启了,那么客户端发送的消息会返回一个RST信号。

数据格式是在网络中传输的一个重要问题,由于字节序的问题,所以在不同机器上传递数据是有风险的,不一样的结构会导致传递错误,所以就有了http超文本协议,传递字符串是一定不会出错的。


第六章:IO复用:select函数和poll函数

这一章主要讲诉的是IO模型,有5种基本的模型:

阻塞式IO,非阻塞式IO,IO复用, 信号驱动式IO, 异步IO。

最常用的就是前三个了,信号驱动式io在描述符就绪时,内核会发送SIGIO通知我们。异步IO是使用的非常少的。

使用select函数和poll函数可以完成IO复用,调用的时候阻塞在select函数上,直到有一个文件描述符可用,然后才返回可用的个数。使用宏定义FD_ISSET来测试该描述符是否是可用的描述符。调用select函数的第一个参数maxfdp1是所有描述符里最大值加一,所以用起来会有一些不方便,但是熟悉了之后不是问题。

shutdown函数可以只关闭RD或者WR部分,关闭WR部分时会主动发送一个FIN,不用等到所有的文件描述符都关闭。但是这部分里有一个问题我没能解决,就是重定向文件给stdin,我试了几次都失败了,暂时没有找到解决的办法。


第七章:套接字选项

这一部分就是特别理论的部分了,不过还好我之前本科的学习还记得不少,所以大部分的知识没有花费太多的力气就了解了,只是可能真的记不住,选项主要使用setsockopt函数与getsockopt函数来设置与获取。唯一有些头疼的部分就是值-结果参数了,这个参数主要是用来描述内核与进程通信时使用的参数的,重点就是需要传输结构的大小参数。在设置和获取套接字选项的时候,获取参数的数据结构是不同的,这一部分理解了就没有问题了。

其他的选项有些比较重要,看一遍的时候理解,不过估计过不了多久久会忘记,所以这一部分应该以后会需要常常回来复习的。

我学习完之后直观感觉,常用的应该是这些:SO_KEEPALIVE, SO_LINGER, SO_REVBUF, SO_SNDBUF, SO_REUSEADDR, SO_REUSEPORT, TCP_NODELAY。学完感觉差不多就是这些了。以后其他的 需要的时候再回来看就行了,

总结

这一周的学习让我感觉到我的速度应该可以变快更多,不过由于最近忙于考试和项目,没有更多的时间花在这里了,只能暂时保持这个进度前进吧。东西不难,我希望能学到更多,更快。课后的习题我尝试去做了,基本都很简单,希望这代表我都已经学明白了。

你可能感兴趣的:(UNIX网络环境配置,网络编程学习前7章小结)