首页 > 代码库 > socket网络编程

socket网络编程

从各位大神那里学习的,备忘。

 

Internet 套接字的两种类型:

一种是"Stream Sockets"(流格式),(SOCK_STREAM)  例子:telnet,可靠传输,使用TCP协议

另外一种是"Datagram Sockets"(数据包格式),(SOCK_DGRAM) 例如:tftp, bootp 不可靠传输,使用TCP协议

网络分层模型:

  应用层 (Application) 
  表示层 (Presentation) 
  会话层 (Session) 
  传输层(Transport) 
  网络层(Network) 
  数据链路层(Data Link) 
  物理层(Physical) 

把它对应 到 Unix,结果是: 
  应用层(Application Layer) (telnet, ftp,等等) 
  传输层(Host-to-Host Transport Layer) (TCP, UDP) 
  Internet层(Internet Layer) (IP和路由) 
  网络访问层 (Network Access Layer) (网络层,数据链路层和物理层) 

存在两种字节顺序:NBO与HBO
网络字节顺序NBO(Network Byte Order):
按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
主机字节顺序(HBO,Host Byte Order):
不同的机器HBO不相同,与CPU设计有关(个人理解是大小端模式)

很多网络到本机字节顺序的转换可转两种类型: short (两个字节)和 long (四个字节):
  htons()--"Host to Network Short" 
  htonl()--"Host to Network Long" 
  ntohs()--"Network to Host Short" 
  ntohl()--"Network to Host Long" 
  小问题:为什么在数据结构 struct sockaddr_in 中, sin_addr 和 sin_port 需要转换为网络字节顺序,而sin_family 需不需要呢? 答案是: sin_addr 和 sin_port 分别封装在包的 IP 和 UDP 层。因此,它们必须要 是网络字节顺序。但是 sin_family 域只是被内核 (kernel) 使用来决定在数 据结构中包含什么类型的地址,所以它必须是本机字节顺序。同时, sin_family 没有发送到网络上,它们可以是本机字节顺序。 

socket()函数:
#include <sys/types.h> 
#include <sys/socket.h> 
int socket(int domain, int type, int protocol); 
但是它们的参数是什么? 首先,domain 应该设置成 "AF_INET",就 象上面的数据结构struct sockaddr_in 中一样。然后,参数 type 告诉内核 是 SOCK_STREAM 类型还是 SOCK_DGRAM 类型。最后,把 protocol 设置为 "0"。(注意:有很多种 domain、type,我不可能一一列出了,请看 socket() 的 man帮助。当然,还有一个"更好"的方式去得到 protocol。同 时请查阅 getprotobyname() 的 man 帮助。) 
socket() 只是返回你以后在系统调用种可能用到的 socket 描述符,或 者在错误的时候返回-1。全局变量 errno 中将储存返回的错误值。(请参考 perror() 的 man 帮助。) 

TCP/IP 11种状态
LISTEN - 侦听来自远方TCP端口的连接请求; 
SYN-SENT -在发送连接请求后等待匹配的连接请求; 
SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认; 
ESTABLISHED- 代表一个打开的连接,数据可以传送给用户; 
FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
FIN-WAIT-2 - 从远程TCP等待连接中断请求; 
CLOSE-WAIT - 等待从本地用户发来的连接中断请求; 
CLOSING -等待远程TCP对连接中断的确认; 
LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认; 
TIME-WAIT -等待足够的时间以确保远程TCP接收到连接中断请求的确认; 
CLOSED - 没有任何连接状态;

客户端TCP状态迁移:CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED

服务器TCP状态迁移:CLOSED->LISTEN->SYN_RCVD ->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED

 

当客户端开始连接时,服务器还处于LISTENING,

客户端发一个SYN包后,他就处于SYN_SENT状态,服务器就处于SYS收到状态,

然后互相确认进入连接状态ESTABLISHED.

当客户端请求关闭连接时,客户端发送一个FIN包后,客户端就进入FIN_WAIT_1状态,等待对方的确认包,

服务器发送一个ACK包给客户,客户端收到ACK包后结束FIN_WAIT_1状态,进入FIN_WAIT_2状态,等待服务器发过来的关闭请求,

服务器发一个FIN包后,进入CLOSE_WAIT状态,

当客户端收到服务器的FIN包,FIN_WAIT_2状态就结束,然后给服务器端的FIN包给以一个确认包,客户端这时进入TIME_WAIT,

当服务器收到确认包后,CLOSE_WAIT状态结束了,

这时候服务器端真正的关闭了连接.但是客户端还在TIME_WAIT状态下,

什么时候结束呢.我在这里再讲到一个新名词:2MSL等待状态,其实TIME_WAIT就是2MSL等待状态,

为什么要设置这个状态,原因是有足够的时间让ACK包到达服务器端,如果服务器端没收到ACK包,超时了,然后重新发一个FIN包,直到服务器收到ACK 包.

TIME_WAIT状态等待时间是在TCP重新启动后不连接任何请求的两倍.

 

 

 

 

 

参考:

http://www.cnblogs.com/Jessy/p/3535612.html

http://blog.csdn.net/roger_77/article/details/1453049

http://blog.csdn.net/bestone0213/article/details/44872529

socket网络编程