TCP/IP总结

1、In Action

(1)TCP编程的服务器端一般步骤:

a、创建一个socket,用函数socket();

#include <sys/types/h>

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

b、设置socket属性,用函数setsockopt();  (可选)

c、绑定IP地址、端口等信息到socket上,用函数bind();

int  bind(int sockfd, struct sockaddr * myaddr, int addrlen);

d、开启监听,用函数listen();

int listen(int sockfd, int backlog);将套接字设置为监听模式,以等待连接请求。

e、接收客户端上来的连接,用函数accept();

int accept(int sockfd, struct sockaddr *addr, int *addrlen);接受连接请求,并返回一个与此次连接对应的套接字,此时addr为客户端的addr信息。

f、收发数据,用函数send()和recv(),或者read()和write();

int read(int fd, char * buf, int len);

int write(int fd, char * buf, int len);

用返回的套接字和客户端进行通信。

g、关闭连接

int close(int sockfd);

关闭当前的连接,进入等待状态,继续等待客户端的连接;

关闭服务器端的套接字描述符。

h、关闭监听

 

(2)TCP编程的客户端一般步骤:

a、创建一个socket,用函数socket();

b、设置socket属性,用函数setsockopt();  (可选)

c、绑定IP地址、端口等信息到socket上,用函数bind();(可选)

d、设置要连接的对方的IP地址和端口等属性;

e、连接服务器,用函数connect();

int connect(int sockfd, struct sockaddr * servaddr, int addrlen);其中参数servaddr指定远程服务器的套接字地址,包括服务器的IP地址和端口号。

f、收发数据,用函数send()和recv(),或者read()和write();

g、关闭网络连接

 

(3)UDP编程的服务器端一般步骤:

a、创建一个socket,用函数socket();

b、设置socket属性,用函数setsockopt();  (可选)

c、绑定IP地址、端口等信息到socket上,用函数bind();

d、循环接收数据,用函数recvfrom();

e、关闭网络连接

 

(4)UDP编程的客户端一般步骤:

a、创建一个socket,用函数socket();

b、设置socket属性,用函数setsockopt();  (可选)

c、绑定IP地址、端口等信息到socket上,用函数bind(); (可选)

d、设置对方的IP地址和端口等属性;

e、发送数据,用函数sendto();

f、关闭网络连接

 

2、TIPS

(1)TCP的可靠保证,是它在传输前采用三次握手双向机制建立连接,这保证校验了数据,保证了它的可靠性。而UDP的反应速度更快。

UDP是不可靠的传输协议,即发出去的数据不一定接收得到。

 

(2)TCP/IP协议组流行,是因为它可以用在各种各样的信道和底层协议之上。如:T1和X.25、以太网以及RS-232串行接口。TCP/IP协议是一组包括TCP协议、IP协议、UDP协议、ICMP协议和其他一些协议的协议组。

 

传统的开放式系统互连参考模型,是一种通信协议的7层抽象的参考模型,其中每一层执行某一特定任务。该模型的目的是使各种硬件在相同的层次上相互通信

7层是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

 

TCP/IP通讯协议采用了4层的层级结构,每一层都通过它的下一层所提供的网络来完成自己的需求。这4层为:

应用层:应用程序间沟通的层,如SMTP、FTP、Telnet(网络远程访问协议);

传输层:在此层中,它提供了节点间的数据传送服务。TCP和UDP给数据包加入传输数据并把它传输到下一层中。这一层负责传送数据,且确定数据已被送达并接收

网络层:负责提供基本的数据封包传送功能,让每一块数据包都能到达目的主机,但不检查是否被正确接收。

网络接口层:对实际的网络媒体的管理,定义如何使用实际网络(如Ethernet、Serial Line等)来传送数据。

 

(3)IP

IP层接收由更低层(网络接口层,如以太网设备驱动程序)发来的数据包,并把该数据包发送到更高层;IP层也能把从TCP或UDP层接收来的数据包传送到更底层。

IP数据包是不可靠的,因为IP没有做任何事情来确认数据包是按顺序发送的或者没有被破坏。

IP数据包中含有发送它的主机地址(源地址)和接收它的主机地址(目的地址)。

 

(4)TCP

若IP数据包中有已经封装好的TCP数据包,则IP将把它们向上传送到TCP层。TCP将包排序并进行错误检查,同时实现虚电路间的连接TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传

 

面向连接的服务(如FTP、Telnet、SMTP等)需要高度的可靠性,所以它们使用了TCP。

 

(5)UDP

UDP主要用于面向查询——应答的服务,如NFS,不被应用于使用虚电路的面向连接的服务。

欺骗UDP包比欺骗TCP包更容易,因为UDP没有建立初始化连接(也可以称为握手),因为在两个系统间没有虚电路。 

 

(6)ICMP

和IP位于同一层,被用来传送IP的控制信息,主要用来提供有关通向目的地址的路径信息。ICMP的redirect信息通知主机通向其它系统的更准确的路径,unreachable信息则指出路径有问题。ping是基于ICMP的服务。

 

(7)

TCP和UDP服务通常有一个c/s的关系。如一个Telnet服务进程开始在系统上处于空闲状态,等待着连接。

两个系统间的多重Telnet连接是如何相互确认并协调一致?——>TCP或UDP连接唯一地使用每个信息中的如下四项进行确认:

a、源IP地址

b、目的IP地址

c、源端口

d、目的端口

端口是一个软件结构,被客户程序或服务进程用来发送和接收信息。一个端口对应一个16bit的数

 

3、PS

(1)TCP协议如何关闭连接:

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

a、首先,c(client)调用close(),给server(s)发送FIN,请求关闭连接;s收到FIN之后给c发送ACK,同时关闭读通道,s状态变为CLOSE_WAIT状态。

b、c收到对自己FIN确认的ACK之后,关闭写通道;

c、然后s调用close()关闭连接,给c发送FIN,c收到后给s发送ACK,同时c关闭读通道,进入TIME_WAIT状态;

d、s收到c的ACK之后,关闭写通道,TCP连接转为CLOSED状态,也就是关闭连接。

e、c在TIME_WAIT状态下要等待最大数据段生存期的两倍,然后才进入CLOSED状态,TCP关闭连接的过程才彻底结束。

一个FIN占用一个序号。 

 

(2)TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

a、第一此握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认;

b、第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态;

c、第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。

完成三次握手,客户端与服务器开始传送数据。

 

(3)为什么建立连接协议是三次握手,而关闭连接是四次挥手?

因为服务器端的Listen状态下的socket,当收到SYN报文的建连接请求后,可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭socket,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的

 

(4)为什么TIME_WAIT状态还需要等2MSL后才能返回到closed状态?

因为虽然双方都同意关闭连接了,且握手的4个报文也都协调和发送完毕,按理可以直接回到closed状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的socket可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文

 

(5)FIN_WAIT_1:

 FIN_WAIT_1和FIN_WAIT_2状态都是表示等待对方的FIN报文。FIN_WAIT_1状态实际上是当socket在established状态时,它想主动关闭连接,向对方发送了FIN报文,此时该socket即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态。

 

(6)TIME_WAIT:表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到closed可用状态了。若FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

 

(7)CLOSING:

实际情况下很少见。正常情况下,当你发送FIN报文后,按理说应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却收到了对方的FIN报文。什么情况下会出现此情况呢?——>若双方几乎在同时close一个socket,那么就出现了双方同时发送FIN报文的情况,即会出现CLOSING状态,表示双方都正在关闭socket连接。

 

(8)CLOSE_WAIT

表示在等待关闭。当对方close一个socket 后发送FIN报文给自己,你会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来,你是否还有数据发送给对方,若没有,你就可以close这个socket,发送FIN报文给对方,即关闭连接。因此在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。

 

(9)LAST_ACK

它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章