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

Linux 下的网络编程

1、目的

实现不同主机上进程间的通信。

2、问题

  1. 主机与主机之间在物理层面必须互联互通。
  2. 进程与进程在软件层面必须互联互通。
  • IP地址:计算机的软件地址,用来标识计算机设备。
  • MAC地址:计算机的硬件地址(固定)。
  • 网络的端口号:标记同一主机上的不同网络进程。

3、网络协议

网络通信标准

OSI七层模型

开放系统互联模型,是不同设备间网络通信的通信标准,可概括为“物数网传会表应”。

  • 应用层:要传输的数据信息,如文件传输、电子邮件等。
  • 表示层:进行数据加密、解密操作,压缩、解压缩。
  • 会话层:建立数据传输通道(会话)。
  • 传输层:确定传输方式(UDP、TCP),涉及端口号。
  • 网络层:实现数据路由、路径规划(路由器、IP),涉及传输方式(UDP、TCP)和端口号。
  • 数据链路层:将各层数据封装成帧,实现点对点通信(局域网内通信),进行差错检测(交换机、ARP)。
  • 物理层:定义物理设备标准、电器特性,涉及网线、光纤等传输介质。

TCP/IP模型

应用模型,有五层和四层两种划分方式。

五层划分
  • 应用层
    • HTTP:超文本传输协议。
    • HTTPS:超文本传输协议(SSL加密算法)。
    • FTP:文件传输协议(TCP)。
    • TFTP:简单文本传输协议(UDP)。
    • MQTT:消息队列遥测传输(物联网协议)。
    • DNS:域名解析服务(将域名转换为IP地址)。
  • 传输层
    • TCP:传输控制协议。
    • UDP:用户数据报协议。
  • 网络层
    • IP协议:包括IPv4和IPv6。
  • 数据链路层
    • ARP协议:地址解析协议。
  • 物理层
四层划分
  • 应用层
  • 传输层
  • 网络层
  • 网络接口层

4、IP协议

基本概念

IP协议位于网络层。

  • IPv4为32位,如192.168.1.128。
  • IPv6为128位。

IP地址的用户表示形式为点分十进制,如192.168.1.140;

计算机存储形式为32位二进制,如11000000 10101000 00000000 01000011。

组成与相关概念

  • IP地址组成:IP地址 = 网络位 + 主机位。
    • 例如192.168.0.121/24,其中24表示网络位的位数。
      • 网络位:标识该IP地址位于哪个网段(局域网)内。
      • 主机位:标识在这个网段(局域网)内的第几台主机。
  • 子网掩码:用于区分IP地址的网络位和主机位,搭配IP地址使用。
    • 子网掩码是1的部分对应IP地址的网络位,是0的部分对应IP地址的主机位。
    • 如255.255.255.0,其二进制形式为11111111.11111111.11111111.00000000。
  • 网段号:IP地址网络位不变,主机位全为0,则为该IP地址的网段号。
    • 例如,IP地址192.168.1.3,子网掩码255.255.0.0,其网段号为192.168.0.0,位于192.168.1.0网段内(网段内的IP能直接通信)。
  • 广播号:IP地址网络位不变,主机位全为1,则为该IP地址的广播号。
    • 向广播号发送信息,所有局域网内IP都能收到此信息。例如,IP地址192.168.1.3,子网掩码255.255.255.0,其广播号为192.168.1.255(如feiQ、VNC使用)。
  • 网关地址:如192.168.1.1。

IP地址划分

类别范围子网掩码用途私有IP地址范围
A类地址1.0.0.0 - 126.255.255.255255.0.0.0管理大规模网络10.0.0.0 - 10.255.255.255
127.0.0.0回环地址
B类地址128.0.0.0 - 191.255.255.255255.255.0.0管理大中规模网络172.16.0.0 - 172.31.255.255
C类地址192.0.0.0 - 223.255.255.255255.255.255.0管理中小规模网络192.168.0.0 - 192.168.255.255
D类地址224.0.0.0 - 239.255.255.255组播和广播使用
E类地址240.0.0.0 - 255.255.255.254用来进行实验
  • 公有IP:由电信公司直接分配,需要付费,可以直接访问internet。
  • 私有IP:不能直接访问internet的IP地址,目的是节省IP地址。

5、网络端口号

基本信息

        端口号是16位的整形数据(unsigned short),范围为0~65535,功能是标记同一主机的不同网络进程。

分类

  1. 1-1023之间的端口号:任何TCP/IP实现所提供的服务使用。如http:80,FTP:20/21,TFPT:69,HTTPS:443。
  2. 1024-49151:被注册的端口号,被IANA指定为特殊服务使用。如MQTT:1883/8883。
  3. 49152-65535:动态或私有端口号。

6、网络配置

  1. ping命令:ping ip地址/域名,用于查看当前主机和IP/域名所对应的主机网络是否联通。如ping www.baidu.com。
  2. 查看IP地址
    • 在Linux中使用        ifconfig。
    • 在Windows上使用      ipconfig。
  3. 网络配置步骤
    1. 虚拟机--》设置--》网络适配器---》桥接模式。
    2. 编辑--》虚拟网络编辑器--》更改设置--》VMnet0---》桥接至--》当前PC正在上网的网卡上--》应用--》确定。
    3. 修改网络配置文件:sudo vim /etc/network/interfaces,文件内容如下:
    auto lo  
    iface lo inet loopback  
    auto ens33   
    iface ens33 inet dhcp  
    
  4. 重启网络服务:sudo /etc/init.d/networking restart
  5. 测试:ping www.baidu.com

7、网络协议--UDP

基本概念

UDP(User Datagram Protocol)即传输层用户数据报协议。

网络编程模型

  • B/S模型(browser/server,浏览器/服务器):
    1. 客户端是通用的客户端(浏览器)。
    2. 一般只做服务器开发。
    3. 客户端要加载的数据均来自服务器。
  • C/S模型(client/server,客户端/服务端):
    1. 客户端是一个专用的客户端。
    2. 服务器和客户端都需开发。
    3. 客户端可以保存资源,本地加载,无需所有数据都请求服务器。

UDP编程

套接字

套接字是文件描述符,是网络通信时应用层可操作的端口。

相关函数
  1. socket函数

    #include <sys/types.h>          /* See NOTES */  
    #include <sys/socket.h>  
    int socket(int domain, int type, int protocol);  
    
    • 功能:创建通信的套接字。
    • 参数:
      • domain:网络层使用的协议族,AF_INET表示IPv4,AF_INET6表示IPv6。
      • type:规定传输层的协议,SOCK_DGRAM表示UDP协议,SOCK_STREAM表示TCP协议,SOCK_RAW表示原始套接字。
      • protocol:0按照默认协议方式创建。
    • 返回值:成功返回套接字,失败返回-1。
  2. sendto函数

    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,  const struct sockaddr *dest_addr, socklen_t addrlen);  
    
    • 功能:向网络套接字发送数据。
    • 参数:
      • sockfd:套接字。
      • buf:要发送的数据的首地址。
      • len:要发送的字节数。
      • flags:0表示按照默认方式发送。
      • dest_addr:接收方的地址信息(IP+端口号)。
      • addrlen:接收方地址的大小。
    • 返回值:成功返回实际发送的字节数,失败返回-1。
  3. sockaddr_in结构体(man 7 ip)

    struct sockaddr_in 
    {  sa_family_t    sin_family; /* address family: AF_INET */  in_port_t      sin_port;   /* port in network byte order */  struct in_addr sin_addr;   /* internet address */  
    };  /* Internet address. */  
    struct in_addr 
    {  uint32_t       s_addr;     /* address in network byte order */  
    };  
    
  4. 字节序转换函数    

字节序转换

网络字节序(大端顺序)和主机字节序(小端顺序)在数据存储方式上存在差异。

网络字节序中,高位字节存储在低地址;主机字节序中,低位字节存储在低地址。

例如,数值$0x1234$:

  • 小端存储:低地址为$0x34$,高地址为$0x12$
  • 大端存储:低地址为$0x12$,高地址为$0x34$

标准库函数提供了字节序转换功能,具体声明如下:

uint32_t htonl(uint32_t hostlong);          // 主机转网络(32位)
uint16_t htons(uint16_t hostshort);         // 主机转网络(16位)
uint32_t ntohl(uint32_t netlong);           // 网络转主机(32位)
uint16_t ntohs(uint16_t netshort);          // 网络转主机(16位)
in_addr_t inet_addr(const char *cp);
功能:将字符串IP地址转换成二进制IP地址形式char *inet_ntoa(struct in_addr in);
功能:将二进制ip转换成字符串
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:绑定自己的IP地址和端口号
参数:sockfd:套接字addr:需要绑定的地址addrlen:地址大小
返回值:成功:0失败:-1
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
功能:从套接字上接收数据
参数:sockfd:套接字buf:存放接收数据的内存首地址len:希望接收的字节数flags:0 :按照默认方式接收(阻塞)src_addr:发送方的地址信息addrlen:发送发地址的指针
功能:成功:实际接收到的字节数失败:-1

8、代码训练

#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> 
#include <arpa/inet.h>
#include<string.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd < 0){perror("socket error");return -1;}// struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("192.168.0.179");// 创建子进程char buff[1024] = {0};while(1){fgets(buff, sizeof(buff), stdin);ssize_t cnt = sendto(sockfd, buff, strlen(buff), 0, (struct sockaddr *)&seraddr, sizeof(seraddr));if(cnt < 0){perror("sendto error");return -1;}printf("cnt = %ld\n", cnt);memset(buff, 0, sizeof(buff));}close(sockfd);return 0;
}
#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd < 0){perror("socket error");return -1;}// 服务端自己的地址信息变量struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("192.168.0.177");int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if(ret < 0){perror("bind error");ret -1;}char buff[1024] = {0};while(1){ssize_t cnt = recvfrom(sockfd, buff, sizeof(buff), 0, NULL, NULL);if(cnt < 0){perror("recvfrom error");return -1;}printf("cnt = %ld, buff = %s\n", cnt, buff);memset(buff, 0, sizeof(buff));}close(sockfd);return 0;
}

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

相关文章:

  • 学习嵌入式的第二十四天——数据结构——队列和树
  • Git 提交除某个文件外的其他所有文件
  • 微信开发者工具:更改 AppID 失败
  • 嵌入式-EXTI的工作原理和按钮实验-Day19
  • 我从零开始学习C语言(13)- 循环语句 PART2
  • QT-窗口类部件
  • K8S高可用集群
  • K8s的相关知识总结
  • 如何理解面向过程和面向对象,举例说明一下?
  • Qt5 的跨平台开发详细讲解
  • 计算机毕设选题推荐 基于Spark的家庭能源消耗智能分析与可视化系统 基于机器学习的家庭能源消耗预测与可视化系统源码
  • 告别第三方流氓工具,如何实现纯净系统维护
  • DIC技术极端环境高温案例分享——从1600℃的锆合金力学性能测试到3000℃变形测试的DIC测量
  • 手机、电脑屏幕的显示坏点检测和成像原理
  • k8s----学习站点搭建
  • C++显示类型转换运算符static_cast使用指南
  • 贪吃蛇--C++实战项目(零基础)
  • 大模型微调:从理论到实践的全面指南
  • 【链表 - LeetCode】19. 删除链表的倒数第 N 个结点
  • Laravel 使用阿里云OSS S3 协议文件上传
  • Java多线程面试题二
  • Flask电影投票系统全解析
  • WPF控件随窗体大宽度高度改变而改变
  • 金融风控AI引擎:实时反欺诈系统的架构设计与实现
  • Rust 入门 注释和文档之 cargo doc (二十三)
  • AP服务发现PRS_SOMEIPSD_00255 的解析
  • 《WINDOWS 环境下32位汇编语言程序设计》第7章 图形操作(1)
  • UNIKGQA论文笔记
  • XP系统安装Android Studio 3.5.3并建立Java或Native C++工程,然后在安卓手机上运行
  • 算法题(188):团伙