赞
踩
网络编程
协议栈
Linux 优点之一就是在于它丰富而稳定的网络协议栈,其范围是从协议无关层(如通用的socket层接口和设备层)到各种网络协议的实现;
对于网络理论介绍一般采用OSI模型,但是Linux中的网络栈的介绍一般分为四层的Internet模型
第二部分是传输层协议,包括传输控制协议和用户数据报文协议
传输控制协议(TCP)
该协议对建立网络上用户进程之间的对话负责,他确保进程之间的通信
用户数据报文协议(UDP):UDP提供不可靠的非连接型传输层服务,它允许在源和目的地之间传送数据,而不必在传送数据之前建立对话。它主要用于那些非连接型的应用程序,如视频点播。
应用协议层:这部分主要包括TeInet,文件传送协议(FTP和TFTP),简单文件传送协议(SMTp)和域名
IP协议:IP有以下四个功能
数据传送
寻址
路由器
数据报文的分段
函数
ssocket 函数(主动套接口) C/S都需要使用
创建一个socket
bind
用于绑定IP地址和端口号到socket
connect
该函数用于绑定之后的client端与服务器端
listen (将socket从主动套接口变成被动套接口)
设置能处理的最大连接要求,Listen()并未开始接受连接线,只是设置socket为listen模式。
accept
用来接受socket连接
send
发送数据
recv
接收数据
1)创建套接字:socket函数
·函数原型:
int socket(int domain, int type, int protocol);
参数1:参数位置IPV4(AF_INET)/IPV6(AF_INET6)
参数2:套接字类型
SOCK_STREM:使用TPC
SOCK_DGRAM:使用UDP
SOCK_RDM:使用原始网络通信
SOCK_NONBLOCK:将socket返回文件描述符指定为非阻塞的
SOCK_CLOEXEC:一旦进程exec执行新程序后,自动关闭socket返回的文件描述符
·返回值:
成功:返回套接字文件描述符
失败:返回-1,errno被设置
给套接字绑定ip地址和端口号:bind函数
·函数原型
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数1:socket函数创建的套接字
参数2:保存ip和端口号的结构体
参数2:结构体的长度
·返回值:
成功:返回0
失败:返回-1,errno被设置
出现无法绑定?
client终止时自动关闭socket描述符,server的TCP连接收到client发的FIN段后处于TIME_WAIT状态。TCP协议规定,主动关闭连接的一方要处于TIME_WAIT状态,等待两个MSL(maximum segment lifetime)的时间后才能回到CLOSED状态,因为我们先Ctrl-C终止了server,所以server是主动关闭连接的一方,在TIME_WAIT期间仍然不能再次监听同样的server端口。MSL在RFC1122中规定为两分钟;
解决办法:setsockopt函数
在server代码的socket()和bind()调用之间插入如下代码
将套接字文件描述符,从主动变为被动文件描述符(做监听准备):listen
·函数原型:
int listen(int sockfd, int backlog);
参数1:socket所返回的套接字文件描述符
参数2:指定队列的容量(一般小于30)
·函数功能:
将套接字文件描述符,从主动文件描述符变为被动描述符,然后用于被动监听客户的连接*将套接字文件描述符,从主动文件描述符变为被动描述符,然后用于被动监听客户的连接
·返回值:
成功:返回0
失败:返回-1,errno被设置
被动监听客户的连接并响应:accept函数:
·函数原型:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
·函数功能:
被动监听客户发起三次握手的连接请求,三次握手成功,即建立连接成功
·返回值:
成功:返回一个通信描述符,专门用于与该连接成功的客户的通信,总之后续服务器与该客户间 正式通信,使用的就是accept返回的“通信描述符”来实现的
失败:返回-1,errno被设置
服务器调用read(recv)和write(send),收发数据,实现与客户的通信:
send函数
·函数原型:
size_t send(int sockfd, const void *buf, size_t len, int flags);
参数1:用于通信的通信描述符
参数2:应用缓存,用于存放你要发送的数据
参数3:buf缓存的大小
参数4:
设置为0,send阻塞发送
设置MSG_NOSIGNAL:send数据时,若对方关闭链接调用send的进程便发送SIGPIEIE信号
设置MSG_DONTWAIT:非阻塞发送
设置MSG_OOB:表示发送的是带外数据
recv函数:
·函数原型:
size_t recv(int sockfd, void *buf, size_t len, int flags);
参数1:通信文件描述符
参数2:应用缓存,用于存放接收的数据
参数3:buf缓存的大小
参数4:
设置为0,recv阻塞接收
设置MSG_DONTWAIT:非阻塞接收
设置MSG_OOB:表示接收的是带外数据
·函数功能:
接收对方发送的数据
·返回值:
成功:返回接收的字节数
失败:返回-1,ernno被设置
注意事项:
收发数据的数据需要在网络中传输,所以同样要进行端序的转换:
发送数据:将主机端序转为网络端序
接收数据:将网络端序转为主机端序
不过只有short、int、float等存储单元字节>1字节的数据,才有转换的需求。如果是char这种存储单元为一个字节的数据,不需要对端序进行转换。
调用close或者shutdown关闭TCP的连接:
close:
缺点1:会一次性将读写都关掉了
缺点2:如果多个文件描述符指向了同一个连接时,如果只close关闭了其中某个文件描述符时, 只要其它的fd还打开着,那么连接不会被断开,直到所有的描述符都被close后才断开连接。
出现多个描述指向同一个连接的原因可能两个:
通过dup方式复制出其它描述符
子进程继承了这个描述符,所以子进程的描述符也指向了连接
shutdown:
·函数原型:
int shutdown(int sockfd, int how);
参数1:TCP服务器断开连接时,使用的是accept所返回的文件描述符
参数2:如何断开链接
SHUT_RD:只断开读连接
SHUT_WR:只断开写连接
SHUT_RDWR:读、写连接都断开
函数功能:
可以按照要求关闭连接,而且不管有多少个描述符指向同一个连接,只要调用shutdown去 操作了其中某个描述符,连接就会被立即断开
·返回值:
成功:返回0
失败:返回-1,errno被设置
·用socket创建套接字文件,指定使用TCP协议
·调用connect主动向服务器发起三次握手,进行连接
函数原型:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数1:socket所返回的套接字文件描述符
参数2:用于设置你所要连接服务器的IP和端口
参数3:参数2所指定的结构体变量的大小
功能:
向服务器主动发起连接请求
返回值:
成功:返回0
失败:返回-1,ernno被设置
·调用read(recv)和write(send)收发数据
·调用close或者shutdown关闭连接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。