Linux下的网络编程

网络编程

协议栈

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关闭连接

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值