当前位置: 首页 > web >正文

LinuxC语言系统开发——网络编程

一.网络编程
1. 网络基础
1.1  网络的作用?
网络是用于远距离,跨主机的数据通讯。

    1.2  网络体系结构:
网络数据的传输过程往往是比较复杂的,为了网络数据完整,一致,安全性的送达给目标主机,
计算机网络系统对数据的传输过程进行了分段,分层管理,每一层都有该层功能,同时每一层
给下一层提供服务,也可以使用上一层提供的服务,这种分层结构以及每一层所提供的功能
协议的及格,称为网络体系结构。

    1.3  两种重要的网络体系结构模型
1) ISO提供的 OSI 七层协议模型:
应用层
表示层
会话层
传输层
网络层
数据链路层
物理层
2) TCP/IP 四层协议模型 (事实上的工业标准)
应用层
传输层
网络层
网络接口层

    1.4  传输层的协议

          1) TCP(传输控制协议)
TCP:面向连接的可靠的数据传输服务。
面向连接: 通讯双方在数据交互之前,必须要建立网络连接。

             原则:网络程序实际应用, 往往是基于 C / S 架构,或者是 B / S 结构。

         网络连接的建立过程:(三次握手过程)

          第一次握手: 客户端发送SYN(握手信号)给服务器,客户端进入 SYN_SEND,等待服务器回应;
第二次握手: 服务器发送SYN(握手信号)+ ACK(响应信号)给客户端,服务端进入 SYN_RECV;
第三次握手: 客户端发送ACK(响应信号)给服务端,完成TCP网络连接;上方进入 ESTABLISHED状态。

         网络断开的过程:(四次挥手过程)

          第一次挥手: 客户端发送FIN(挥手信号)给服务器,客户端进入 FIN_WAIT1,等待服务器回应;
第二次挥手: 服务器发送ACK(响应信号)给客户端,服务端进入 CLOSE_WAIT,客户端进入 FIN_WAIT2;
第三次挥手: 服务器发送FIN(挥手信号) + ACK(响应信号)给客户端,服务端进入 LAST_ACK;
向客户端请求断开服务器到客户端方向的数据传输.
第四次挥手: 客户端发送ACK(响应信号)给服务器,客户端进入 TIME_WAIT,等待网络关闭,2MSL
后完成网络断开;服务器接收到客户端发送ACK(响应信号),连接关闭

        面试题:为什么TCP建立过程需要3次握手,而断开需要4次挥手?
因为TCP的连接是双向的,在断开时,需要在每个方向都要单独进行数据关闭,连接断开。


2) UDP(用户数据报协议) 

          UDP:面向无连接的不可靠的数据传输服务。

          UDP协议的特点:
1. 无连接,不可靠
2. 系统的资源消耗少,因为不连接就不需要系统去维护连接状态;
3. 实时性高,
4. UDP可以实现一对多通讯

2. 网络编程应用  
2.1  网络专业术语
1)  IP地址:网络中主机的唯一标识。本质是一个非负正整数(主机编号)

         IP地址的表现形式:
1) 用二进制表示
2) 点分十进制表示的字符串     192.168.12.39

         IP地址的组成:
1) 网络ID:   用于标识主机处于哪一个网络
2) 主机ID:    用于网络中主机的标识号

         IP的分类:
根据网络ID与主机ID在正整数中占据的二进制位数量不同,

点分十进制第一字节取值范围
A:       1~127
B:       126 ~ 191
C:       192 ~ 223
D:       224 ~ 239                  用于UDP组播通讯
E:       240 ~ 254                  保留地址

         特殊IP:
环回/环路IP :   127.0.0.1             INADDR_LOOPBACK
任意IP :        0.0.0.0               INADDR_ANY
本地广播IP :    255.255.255.255       INADDR_BROADCAST

        2) 端口 (Port)

         作用: 用于标识发送到某台主机的网络数据,应该由该主机内的哪一个网络程序来处理。  
本质:16位无符号整型值

    3) 网络字节序:

作用:为了避免不同主机因主机字节序不同,导致对网络数据解析不同,造成数据不一致的问题。

网络字节序规定不同主机均采用大端方式存储网络数据。

    4) 套接字 (Socket):

套接字:  网络编程的接口。
类型:    1.流式套接字   (SOCK_STREAM)  基于 TCP
2.数据报套接字 (SOCK_DGRAM)   基于 UDP
3.原始套接字   (SOCK_RAW)     用于底层协议开发
...
2.2  基于UDP的网络编程
1)  基础网络编程(单播unicast)

服务器端:
1. 创建套接字
socket                     
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
函数原型:     int socket(int domain,int type,int protocol);
函数功能:    创建套接字
函数参数:    domain: 协议族,常用取值
AF_INET:   IPv4
AF_INET6   IPv6
type:  套接字类型,常用取值
SOCK_DGRAM
SOCK_STREAM
SOCK_RAW
protocol: 一般写0,让系统决定套接字使用的协议
函数返回值:  成功返回  套接字描述符
失败返回-1,错误码放在errno
2. 绑定自身地址信息到套接字上
bind
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/in.h>
函数原型:     int bind(int sockfd,struct sockaddr* addr,int addrlen);
函数功能:    绑定自身地址信息到套接字
函数参数:    sockfd: 套接字描述符
addr:   地址结构体,用于存储地址信息,实际使用中用sockaddr_in 代替。                          
addrlen: 地址结构体长度
函数返回值:  成功返回  0
失败返回-1,错误码放在errno

引申: 网络字节序转换:
涉及的函数族:
#include <arpa/inet.h>

uint16_t  htons(uint16_t port);
uint16_t  ntohs(uint16_t port);

                uint32_t inet_addr(const char* ip);
char* inet_ntoa(struct in_addr in);

3. 接收客户端数据
recvfrom                     
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
函数原型:     int recvfrom(int sockfd,void* buf,int len,int flags,
struct sockaddr* fromaddr,int* fromlen);
函数功能:    接收网络数据
函数参数:    sockfd: 套接字描述符
buf:   用于存储接收到的网络数据的内存缓冲区
len:    内存缓冲区长度
flags: 操作方式,一般写 0
fromaddr: [out]发送方的地址信息
fromlen: [out]发送方的地址信息长度
函数返回值:  成功返回  实际接收的字节数
失败返回-1,错误码放在errno
4. 发送数据给客户端
sendto                     
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
函数原型:     int sendto(int sockfd,const void* buf,int len,int flags,
struct sockaddr* toaddr,int tolen);
函数功能:    接收网络数据
函数参数:    sockfd: 套接字描述符
buf:   用于存储待发送的网络数据的内存缓冲区
len:    发送的数据实际长度
flags: 操作方式,一般写 0
toaddr: 目标主机的地址信息
tolen:   地址信息结构体长度
函数返回值:  成功返回  实际发送的字节数
失败返回-1,错误码放在errno
5. 关闭套接字


客户端:
1.创建socket;(socket)
2.设定对方的地址信息;
3.发送消息给服务端(sendto)
4.接收服务端的信息(recvfrom)
5.关闭套接字  close

    2) UDP广播通讯(broacast)   

注意: UDP广播通讯要借助特殊IP。

             广播地址:
1. 直接广播地址:主机ID二进制位全为1          xxx.xxx.xxx.255 (c类为例)
2. 本地广播地址:网络ID,主机ID二进制位全为1   255.255.255.255

         发送端:
1.  创建数据报套接字
2.  开启套接字广播属性;
setsockopt
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
函数原型:     int setsockopt(int sockfd,int level,int optname,const void* optval,
int optlen);
函数功能:    接收网络数据
函数参数:    sockfd: 套接字描述符
level: 套接字属性层,可取值如下:
SOL_SOCKET
IPPROTO_IP
IPPROTO_TCP
optname:  属性名
flags: 操作方式,一般写 0
optval: 指向属性值的指针
optlen:   属性值的长度
函数返回值:  成功返回  实际发送的字节数
失败返回-1,错误码放在errno

              例子:  int  enable = 1;
setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&enable,sizeof(int));
3.  设定广播地址和广播端口
4.  发送广播数据到广播地址和端口
5.  接收回复的数据
6.  关闭套接字
接收端:
1.  创建数据报套接字
2.  绑定任意地址和广播端口
3.  接收广播数据
4.  回复数据
5.  关闭套接字

      3) UDP组播通讯(multicast)  

注意: UDP组播通讯要借助特殊IP (D类)。

            组播地址:
224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;
224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。

             发送端:
1.  创建数据报套接字
2.  指定组播地址和组播端口
3.  向组播地址和组播端口发送数据,
4.  接收回复的数据
5.  关闭套接字

         接收端:
1.  创建数据报套接字
2.  绑定任意地址和组播端口
3.  加入组播组
setsockopt

               struct ip_mreqn   reqn = {0};
reqn.imr_multiaddr.s_addr = inet_addr("224.0.2.100");
reqn.imr_address.s_addr   = inet_addr("192.168.255.132");
reqn.imr_ifindex  = if_nametoindex("ens33");

                       setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&reqn,sizeof(reqn));
4.  接收组播数据
5.  回复数据
6.  退出组播组
setsockopt(sockfd,IPPROTO_IP,IP_DROP_MEMBERSHIP,&reqn,sizeof(reqn));
7.  关闭套接字

  2.3  基于TCP协议的网络编程

服务器端:
注意: TCP服务器往往要涉及两种作用的套接字
一个用于监听客户端连接,
一个用于和客户端数据交互,

       编程流程:
1.  创建流式套接字(用于监听客户端连接)
2.  绑定服务端地址信息到监听套接字上,
3.  监听客户端连接
listen
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
函数原型:     int listen(int sockfd,int backlog);
函数功能:    监听客户端连接
函数参数:    sockfd: 监听套接字描述符
backlog:   可排队连接的最大连接数
函数返回值:  成功返回  0
失败返回-1,错误码放在errno
4.  阻塞等待接受客户端连接
accept
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
函数原型:     int accept((int sockfd, struct sockaddr* addr, int* addlen));
函数功能:   接受客户端连接,并生成通讯套接字
函数参数:    sockfd: 监听套接字描述符
addr:   [out]获取客户端地址信息的结构体指针
addlen:   [out]获取客户端地址信息的结构体长度的指针
函数返回值:  成功返回  通讯套接字
失败返回-1,错误码放在errno
5.  发送网络数据
send                    
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
函数原型:     int send(int sockfd,const void* buf,int len,int flags);
函数功能:    接收网络数据
函数参数:    sockfd: 套接字描述符
buf:   用于存储待发送的网络数据的内存缓冲区
len:    发送的数据实际长度
flags: 操作方式,一般写 0                
函数返回值:  成功返回  实际发送的字节数
失败返回-1,错误码放在errno
6.  接收网络数据
recv
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
函数原型:     int recvf(int sockfd,void* buf,int len,int flags);
函数功能:    接收网络数据
函数参数:    sockfd: 套接字描述符
buf:   用于存储接收到的网络数据的内存缓冲区
len:    内存缓冲区长度
flags: 操作方式,一般写 0                
函数返回值:  成功返回  实际接收的字节数
返回0. 代表通讯对方断开网络连接。
失败返回-1,错误码放在errno
7.  关闭套接字


客户端
1.创建流式套接字;  (socket)
2.连接服务器(connect)
connect
函数头文件    #include <sys/socket.h> 
#include <sys/types.h> 
函数原型:     int connect((int sockfd, struct sockaddr* addr, int addlen));
函数功能:    连接服务器
函数参数:    sockfd: 套接字描述符
addr:   服务器地址信息的结构体指针
addlen:  地址信息的结构体长度
函数返回值:  成功返回  0
失败返回-1,错误码放在errno
3.发送消息到服务器(send)
4.接收服务端的信息(recv)
5.关闭套接字  (close)

http://www.xdnf.cn/news/19229.html

相关文章:

  • 英文版在线客服系统支持海外客户的实时聊天解决方案
  • 透视文件IO:从C库函数的‘表象’到系统调用的‘本质’
  • PS的基础操作与图片常用知识
  • 【LeetCode 热题 100】62. 不同路径——(解法二)递推
  • 国务院提出“人工智能+”行动,容智智能体引领产业变革发展
  • Linux下的软件编程——数据库
  • 【备战2025数模国赛】(三)数模常见赛题类型及解决办法
  • 《Unity Shader入门精要》学习笔记三(复杂的光照)
  • 神经网络基础
  • C++中类,this指针,构造函数,析构函数。拷贝构造函数,初步理解运算符重载,初步理解赋值运算符重载
  • 数据结构——线性表(链表,力扣中等篇,增删查改)
  • AWS集成开发最佳实践:构建高效可靠的云管理平台
  • React前端开发_Day4
  • 2025年06月 Python(四级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • SyncBack 备份同步软件: 使用 FTPS、SFTP 和 HTTPS 安全加密传输文件
  • IDEA之GO语言开发
  • 虚拟私有网络笔记
  • 成都五块石写字楼出租,国际数字影像产业园影像企业专属
  • Tinymce富文本编辑器封装
  • 云手机技术中都有着哪些局限性?
  • mysql中cross join于普通join的区别
  • 无懈可击的 TCP AIMD
  • 网络请求优化:用 Retrofit 拦截器玩转日志、重试与缓存,OkHttp 和 Volley 谁更香?
  • STM32 USBx Device MSC standalone 移植示例 LAT1488
  • Product Hunt 每日热榜 | 2025-08-29
  • typescript postgres@3.x jsonb数据插入绕过类型检测错误问题
  • SwiGLU激活函数的原理
  • TensorFlow 面试题及详细答案 120道(51-60)-- 模型保存、加载与部署
  • 微软正在公开测试其首个完全自主训练的大语言模型——MAI-1-preview
  • python 日常学习记录