Linux系统编程(七)网络编程TCP、UDP

本文目录

  • 一、基础知识点
    • 1. IP地址
    • 2. 端口
    • 3. 域名
    • 4. 网络协议类型
    • 5. IP协议类型
    • 6. 字节序
    • 7. socket套接字
  • 二、常用API
    • 1. socket套接字描述符
    • 2. bind套接字绑定
    • 3. listen设置客户端连接个数
    • 4. accept接收客户端请求
    • 5. connect连接服务端
  • 三、编程流程
    • 1.TCP编程

  
在学习本章之前,可以查看 《计算机网络基础》这篇文章进行学习。

一、基础知识点

1. IP地址

   IP 地址的作用是标识计算机的网卡地址,每一台计算机都有一个 IP 地址。在程序中是通过IP 地址来访问一台计算机的。 本节将讲述 IP 地址的一些知识。 IP 地址是用来标识全球计算机地址的一种符号,就比如一个手机的号码,使用这个地址可以访问一个计算机。
   IP 地址具有统一的格式。 IP 地址是 32 位长度的二进制数值, 存储空间是 4 个字节。例如: 11000000 10101000 00000001 00000110 是一台计算机的 IP 地址,但二进制的数值是不便于记忆的,可以把每个字节用一个十进制的整数来表示,既 192.168.1.6
   在同一个网络中, IP 地址是唯一的。因为需要根据 IP 地址来访问一台计算机,所以在可以访问的范围以内,每一台计算机的 IP 地址是唯一的。在终端中输入命令 ifconfig 可以查看本机 IP 信息。

2. 端口

   在网络通信中,IP地址帮助我们定位到特定的计算机,而端口号则帮助我们在这台计算机上找到具体的应用程序或服务。每个应用程序监听不同的端口,以便接收和处理来自网络的请求。端口号通常以数字形式表示,并与IP地址一起使用,以标识网络通信的不同端点。
   通俗举例:在同一个主机上,IP地址是固定的,但是主机上有很多程序功能,这些功能有不同的端口号。我们为了访问主机的某个功能程序,就必须指定其功能对应的端口号。例如主机的IP为:192.168.12.4,QQ的端口号为10,微信的端口号为13。我们为了使用微信这个功能,我们就需要使用:192.168.12.4: 13来使用其功能。

3. 域名

   域名是互联网中用于标识一个网站或服务器的友好名称,它是IP地址的可读形式。域名系统(DNS)将域名转换为IP地址,使用户能够通过简单易记的名字访问网站,而不需要记住难记的IP地址。例如百度的域名为www.baidu.com,我们可以使用这个域名来代替百度的IP地址。小知识:可以使用 ping 命令来查看一个域名所对应的 IP 地址,例:ping www.baidu.com,我们就可以查看其真实的ip地址。

4. 网络协议类型

(1)TCP协议:提供可靠的、面向连接的数据传输,确保数据按顺序传递、不丢失、不重复,并进行错误检测和纠正。常用于需要可靠数据传输的应用,如Web、电子邮件和文件传输。
   TCP 是面向连接的协议。所谓连接,就是两个对等实体为进行数据通信而进行的一种结合。面向连接服务是在数据交换之前,必须先建立连接。当数据交换结束后,则应终止这个连接。面向连接服务具有:连接建立、数据传输和连接释放这三个阶段。在传送数据时是按序传送的。建立链接:三次握手(这个过程我们并不看得到)。
在这里插入图片描述

(2)UDP协议:提供不可靠的、面向无连接的数据传输,数据包可能会丢失、重复或乱序,不进行错误检测和纠正。传输速度比TCP快!常用于实时性要求高、数据量小、丢失少不影响的应用,如视频流、音频流和游戏通信。

5. IP协议类型

  IPv4和IPv6是两种不同版本的互联网协议(IP),用于标识网络设备的地址并进行数据包路由。它们的主要区别在于地址格式和容量。

(1)IPV4:是第四版互联网协议,目前仍是最广泛使用的IP协议。

●它使用32位地址空间,格式如下:
  地址格式:四个十进制数,每个数范围从0到255,由点分隔。例如:192.168.1.1。
  地址数量:IPv4的地址空间约有42亿个唯一地址(2^32)。
●IPv4的特点
  地址空间有限:由于地址空间较小,IPv4地址逐渐耗尽,尤其随着互联网设备数量的爆炸性增长。
  地址分配:IPv4地址的分配方式包括公共地址和私有地址,私有地址用于局域网内通信,不可在互联网中直接使用(如192.168.x.x)。
  NAT(网络地址转换):由于地址空间有限,NAT技术被广泛应用,使多个设备可以共享一个公共IP地址访问互联网。

(2)IPV6:是第六版互联网协议,设计为IPv4的继任者,提供更大的地址空间和其他改进。

● 它使用128位地址空间,格式如下:
   地址格式:八组十六进制数,每组四个十六进制数字,由冒号分隔。例如:2001:0db8:85a3:0000:0000:8a2e:0370:7334
  地址数量:IPv6的地址空间极其庞大,有约3.4×1038个地址(2128)。
●IPv6的特点
  几乎无限的地址空间:IPv6提供了极其庞大的地址空间,足以满足未来互联网设备的需求。
  简化的地址配置:支持无状态地址自动配置(SLAAC),设备可以自动生成IPv6地址,不需要手动配置或DHCP。
  内置安全性:IPv6支持IPSec协议,提供更好的安全性。
  无NAT需求:由于地址空间充足,不再需要NAT,大大简化了网络结构和提高了传输效率。
  改进的路由和网络配置:IPv6改进了路由选择和地址分配机制,简化了网络配置和管理。

6. 字节序

顾名思义就是字节的存放顺序,就是字节数大于1的数据在内存中的存放顺序,字节数为1的数据就没有顺序的问题。
(1)主机字节序
  数据在主机(计算机)内部的字节顺序。在计算机系统中,数据存储在内存中,字节的存储顺序取决于计算机的体系结构。
  ●有两种主要的字节序:大端序小端序。在大端序中,高位字节存储在低地址,低位字节存储在高地址。在小端序中,低位字节存储在低地址,高位字节存储在高地址。

(2)网络字节序
  是一种特定的字节序,用于在网络中传输数据。在网络通信中,数据在传输过程中需要保持一致的字节序,以确保不同主机之间能够正确解释和处理数据。网络字节序规定使用大端序作为标准字节序。

  为了确保在网络通信中使用统一的字节序,常见的网络编程库提供了一系列函数来进行字节序转换,以确保数据在传输过程中采用网络字节序。

htons() //将16位整数从主机字节序转换为网络字节序(Host to Network Short)。
htonl() //将32位整数从主机字节序转换为网络字节序(Host to Network Long)。
ntohs() //将16位整数从网络字节序转换为主机字节序(Network to Host Short)。
ntohl() //将32位整数从网络字节序转换为主机字节序(Network to Host Long)。inet_ntoa() // 是一个用于将网络字节序的二进制 IPv4 地址转换为点分十进制字符串表示形式的函数。
inet_addr() //函数用于将点分十进制字符串形式的 IPv4 地址转换为网络字节序的二进制形式。

7. socket套接字

(1)定义
   Socket(套接字)是在网络编程中用于实现不同主机间通信的一种机制,它允许应用程序通过网络发送和接收数据。
   Socket的工作原理基于客户端-服务器模型,其中一个程序充当客户端,另一个充当服务器。通常,服务器在一个主机上运行并侦听特定的端口,客户端则连接到服务器的IP地址和端口号。

(2)类型
   ①流式 socket(SOCK_STREAM):提供可靠的、面向连接的通信流;它使用 TCP 协议,从而保证了数据传输的正确性和顺序性。
   ②数据报 socket(SOCK_DGRAM):定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议 UDP
   ③原始 socket:原始套接字允许对底层协议如 IP 或 ICMP 进行直接访问,它功能强大但使用较为不便,不常用。

二、常用API

●头文件

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>

1. socket套接字描述符

返回值:套接字描述符

int socket(int domain, int type, int protocol)
//int domain ::代表一个协议族。AF_INET 决定了要用 ipv4 地址;
//int type:指定IP协议类型,常见的是TCP: SOCK_STREAM。 UDP:SOCK_DGRAM等。
//int protocol:当为 0 时,会自动选择 type 类型对应的默认协议。

2. bind套接字绑定

   将套接字绑定到指定的本地地址上,这样就可以在该地址上进行数据收发操作。通常,在服务器程序中,使用bind()函数将服务器套接字绑定到服务器的IP地址和端口号上,以便客户端可以连接到该地址并与服务器通信。

int bind(int sockfd, struct sockaddr* my_addr, int addrlen);
//int sockfd:socket套接字描述符
//struct sockaddr* my_addr :本地ip地址结构体,包含ip地址、端口等。
// int addrlen: struct sockaddr 结构的大小。

使用举例:

//下述结构体已经在#include <sys/socket.h>头文件中定义,不需要程序员自己定义。
/*struct sockaddr_in {sa_family_t sin_family;     // address family: IP协议类型:AF_INET(IPV4)、AF_INET6(IPV6)。in_port_t sin_port;         // port in network byte order 端口号 struct in_addr sin_addr;    //internet address IP 地址 };struct in_addr {in_addr_t s_addr;  //ip地址
*/
//填写绑定的结构体内容	
sockaddr_in server_info;    //初始化结构体
server_info.sin_family =AF_INET;    //IPV4类型
server_info.sin_port=htons(50000);  //htons()将一个主机字节序端口号转为网络字节序下的端口号。
server_info.sin_addr.s_addr=htonl(INADDR_ANY); //所有人都可以连接。bind(sockfd, (struct sockaddr*)&server_info, sizeof(server_info));  //绑定ip以及端口号

3. listen设置客户端连接个数

   设置客户端连接个数(最大排队长度):即多个客户端连接服务端时,当服务端没有接收这个请求,则客户端会进入排队等待中,那么这个排队长度就是最大可以容忍排队客户端的数量。

int listen(int sockfd, int backlog);
//int sockfd:socket套接字描述符。
// int backlog:设置请求排队的最大长度,当有多个客户端程序和服务端相连时, 使用这个表示可以介绍的排队长度。

4. accept接收客户端请求

监听是否有客户端链接,调用 accpet 之后会一直阻塞,直到有用户连接。
返回值:客户端的文件描述符。

int accept(int sockfd, void *addr, int *addrlen);
//int sockfd:socket套接字描述符。
//void *addr :用于存放客户端的信息
//int *addrlen :接收客户端的信息长度。

举例:

sockaddr_in client_info;    //用于存储连接的客户端的信息
int client_socket;client_socket=accept(sockfd, (struct sockaddr*)&client_info, &(sizeof(client_info)));
printf("客户端的socket:%d, ip:%s, 端口:%d\n",client_socket, client_info.sin_addr, client_info.sin_port);

5. connect连接服务端

用于在客户端与服务器进行端连接。0 :成功。1 :失败。

int connect(int sockfd, struct sockaddr * serv_addr,int addrlen);
//int sockfd:socket()返回的文件描述符。
//struct sockaddr * serv_addr:服务端的地址,通常传递 struct sockaddr_in 结构体类型。
//int addrlen) :serv_addr长度。

三、编程流程

1.TCP编程

在这里插入图片描述

使用例程:

●TCP服务端:
   服务端是固定的,客户端是改变的。只能客户端去连接服务端,不能服务端连接客户端。正常先断开客服端,再断开服务端。

#include <sys/types.h>        
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>//-----------------------------------------------服务端---------------------------
int main(int argc, char **argv)
{	  int ret;int client_sock;  int  server_sock;char receive_data[100]={0};struct sockaddr_in client_info;struct sockaddr_in server_info;socklen_t length;//1.创建socket,ip协议类型,网络协议类型,具体协议//SOCK_STREAM(流式): 使用TCP协议,保证数据传输的正确性和顺序性;//SOCK_DGRAM(数据报):使用UDP协议,不保证数据传输的正确性和顺序性。(速度快)	 server_sock=socket(AF_INET, SOCK_STREAM, 0);if(server_sock < 0){perror("socket error");return -1;}//2.设置服务端 server_info.sin_family = AF_INET;                 //ip协议类型为 ipv4server_info.sin_port   = htons(8888);            //端口号为8888。将小端转为大端。server_info.sin_addr.s_addr=htonl(INADDR_ANY);   //接收所有人的连接,程序在哪作为服务端运行,就填该地的ip地址。//3.绑定端口:绑定到指定的socket,绑定的信息,信息的长度ret= bind(server_sock, (const struct sockaddr *)&server_info,sizeof(server_info));if(ret < 0){perror("bind error");return -1;}//4.开启监听:监听的socket,最大排队数(当1个客户端申请连接,但服务端还没有同意连接请求时,客户端会等待。最多有10个可以等待排队的客户端)ret=listen(server_sock, 10);if(ret < 0){perror("listen error");return -1;}//5. 接收客户端连接。length=sizeof(client_info);client_sock= accept(server_sock, (struct sockaddr *)&client_info,  &length); //将连接的客户端的信息存到client_info中。	printf("客户端的socket:%d, ip:%s, 端口:%d\n",client_sock, inet_ntoa(client_info.sin_addr), client_info.sin_port);//6. 服务端向指定的客户端发送数据write(client_sock, "hello world",strlen("hello world"));//7. 接收指定的客户端发送的数据。读不到会阻塞。read(client_sock, receive_data,100);printf("Client:%d,Send_data:%s\n",client_sock, receive_data);//7. 关闭描述符close(client_sock);                //先关闭客户端描述符close(server_sock);                //再关闭服务端描述符
}

在调试时:服务端在哪运行就填哪的IP地址。
在这里插入图片描述

●TCP客户端:

#include <sys/types.h>        
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>int main(int argc, char **argv)
{int client_sock;int ret;struct sockaddr_in server_info;char receive_data[100]={0};// 1.创建socket,ip协议类型,网络协议类型,具体协议//SOCK_STREAM(流式): 使用TCP协议,保证数据传输的正确性和顺序性;//SOCK_DGRAM(数据报):使用UDP协议,不保证数据传输的正确性和顺序性。(速度快)client_sock=socket(AF_INET, SOCK_STREAM, 0);if(client_sock< 0){perror("socket error");return -1;}	  // 2.设置服务端的信息	  server_info.sin_family = AF_INET;                           //ip协议类型为 ipv4server_info.sin_port   = htons(8888);                      //服务端端口号为40000。将小端转为大端server_info.sin_addr.s_addr= inet_addr("192.168.195.15");     //写入服务端的ip地址// 3.连接服务端	  ret=connect(client_sock,(const struct sockaddr *)&server_info, sizeof(server_info));if(ret < 0){perror("connect error");return -1;}printf("connect ok!\n");//4. 向服务器发送数据write(client_sock, "i am client_one", strlen("i am client_one"));//5. 接收服务器发送的数据,读不到会阻塞。read(client_sock, receive_data, 100);  printf("receive_data:%s\n",receive_data);//6. 创建接收服务端数据的线程,实现客户端与服务端互相收发close(client_sock);                //关闭服务端通信句柄return 0;
}

我们使用两个命令窗口,先执行服务端的代码,再执行客户端的代码。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/20474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《mysql轻松学习·二》

1、创建数据表 contacts&#xff1a;数据表名 auto_increament&#xff1a;自动增长 primary key&#xff1a;主键 engineInnoDB default charsetutf8; 默认字符集utf8&#xff0c;不写就默认utf8 对数据表的操作&#xff1a; alter table 数据表名 add sex varchar(1); //添…

使用YOLOv10训练自己的数据集

1. yolov10源码下载 THU-MIG/yolov10: YOLOv10: Real-Time End-to-End Object Detection (github.com)https://github.com/THU-MIG/yolov10?tabreadme-ov-file 2. 环境配置 预先安装好ANACONDA、PyCharm或者VSCode等基本软件。参考以下博客&#xff1a; 史上最全最详细的An…

unity2D跑酷游戏

项目成果 项目网盘 导入资源包 放入Assets文件Assets资源文件 游戏流程分析 摄像机size调小&#xff0c;让图片占满屏幕 人跑本质&#xff0c;相对运动&#xff0c;图片无限向右滚动 图片720&#xff0c;缩小100倍第二个图片x为7.2每unit px100两张图片刚好挨着连贯 空对象Bg…

Yolov10笔记

一、前言 清华大学团队设计的Yolov10. 在这项工作中&#xff0c;我们主要从后处理和模型结构两方面进一步优化YOLO系列模型的性能和延迟平衡。我们首先为YOLO引入了端到端训练的一致双重分配&#xff0c;这在大大降低推理延迟的情况下保证了性能。此外&#xff0c;我们针对YOLO…

【计算机毕设】设计与实现基于SpringBoot的在线文档管理系统 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 在当今信息爆炸的时代&#xff0c;文档管理对于任何组织都至关重要。基于SpringBoot的在线文档管理系统的设计旨在为用户提供一个便捷、高效、安全的…

轻松拿捏C语言——【内存函数】

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f389;创作不易&#xff0c;请多多支持&#x1f389; &#x1f308;感谢大家的阅读、点赞、收藏和关注&#x1f495; &#x1f339;如有问题&#xff0c;欢迎指正~~ 目录&#x1…

JVM学习-类加载过程(一)

概述 在Java中数据类型分为基本数据类型和引用数据类型&#xff0c;基本数据类型由虚拟机预先定义&#xff0c;引用数据类型则需要进行类的加载按Java虚拟机规范&#xff0c;从class文件加载到内存中的类&#xff0c;到类卸载出内存为止&#xff0c;它的整个生命周期包含以下7…

测试工具fio

一、安装部署 fio是一款优秀的磁盘IO测试工具&#xff0c;在Linux中比较常用于测试磁盘IO 其下载地址&#xff1a;https://brick.kernel.dk/snaps/fio-2.1.10.tar.gz 或者登录其官网&#xff1a;http://freshmeat.sourceforge.net/projects/fio/ 进行下载。 tar -zxvf fio-…

【redis】宝塔,线上环境报Redis error: ERR unknown command del 错误

两种方式&#xff1a; 1.打开宝塔上的redis&#xff0c;通过配置文件修改权限&#xff0c;注释&#xff1a;#rename-command DEL “” 2.打开服务器&#xff0c;宝塔中默认redis安装位置是&#xff1a;cd /www/server/redis 找到redis.conf,拉到最后&#xff0c;注释#rename-co…

Flutter 验证码输入框

前言&#xff1a; 验证码输入框很常见&#xff1a;处理不好 bug也会比较多 想实现方法很多&#xff0c;这里列举一种完美方式&#xff0c;完美兼容 软键盘粘贴方式 效果如下&#xff1a; 之前使用 uniapp 的方式实现过一次 两种方式&#xff08;原理相同&#xff09;&#xff1…

二叉树链式结构的前序、中序、后序、层序遍历

文章目录 一、二叉树创建二、前序遍历概念以及解释代码 三、中序遍历概念及解释代码 四、后序遍历概念及解释代码 五、层序遍历概念及解释代码 一、二叉树创建 &mesp; 实现二叉树的遍历&#xff0c;我们要先手搓出一个二叉树&#xff0c;在次基础上实现二叉树的前序、中序…

【RLHF个人笔记】RLHF:Reinforcement Learning from Human Feedback具体过程

【RLHF个人笔记】RLHF:Reinforcement Learning from Human Feedback具体过程 RLHF训练的三个步骤步骤1&#xff1a;收集数据与有监督训练策略步骤2&#xff1a;收集数据训练奖励模型步骤3&#xff1a;结合奖励模型利用强化学习算法如PPO算法来优化策略 参考内容 RLHF训练的三个…

今年一定要做的副业兼职,1篇文章收入600,批量操作收入翻倍

随着公众号开放公域流量&#xff0c;流量主收入迅速攀升&#xff0c;吸引了众多投资者纷纷涌入这一领域&#xff0c;通过流量主赚取了丰厚的利润。上周&#xff0c;我曾向大家介绍了一些借助公众号流量主实现盈利的策略。 然而&#xff0c;公众号的盈利途径远不止流量主一种。…

数据库(14)——DQL排序查询

DQL排序查询语法 SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1,字段2 排序方式2; 排序方式 ASC&#xff1a;升序 DESC&#xff1a;降序 注&#xff1a;如果是多字段排序&#xff0c;当第一个字段值相同时&#xff0c;才会根据第二个字段进行排序。如果不写排序方式默…

图像处理ASIC设计方法 笔记27 红外非均匀校正的两点定标校正算法

非均匀性校正(Non-Uniformity Correction, NUC)是一种在图像处理和传感器校准中常用的技术,用于改善图像传感器(如CCD或CMOS相机)的输出质量。这种校正主要针对传感器在不同像素之间可能存在的响应差异,这些差异可能是由于制造过程中的微小不完美导致的。 基本原理: 响应…

MAB规范(2):Introduction 介绍

Chapter1 Introduction 1.1 指南目的 MathWorks咨询委员会&#xff08;MAB&#xff09;指南规定了Simulink和Stateflow建模的重要基本规则。这些建模指南的总体目的是让建模者和控制系统模型的使用者能够简单、共同地理解。 指南的主要目标是&#xff1a; • 可读性  提高…

CentOS8安装opensips 3.5

环境&#xff1a;阿里云 操作系统CentOS8.5 依赖包安装&#xff1a; libmicrohttpd cd /usr/local/src wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-latest.tar.gz tar vzxf libmicrohttpd-latest.tar.gz cd libmicrohttpd-1.0.1/./configure make make …

联芸科技偏高的关联交易:业绩波动性明显,海康威视曾拥有一票否决

《港湾商业观察》施子夫 5月31日&#xff0c;上交所上市审核委员会将召开2024年第14次审议会议&#xff0c;届时将审议联芸科技&#xff08;杭州&#xff09;股份有限公司招股书&#xff08;以下简称&#xff0c;联芸科技&#xff09;的首发上会事项。 据悉&#xff0c;此次系…

Github 2024-05-31 Java开源项目日报 Top10

根据Github Trendings的统计,今日(2024-05-31统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目10TypeScript项目1JavaGuide - Java 程序员学习和面试指南 创建周期:2118 天开发语言:Java协议类型:Apache License 2.0Star数量:1…

Rust 第三方库创建和导入(cargo --lib)

前言 日常开发过程中&#xff0c;难免会有一些工具方法&#xff0c;多个项目之间可能会重复使用。 所以将这些方法集成到一个第三方包中方便后期维护和管理&#xff0c; 比如工具函数如果需要修改&#xff0c;多个项目可能每个都需要改代码&#xff0c; 抽离到单独的包中只需要…