您的位置:首页 > 理论基础 > 计算机网络

unix网络编程1 基础知识

2015-04-05 18:39 369 查看

Introduction

通过学习unix网络编程,在不使用任何库只使用api的情况下实现一个内置lua解释器的web服务器,实现简单的业务逻辑,比如通过cgi模式在web浏览器中显示图片,播放视频,可以在不重启服务器的情况下更新业务逻辑。

主要是学习unix网络编程做的笔记,其中将插入网络编程

的基础知识,会有多进程版,I/O复用,多线程版本,每个web

服务器的吞吐量,并发连接数我都会有测试,最后会有对比图。

基础知识

要编写计算机网络通信程序,首先要确定的就是通信的协议(protocol)。一般认为web服务器是一个长时间运行的程序(deamon),它只是在响应来自网络的请求时才发送网络信息。协议的另外一端就是web客户程序,如某种浏览器。一般来说都是客户端向服务端发消息,服务端就一直等着。也有服务器向客户发起请求的异步回调(asynchronous callback)通信,但是一般还是如下图的客户端/服务器模式。



多个客户向一个服务器发送请求



web客户端和服务器使用TCP(Transmission Control Protocol,传输控制协议)通信。TCP又转而使用IP(Internet Protocol,网际协议)通信,IP通过链路层通信。下图表示通信层次【局域网的情况】.

观察到虽然应用层是使用某种应用通信协议,比如FTP,HTTP。传输层都是是使用TCP协议。

下图又展现了客户/服务端信息流的传送方向,客户把信息从上到下通过链路层传送到服务器端,服务端从链路层读取一直到应用层。



如果客户/服务端要在广域网通信则需要使用路由器。如下图



OSI模型

下图所示,我们只关心传输层,以及数据链路层1500字数据限制,其他层都可以不管。



下面只介绍TCP,不介绍UDP,UDP相关资料请参考unix网络编程相关章节。TCP是一个复杂的、可靠的字节流协议。

UDP不提供确认,序列号,超时,重传,RTT估算等机制。

TCP提供客户与服务器之间的连接(connection),客户端先和服务器建立连接,连接之后才能交换数据,最后连接终止。

TCP提供可靠性,当TCP发数据要求对端要发送一个确认。如果没有收到数据就会重传数据,并且等待比上一次更长的时间[这个有算法计算往返时间(round-trip time,RTT),多次失败以后才放弃。

[注意TCP传送的数据不能保证100%正确,它只能保证客户端收到了没有,不保证正确性]

TCP给每一个字节一个序号,对发送的数据进行排序。通过这种方式TCP接收端可以对乱序的数据根据序号进行排序,如果有一个字节是重复的(因为网络拥堵的情况重传了数据),接收端就可以通过相同的序号丢弃掉这个字节

TCP提供流量控制(flow control).TCP会告诉对端任何时刻能够可以接收的数据有多少,这个叫做通知窗口(advertised window).任何时刻窗口接收缓冲区能够接收多少数据。

TCP是全双工(full-duplex)的,既可以发数据,又可以接收数据,而且为每一个数据流方向都提供,流量控制,跟踪序列号等。

TCP的建立

三路握手

服务端被动打开(passive open),通过调用socket、bind、listen三个函数来完成。

客户端主动打开(active open),通过调用connect函数来完成,这会导致TCP发送一个SYN分节(分节里面含有连接建立以后传送数据的初始序号)

服务器必须确认(ACK)客户的SYN,并且它也发送一个SYN(里面含有服务端在连接建立以后发送第一个字节数据的序号)

客户必须确认服务端的SYN。

这种交换至少需要三个分组,所以称为三路握手(three-way handshake),下图表现三路握手

下图中客户的初始序号是J,服务器的初始序号是K,ACK是下一次希望接受的序号。SYN和FIN都占了一个字节,所以ACK要加1。

注:分节是什么?

网络各层是交换的信息单位是协议数据单元(protocol data unit,PDU),分节(segment)就是对应与TCP传输层的PDU。分节的长度是有限的。每个分节所封装的数据可以是应用进程的字节流数据(就是tcp通过输出操作写到套接字中的数据),按顺序封装后传送给TCP接收端。下面这两剧很重要请注意,就是每个分节所封装的由应用进程的数据可能不完整,这取决于,对端所告知的最大分节大小,下面会讲,以及链路层的外出接口最大传输单元(MTU).ip层(ipv4)所接收的最大数据为65535字节,所以运输层的数据不能超过这个数,还有传达链路层超过1500字节会分片。



TCP选项

MSS选项。通知对端它的最大分节大小(maximum segment size),发送端使用接收端的MSS值作为所发分节的最大大小。

窗口规模选项。TCP连接通知对端的最大窗口是65535

TCP连接终止

TCP连接终止需要四个分节

应用进程主动关闭(active close),调用close函数实现,该端的TCP发送一个FIN分节,表示数据发送完毕。

接收端接收了这个FIN分节就会进行被动关闭(passive close),TCP还要给发送端一个确认。FIN放在排队的数据后面,作为一个文件结束符(end-of-file)传递给应用进程,对端接收到FIN以后就没数据读了。

一段时间后收到文件描述符的应用进程也会调用close函数这也会导致它的TCP向发送方发FIN分节。

接收到第二个FIN分节,发送端再确认这个分节。

注意:第二步和第三部在FIN分节一起发送的时候就合并为一步。

下图展示TCP连接终止



TCP状态转换图 TCP建立连接和连接终止

黑线表示客户正常状态转换

虚线表示服务器正常状态转化



下图是一个从开始建立连接,指示对端分节大小,服务端可以接收单个分节的最大大小是1460字节,客户端是536字节。建立连接就可以发送数据了,最后结束是四个分节。



端口号

使用端口号来区分进程。

唯一表示一台服务器,客户端通过众所周知端口号(well-konwn port)。

客户端使用创输层临时分配的端口号。

套接字对

TCP连接的两端的端口号+ip地址

TCP端口号和并发服务器

并发服务器通过主服务器派生子进程处理新的连接.

比如在freebsd上启动一个服务器,端口号21,该主机多宿,ip地址12.106.32.254和192.168.42.1.服务器被动打开使用{* : 21,* : },服务器在任意本地接口(第一个 ),21端口号等待连接,这个称其为监听套接字,后面外地地址是用接收任意地址的客户的访问,所以用 * 表示.当服务器接收客户连接时,将连接交给子进程处理.连接建立后要把已连接套接字填入.



并发服务器让子进程处理客户



处理第二个客户,TCP客户主机第二个客户分配的端口号是1501



缓冲区大小

ipv4定义了最小重组缓冲区大小(minimum reassembly buffer size),支持最小数据报大小是576字节.

MSS最大值为65535

以太网使用ipv4最大1460(tcp首部20字节,ipv4首部20字节)

下面是重点注意

每一个TCP套接字都有一个发送缓冲区,当某个应用进程调用write,内核从该应用进程复制数据到发送缓冲区,如果发送缓冲区放不下,应用进程进入睡眠.假设该套接字是阻塞的,内核不从write系统调用返回,直到应用进程缓冲区所有数据都复制到套接字发送缓冲区.从write返回仅仅表示应用进程数据复制到套接字发送缓冲区,并不表示对端接收到数据.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息