Linux C 网络编程概述

网络编程

  • 计算机网络
    • 概述
    • 分类
    • 网络体系结构
    • 通信协议
    • 通信流程
      • 网络通信帧格式
        • 以太网帧格式分析
        • ARP 协议分析
        • IP 数据报分析
          • IP分类
          • IP 分配
          • 子网掩码
        • TCP 段分析
      • TCP三次握手协议 ⭐
      • TCP四次挥手协议 ⭐
  • TCP编程
    • 基于 TCP 客户端编程-步骤说明
    • 基于 TCP 服务器端编程-步骤说明
    • 基于 TCP 服务端/客户端编程例子⭐
    • 基于 TCP 服务端/客户端编程详细案例⭐
    • 函数
      • 创建套接字  socket
      • 绑定函数  bind
        • 大小端排序转换函数
        • 地址格式转换函数
      • 监听  listen
      • 等待客户端连接  accept
      • 连接服务器   connect
      • 发送函数  send
      • 接收函数  recv
  • NAT映射
    • 概述
    • NAT 的优缺点
  • 内网穿透(打洞)技术
  • UDP编程
    • 概念
    • 通信流程
    • 基于 UDP 客户端编程思路
    • 基于 UDP 服务器端编程思路
    • 基于UDP 客户端/服务端编程例子⭐
    • 函数
      • 发送函数  sendto
      • 接收函数  recvfrom
    • UDP广播
      • 概念
      • 广播特点
      • 广播地址
  • 网络编程服务器模型
    • 回射服务器
    • 迭代服务器
    • 并发服务器

计算机网络

概述

  计算机网络是指将不同地理位置,具有独立功能的多台计算机及网络设备通过通信线路(包括传输介质和网络设备连接起来),在网络操作系统、网络管理软件及网络通信协议的共同管理和协调下实现资源共享和信息传递的计算机系统。

分类

1 ) 地理范围:广域网 WAN、城域网 MAN、局域网 LAN、个人区域网 PAN。
2 ) 按拓扑结构:星型拓扑结构、总线型拓扑结构、环形拓扑结构、网状拓扑结构、混合拓扑结构。
3 ) 按网络使用者分类:公用网、专用网。
  局域网(LoxalAreaNetwork,LAN)是指范围在几百米到十几公里内办公楼群或校园内的计算机相互连接所构成的计算机网络。计算机局域网被广泛应用于连接校园、工厂以及机关的个人计算机或工作站,以利于个人计算机或工作站之间共享资源和数据通信。
  城域网(MetropolitanAreaNetwork,MAN)所采用的技术基本上与局域网相类似,只是规模上要大一些。城域网既可以覆盖相距不远的几栋办公楼,也可以覆盖一个城市;既可以是私人网,也可以是公用网。城域网既可以支持数据和话音传输,也可以与有线电视相连。城域网一般只包含一到两根电缆,没有交换设备,因而其设计就比较简单。
  广域网(WidoAreaNetwork,WAN)通常跨接很大的物理范围,如一个国家。广域网包含很多用来运行用户应用程序的机器集合,我们通常把这些机器叫做主机;把这些主机连接在一起的是通信子网(communicationsubnet)。通信子网的任务是在主机之间传送报文。将计算机网络中的纯通信部分的子网与应用部分的主机分离开来,可以大大简化网络的设计。

网络体系结构

在这里插入图片描述
  ISO 制定的 OSI 参考模型的过于庞大、复杂招致了许多批评。因此简化ISO的TCP/IP应运而生。
在这里插入图片描述

通信协议

TCP/IP:英文(Transmission Control Protocol/Internet Protocol)的缩写,传输控制协议/网际协议。
Telnet:是 TCP/IP 协议族中的一员,是 Internet 远程登陆服务的标准协议。
FTP:(文件传输协议)用于在网络上进行文件传输的一套标准协议,使用客户/服务器模式。
TCP:(传输控制协议) 为应用程序提供可靠的通信连接。适合于一次传输大批数据的情况。并适用于要求高的应用程序。
UDP:(用户数据包协议)提供了无连接通信,且不对传送包进行可靠的保证。适合于一次传输少量数据。
ICMP:(网络控制消息协议)用于发送报告有关数据包的传送错误的协议。
IGMP:(网络组管理协议)被 IP 主机用来向本地多路广播路由器报告主机组成员的协议。
IP:(网际互联协议)负责在主机和网络之间寻址和路由数据包。
ARP:(地址转换协议)用于获得同一物理网络中的硬件主机地址。
MPLS:(多协议标签交换)很有发展前景的下一代网络协议。

通信流程

网络通信帧格式

  数据包在以太网物理介质上传播之前必须封装头部和尾部信息。封装后的数据包称为称为数据帧,数据帧中封装的信息决定了数据如何传输。以太网上传输的数据帧有两种格式,选择哪种格式由 TCP/IP 协议簇中的网络层决定。
  网络通信中有两种数据帧格式:第一种是上世纪 80 年代初提出的 DIX v2 格式,即 Ethernet II 帧格式。Ethernet II 后来被 IEEE 802 标准接纳,并写进了 IEEE 802.3x-1997 的 3.2.6 节。以太网中大多数的数据帧使用的是 Ethernet II格式。本课程主要研究 Ethernet(以太网帧格式)在网络中传输过程。
网络通信帧格式

以太网帧格式分析

在这里插入图片描述

ARP 协议分析

在这里插入图片描述

IP 数据报分析

在这里插入图片描述

IP分类

  按照 IP 版本分类:IPv4、IPv6。IPv4 的地址位数为 32 位,也就是最多有 2 的 32 次方(42 亿)的电脑可以连接: 近十年来由于互联网的蓬勃发展,IP 地址的需求量愈来愈大,导致 IPv4 定义的有限地址空间将被耗尽,地址空间的不足必将妨碍互联网的进一步发展。为了扩大地址空间,拟通过 IPv6 重新定义地址空间。IPv6 采用 128 位地址空间长度,几乎可以不受限制地提供地址。
  按照状态分类:静态 IP 与动态 IP。动态 IP 需要在连接网络时自动获取 IP 地址以供用户正常上网,而静态 IP 是 ISP 在装机时分配给用户的 IP 地址,可以直接连接上网,不需要获取 IP 地址。
  按照 IP 身份分类:公有 IP 与私有 IP。公有 IP:指以公网连接 Internet 上的非保留地址。私有 IP:是在本地局域网上的 IP。
  每个 IP 地址都被分为两个部分即网络地址和主机地址。这样做的目的是为了在路由器转发数据包时更方便的寻址。网络位是用来确定网络的,就相当于你生活在哪个区域。主机位就是每一台电脑所用的 IP 地址,就相当于你所在区域有多少人,每个人的固定住所。

IP 分配

全为 0 表示任意 全为 1 表示广播
A 类地址范围:1.0.0.1—126.155.255.254
A 类:0xxxxxxx.hhhhhhhh.hhhhhhhh.hhhhhhhh  2^24-2=16777214;
B 类地址范围:128.0.0.1—191.255.255.254
B 类:10xxxxxx. xxxxxxxx.hhhhhhhh.hhhhhhhh   2^16-2=65534;
C 类地址范围:192.0.0.1—223.255.255.254
C 类:110xxxxx.xxxxxxxx.xxxxxxxx.hhhhhhhh   2^8-2=254;
D 类地址范围:224.0.0.1—239.255.255.254
E 类地址范围:240.0.0.1—255.255.255.254

  在Linux系统中可以使用 ifconfig 指令先查看当前网络 IP 地址信息。
  也可以使用 ifconfig ens33 指令修改 IP,例如:ifconfig ens33 192.168.1.64 netmask 255.255.255.0
  最后可以使用 ping + ip 命令ping自己查看是否重置成功。也可以ping命令查看是否与目标主机连接。

子网掩码

  子网掩码为网络掩码、地址掩码、子网络遮罩,一种用来指明一个 IP 地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,它必须结合 IP 地址一起使用。子网掩码只有一个作用,将某个 IP 地址划分成网络地址和主机地址两部分。子网掩码为一个 32 位地址,用于屏蔽 IP 地址的一部分以区别网络标识和主机标识,并说明该 IP 地址是在局域网上,还是在广域网上。

TCP 段分析

在这里插入图片描述

TCP三次握手协议 ⭐

在这里插入图片描述

TCP四次挥手协议 ⭐

在这里插入图片描述

TCP编程

  套接字是操作系统内核中的一个数据结构,它是网络的节点进行相互通信的门户,它是网络进程的 ID。
  端口号是具有网络功能的应用软件的标识号。端口是一个软件结构,被客户程序或服务程序用来发送和接收数据,一台服务器(或计算机)有 256*256 个端口。

基于 TCP 客户端编程-步骤说明

1.创建通信套接字:socket;
2.编写服务器地址信息(IP 端口 协议 TCP);
3.连接服务器:connect
4.发送信息/接收信息;send/rec | write/read
5.关闭通信套接字;close

基于 TCP 服务器端编程-步骤说明

1.创建监听套接字:socket
2.编写服务器地址信息;(IP 端口 协议 TCP);
3.将服务器地址信息与监听套接字绑定:bind;
4.开始监听:listen
5.等待客户端连接:accept(阻塞等待)
//三次握手
6.发送信息/接收信息 read/write
7.关闭通信套接字:close

在这里插入图片描述

基于 TCP 服务端/客户端编程例子⭐

客户端:具备基础通信功能

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <semaphore.h>
typedef struct sockaddr  SA;
typedef struct sockaddr_in  SIN;
#define MAXBACKLOG   100int Socket(int domain,int type,int protocol);
int Connect(int sockfd,struct sockaddr * serv_addr,int addrlen);
void *son_fun(void * arg);int main(int argc,char *argv[])
{	pthread_t id;//建立监听套接字int socketfd = Socket(AF_INET,SOCK_STREAM,0);//connectSIN   serverinfo;serverinfo.sin_family = AF_INET;serverinfo.sin_port   = htons(atoi(argv[2]));serverinfo.sin_addr.s_addr =  inet_addr(argv[1]);int addrlen = sizeof(SIN);Connect(socketfd,(SA*)&serverinfo,addrlen);printf("服务器:%s 端口:%d\n",inet_ntoa(serverinfo.sin_addr),ntohs(serverinfo.sin_port));//创建子线程pthread_create(&id,NULL,son_fun,(void *)&socketfd);//读写while(1){char readbuff[512]={0};gets(readbuff);if(strlen(readbuff)==0) continue;write(socketfd,readbuff,sizeof(readbuff));}//关闭close(socketfd);return 0;
}
int Socket(int domain,int type,int protocol)
{int socketFd = socket(domain,type,protocol);if(socketFd == -1){perror("socket");exit(1);}return socketFd;
}
int Connect (int sockfd,struct sockaddr * serv_addr,int addrlen)
{int val = connect(sockfd,serv_addr,addrlen);if(val == -1){perror("connect");exit(1);}return 0;
}
void *son_fun(void * arg)
{int readpipefd = *((int *)arg);char readbuff[512]={0};while(1){if(read(readpipefd,readbuff,sizeof(readbuff))>0){printf("接收:%s\n",readbuff);}else{close(readpipefd);pthread_exit(NULL);}}
}

服务端:多线程服务端,具备基础通信功能

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <semaphore.h>
typedef struct sockaddr  SA;
typedef struct sockaddr_in  SIN;
#define MAXBACKLOG   100int Socket(int domain,int type,int protocol);
int Bind(int sockfd,struct sockaddr * my_addr,int addrlen);
int Listen(int s,int backlog);
int Accept(int s,struct sockaddr * addr,int * addrlen);
void *son_fun(void * arg);int main(int argc,char *argv[])
{	//建立监听套接字int socketfd = Socket(AF_INET,SOCK_STREAM,0);//需要进行重用地址及其端口号int  opt = 1;setsockopt(socketfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//绑定信息编写服务器信息SIN   serverinfo;serverinfo.sin_family = AF_INET;serverinfo.sin_port   = htons(atoi(argv[2]));serverinfo.sin_addr.s_addr =  inet_addr(argv[1]);int addrlen = sizeof(SIN);Bind(socketfd,(SA*)&serverinfo,addrlen);//监听Listen(socketfd,MAXBACKLOG);//读写while(1){//等待连接SIN clientinfo;int  clientaddrlen = sizeof(SA);int newfd = Accept(socketfd,(SA*)&clientinfo,&clientaddrlen);printf("客户端地址:%s 端口号:%d\n",inet_ntoa(clientinfo.sin_addr),ntohs(clientinfo.sin_port));//创建子线程pthread_t id;pthread_create(&id,NULL,son_fun,(void *)&newfd);}//关闭close(socketfd);return 0;
}
int Socket(int domain,int type,int protocol)
{int socketFd = socket(domain,type,protocol);if(socketFd ==-1){perror("socket");exit(1);}return socketFd;
}
int Bind(int sockfd,struct sockaddr * my_addr,int addrlen)
{int val = bind(sockfd,my_addr,addrlen);if(val){perror("bind");exit(1);}return 0;
}
int Listen(int s,int backlog)
{int val = listen(s,backlog);if(val == -1){perror("listen");exit(1);}return val;
}
int Accept(int s,struct sockaddr * addr,int * addrlen)
{int NEWfd = accept(s,addr,addrlen);if(NEWfd == -1){perror("listen");exit(1);}return NEWfd;
}
void *son_fun(void * arg)
{int readpipefd = *((int *)arg);char readbuff[512]={0};while(1){if(read(readpipefd,readbuff,sizeof(readbuff))>0){printf("接收:%s\n",readbuff);}else{close(readpipefd);pthread_exit(NULL);}}
}

基于 TCP 服务端/客户端编程详细案例⭐

点我查看

函数

创建套接字  socket

头文件:
  #include<sys/types.h>
  #include<sys/socket.h>
函数原型:: int socket(int domain,int type,int protocol);
参数介绍:
  domain:指定使用何种的地址类型。
    PF_INET/AF_INET Ipv4 网络协议
    PF_INET6/AF_INET6 Ipv6 网络协议
  type:
    SOCK_STREAM 提供双向连续且可信赖的数据流,即 TCP。
    SOCK_DGRAM 使用不连续不可信赖的数据包连接。
  protocol:来指定 socket 所使用的传输协议编号,通常为0.
返回值:成功则返回 socket 文件描述符,失败返回-1。

	int socketfd = socket(AF_INET,SOCK_STREAM,0);

绑定函数  bind

头文件:
  #include<sys/types.h>
  #include<sys/socket.h>
函数原型::int bind(int sockfd,struct sockaddr * my_addr,int addrlen);
参数介绍:
  sockfd:socket 文件描述符。
  my_addr:sockaddr 结构体。
  addrlen:结构体长度。
返回值:功则返回0 ,失败返回-1,错误原因存于 errno 中。

//通用的套接字地址结构
struct sockaddr
{unsigned short int sa_family;char sa_data[14];
};
//IPv4 套接字地址结构
struct sockaddr_in
{unsigned short int sin_family;uint16_t sin_port;struct in_addr sin_addr;unsigned char sin_zero[8];
};
struct in_addr
{uint32_t s_addr;
};
//初始化服务器信息
struct sockaddr_in serverinfo;
serverinfo.sin_family =AF_INET; //协议 IPV4
serverinfo.sin_port =htons(atoi(argv[2])); //网络字节序(大端字节序)与主机字节序(小端字节序) 
serverinfo.sin_addr.s_addr= inet_addr(argv[1]);//192.168.5.166 2159634568 80.B9.68.88 128.185.104.136 点分十进制格式
//计算长度
int addrlen = sizeof(struct sockaddr_in);
//绑定
bind(socketfd,(struct sockaddr*)&serverinfo,addrlen);
大小端排序转换函数

主机字节序:主机内部内存中数据的处理方式。Intel 机器采用小端排序方式
网络字节序:网络字节顺序是 TCP/IP 中规定好的一种数据表示格式,它与具体的 CPU 类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用大端排序方式
这里提供一些端口格式转换函数:(n 代表网络,h代表本地,所以h to n 就是本地转换成网络)
在这里插入图片描述

地址格式转换函数

方便把 xxx.xxx.xxx.xxx 类型的地址与成十进制数字相互转换。
int inet_aton(const char *straddr,struct in_addr *addrptr);
作用:把点分十进制格式 IP 转换成 struct in_addr 类型 IP
char * inet_ntoa(struct in_addr inaddr);
作用:把 struct in_addr 类型的 IP 转换为点分十进制格式
in_addr_t inet_addr(const char *straddr);
作用:把点分十进制 IP 转换为 in_addr_t(uint32)类型 IP
示例:inet_aton(“192.168.1.1”,&ser_addr.sin_addr);

监听  listen

头文件:
  #include<sys/socket.h>
函数原型:int listen(int s,int backlog);
参数介绍:
  s:socket 文件描述符。
  backlog:最大连接数。
返回值: 成功则返回 0,失败返回-1,错误原因存于 errno。

	listen(socketfd,MAXBACKLOG);

等待客户端连接  accept

头文件:
  #include<sys/types.h>
  #include<sys/socket.h>
函数原型:int accept(int s,struct sockaddr * addr,int * addrlen);
参数介绍:
  s:socket 文件描述符。
  addr:远程主机的地址数据结构体。
  addrlen:结构体大小。
返回值:成功则返回客户端的 socket 处理代码,失败返回-1,错误原因存于 errno 中。

	struct sockaddr_in clientinfo;int clientaddrlen =sizeof(SA);int clientfd = accept(socketfd,(struct sockaddr*)&clientinfo,&clientaddrlen);

连接服务器   connect

头文件:
  #include<sys/types.h>
  #include<sys/socket.h>
函数原型:int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
参数介绍:
  sockfd:socket 文件描述符。
  addr:远程主机的地址数据结构体。
  addrlen:结构体大小。
返回值:成功则返回 0,失败返回-1,错误原因存于 errno 中。

	connect(socketfd,(struct sockaddr*)&serverinfo,addrlen);

发送函数  send

头文件:
  #include<sys/types.h>
  #include<sys/socket.h>
函数原型:int send(int s,const void * msg,int len,unsigned int falgs);
参数介绍:
  s:socket 文件描述符。
  msg:发送字符串。
  len:字符串长度。
  falgs:设置flags为0时,send和wirte是同等的。
返回值:

	char sendbuff[128] = "11111";send(socketfd,sendbuff,sizeof(sendbuff),0);

接收函数  recv

头文件:
  #include<sys/types.h>
  #include<sys/socket.h>
函数原型:int recv(int s,void *buf,int len,unsigned int flags);
参数介绍:
  s:socket 文件描述符。
  msg:接收字符串。
  len:接收字符串长度。
  falgs:设置flags为0时,recv和re’a’d是同等的。
返回值:

	char readbuff[128] = {0};send(socketfd,readbuff,sizeof(readbuff),0);

NAT映射

概述

  网络地址转换(NAT)是一种用于访问 Internet 访问模式广域网(WAN)的技术,用于将私有(保留)地址转换为合法 IP 地址。NAT 不仅能够有效地额抵抗外部网络攻击(防火墙:外来连接),还能够在 IP 地址分配不理想,不足的时候有效,合理化的分配 IP 地址,从而能够进行互联网访问。
在这里插入图片描述

NAT 的优缺点

优点:
①极大的节省了合法的 IP 地址。
②能够处理地址重复情况,避免了地址的重新编号,增加了编址的灵活性。
③隐藏了内部网络地址,增强了安全性。
④可以使多个使用 TCP 负载特性的服务器之间实现基本的数据包负载均衡。
缺点:
①由于 NAT 要在边界路由器上进行地址的转换,增大了传输的延迟。
②由于 NAT 改动了 IP 地址,失去了跟踪端到端 IP 流量的能力。当出现恶意流量时,会使故障排除和流量跟踪变的更加棘手。
③不支持一些特定的应用程序。如早期版本的 MSN。
④增大了资源开销。处理 NAT 进程增加了 CPU 的负荷,并需要更多内存来存储 NAT 表项。

内网穿透(打洞)技术

NAT 机制导致:
服务器:私网   对   客户端:私网 需要打洞
服务器:公网   对   客户端:私网 无需打洞
服务器:私网   对   客户端:公网 需要打洞
服务器:公网   对   客户端:公网 无需打洞
了解更多

UDP编程

概念

  UDP(user datagram protocol)的中文叫用户数据报协议,属于传输层(TCP/UDP)。UDP 是面向非连接的协议,它不与对方建立连接,而是直接把我要发的数据报发给对方。所以 UDP 适用于一次传输数据量很少、对可靠性要求不高的或对实时性要求高的应用场景。正因为 UDP 无需建立连接如三次握手,而使得通信效率很高。

通信流程

在这里插入图片描述

基于 UDP 客户端编程思路

1.建立 socket 套接字描述符
2.发送数据到服务器端
3.接收服务器端信息
4.关闭

基于 UDP 服务器端编程思路

1.服务器端开始建立 socket 描述符
2.编写服务器信息
3.sockfd 描述符与服务器进行绑定
4.接收客户端发送过来的数据
5.发送数据到客户端
6.关闭

基于UDP 客户端/服务端编程例子⭐

客户端:具备基础通信功能

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <time.h>
#include <pthread.h>
typedef struct sockaddr  SA;
typedef struct sockaddr_in  SIN;
#define MAXBACKLOG   100int Socket(int domain,int type,int protocol);
int Bind(int sockfd,struct sockaddr * my_addr,int addrlen);
int Recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen);
int Sendto ( int s , const void * msg, int len, unsigned int flags, const struct sockaddr * to , int tolen );int main(int argc,char *argv[])
{	//建立监听套接字int socketfd = Socket(AF_INET,SOCK_DGRAM,0);//绑定信息编写服务器信息SIN   serverinfo;serverinfo.sin_family =AF_INET;serverinfo.sin_port   =htons(atoi(argv[2]));serverinfo.sin_addr.s_addr=  inet_addr(argv[1]);int addrlen = sizeof(SIN);//读写while(1){char readbuff[512] = {0};int fromlen = sizeof(SIN);gets(readbuff);//回发Sendto (socketfd,readbuff,strlen(readbuff), 0,(SA*)&serverinfo,fromlen);}//关闭close(socketfd);return 0;
}
int Socket(int domain,int type,int protocol)
{int socketFd = socket(domain,type,protocol);if(socketFd ==-1){perror("socket");exit(1);}return socketFd;
}
int Bind(int sockfd,struct sockaddr * my_addr,int addrlen)
{int val = bind(sockfd,my_addr,addrlen);if(val){perror("bind");exit(1);}return 0;
}
int Recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen)
{int val = recvfrom(s,buf,len,flags ,from ,fromlen);if(val == -1){perror("recvfrom");exit(1);}return 0;
}
int Sendto ( int s , const void * msg, int len, unsigned int flags, const struct sockaddr * to , int tolen )
{int val = sendto (s ,msg,len,flags,to ,tolen );if(val == -1){perror("sendto");exit(1);}return 0;
}

服务端:具备基础通信功能

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <time.h>
#include <pthread.h>typedef struct sockaddr  SA;
typedef struct sockaddr_in  SIN;
#define MAXBACKLOG   100int Socket(int domain,int type,int protocol);
int Bind(int sockfd,struct sockaddr * my_addr,int addrlen);
int Recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen);
int Sendto ( int s , const void * msg, int len, unsigned int flags, const struct sockaddr * to , int tolen );int main(int argc,char *argv[])
{	//建立监听套接字int socketfd = Socket(AF_INET,SOCK_DGRAM,0);//绑定信息编写服务器信息SIN   serverinfo;serverinfo.sin_family =AF_INET;serverinfo.sin_port   =htons(atoi(argv[2]));serverinfo.sin_addr.s_addr=  inet_addr(argv[1]);int addrlen = sizeof(SIN);Bind(socketfd,(SA*)&serverinfo,addrlen);//读写while(1){char readbuff[512]={0};SIN from;int fromlen = sizeof(SIN);Recvfrom(socketfd,readbuff,sizeof(readbuff),0 ,(SA*)&from ,&fromlen);printf("ip:%s port:%d Data:%s\n",inet_ntoa(from.sin_addr),ntohs(from.sin_port),readbuff);//回发Sendto (socketfd,readbuff,strlen(readbuff), 0,(SA*)&from,fromlen);}//关闭close(socketfd);return 0;
}
int Socket(int domain,int type,int protocol)
{int socketFd = socket(domain,type,protocol);if(socketFd ==-1){perror("socket");exit(1);}return socketFd;
}int Bind(int sockfd,struct sockaddr * my_addr,int addrlen)
{int val = bind(sockfd,my_addr,addrlen);if(val){perror("bind");exit(1);}return 0;
}
int Recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen)
{int val = recvfrom(s,buf,len,flags ,from ,fromlen);if(val == -1){perror("recvfrom");exit(1);}return 0;
}
int Sendto ( int s , const void * msg, int len, unsigned int flags, const struct sockaddr * to , int tolen )
{int val = sendto (s ,msg,len,flags,to ,tolen );if(val == -1){perror("sendto");exit(1);}return 0;
}

函数

发送函数  sendto

头文件:
  #include<sys/socket.h>
函数原型:int sendto(int s,const void *msg,int len,unsigned int flags,const struct sockaddr * to,int tolen);
参数介绍:
  s:套接字文件描述符。
  msg:指向要发送数据的容器地址。
  len:要发送的数据长度。
  flags:一般为 0 阻塞等待。
  to:目地机的 ip 地址和端口号信息。
  tolen:地址长度。
返回值:成功返回发送的字节数,出错返回-1。

	struct sockaddr_in to;int tolen = sizeof(struct sockaddr_in);char sendbuff[512] = {0};Sendto(socketfd,sendbuff,strlen(sendbuff), 0,(struct sockaddr*)&to,tolen);

接收函数  recvfrom

头文件:
  #include<sys/socket.h>
函数原型:int recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen);
参数介绍:
  s:套接字文件描述符。
  buf:指向要存储数据容器的地址。
  len:要保存的数据长度。
  flags:—般为 0 阻塞等待。
  from:源主机的 ip 地址和端口号信息。
  formlen:地址长度。
返回值:成功返回接收的字节数,出错返回-1。

	struct sockaddr_in from;int fromlen = sizeof(struct sockaddr_in);char readbuff[512] = {0};Recvfrom(socketfd,readbuff,sizeof(readbuff),0,(struct sockaddr*)&from ,&fromlen);

UDP广播

概念

  广播 UDP 与单播 UDP 的区别就是 IP 地址不同,广播使用广播地址 255.255.255.255,将消息发送到在同一广播网络上的每个主机。值得强调的是:本地广播信息是不会被路由器转发。当然这是十分容易理解的,因为如果路由器转发了广播信息,那么势必会引起网络瘫痪。这也是为什么 IP 协议的设计者故意没有定义互联网范围的广播机制。广播地址通常用于在网络游戏中处于同一本地网络的玩家之间交流状态信息等。其实广播顾名思义,就是想局域网内所有的人说话,但是广播还是要指明接收者的端口号的,因为不可能接受者的所有端口都来收听广播。

广播特点

1.数据传输不用建立连接,所以不可靠(符合 udp 协议的特点)。
2.数据的发送是面向整个子网的,任何一台在子网内的计算机都可以接收到相同的数据。
3.广播用于 udp 和原始 IP,不能用于 TCP。

广播地址

1.直接广播地址:
指 Host 部分全为 1 的广播地址。如:192.168.0.255。当某机器发出目的地址为直接广播(如:192.168.199.255)时,路由器通过查找路由表可以转发,直到该网段。
2.受限广播地址:
也称本地广播地址,它不被路由发送,但会被送到相同物理网络段上的所有主机,IP 地址的网络号和主机号全为 1 就是地址 255.255.255.255,当某机器发出目的地址为本地广播时,路由器不会转发该包。所以该包只能限制在本网段。

网络编程服务器模型

回射服务器

  即接收客户端的消息,把消息原封不动的返回去。

迭代服务器

  在多个客户端连接的时候,服务器在同一时刻只能响应一个客户端的请求。

并发服务器

  在多个客户端连接的时候,服务器在同一时刻可以响应多个客户端的请求。

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

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

相关文章

汽车智能座舱/智能驾驶SOC -1

看到华为&小康的 AITO问界M6、M7各种广告营销、宣传、测评、好评如潮水般席卷网络各APP平台。翻看了中信和海通对特斯拉M3和比亚迪元的拆解报告&#xff0c;也好奇华为的汽车芯片平台又能做出哪些新花样&#xff0c;下面是Mark开头&#xff0c;也学习下智能座舱和智能驾驶芯…

MISRA 2012学习笔记(5)-Rules 8.10

文章目录 Rules8.10 基本类型模型(The essential type model)8.10.1 原理8.10.2 基本类型(Essential type)Rule 10.1 操作数不得具有不适当的基本类型Rule 10.2 在加减法运算中&#xff0c;不得不当使用本质为字符类型的表达式Rule 10.3 表达式的值不得赋值给具有较窄基本类型或…

单线程的JS中Vue导致的“线程安全”问题

目录 现象分析原因 浏览器中Js是单线程的&#xff0c;当然不可能出现线程安全问题。只是遇到的问题的现象与多线程的情况十分相似&#xff0c;导致对不了解Vue实现的我怀疑起了人生… 现象 项目中用到了element-plus中的加载组件&#xff0c;简单封装了一下&#xff0c;用来保…

linux 开发板以太网通过Ubuntu上外网方法

在开发板嵌入式设备&#xff0c;有一个mgbe网卡&#xff0c;用网线与连接soc的网卡&#xff0c;和外接网卡&#xff0c;将网卡usb接口插入电脑&#xff0c;选择接入到Ubuntu系统 在Ubuntu将能识别到这个外接网卡&#xff0c;这样就可以通过Ubuntu和soc通讯了&#xff0c; 如下…

服务案例|故障频发的一周,居然睡得更香!

医院运维有多忙&#xff1f; 医院运维&#xff0c;听起来平平无奇毫不惊艳&#xff0c;但其中的含金量&#xff0c;可不是“维持系统正常运行”就能总结的。毕竟医院对业务连续性的超高要求&#xff0c;让运维面对的问题都是暂时的&#xff0c;下一秒可能就有新问题需要发现解…

双12电视盒子推荐:测评员解析目前电视盒子哪个最好

电视盒子不需要每月缴费&#xff0c;只需联网就可以收看海量视频资源&#xff0c;游戏、网课、投屏等功能让电视盒子的使用场景更丰富&#xff0c;我每年都会进行数十次电视盒子测评&#xff0c;本期要分享的是双十二电视盒子推荐&#xff0c;全面解析目前电视盒子哪个最好。 一…

思福迪 运维安全管理系统 test_qrcode_b 远程命令执行漏洞

思福迪 运维安全管理系统 test_qrcode_b 远程命令执行漏洞 一、漏洞描述二、漏洞影响三、网络测绘四、漏洞复现1.手动复现2.自动化复现3.python源代码 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任…

数据结构——栈的详细介绍

数据结构——栈 一、栈的结构和概念二、 栈的两种构建方式①、用数组进行构建②、用链表进行构建 三、栈的创建四、栈的初始化五、栈的销毁六、压栈七、出栈八、判空九、获取栈顶元素十、获取栈的size 一、栈的结构和概念 栈&#xff1a;栈是一种特殊的线性表&#xff0c;其只…

第15届蓝桥STEMA测评真题剖析-2023年10月29日Scratch编程初中级组

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第160讲。 第15届蓝桥第2次STEMA测评&#xff0c;这是2023年10月29日举办的STEMA&#xff0c;比赛仍然采取线上形式。这…

Autoware.universe部署06:使用DBC文件进行UDP的CAN通信代码编写

目录标题 一、安装DBC文件编辑工具VectorCANdb二、编写DBC文件2.1 CAN通信协议2.2 编写DBC文件2.2.1 根据CAN协议设置signals2.2.2 设置报文2.2.3 建立节点 三、根据DBC文件编写ROS2驱动程序四、实际通信调试 根据CAN协议编写DBC文件&#xff0c;通过DBC文件编写ROS2包进行UDP通…

jetpack compose中实现丝滑的轮播图效果

写在前面 最近在翻Jetpack库&#xff0c;发现了DataStore&#xff0c;官方是这么说的&#xff1a; Jetpack DataStore 是一种数据存储解决方案&#xff0c;允许您使用协议缓冲区存储键值对或类型化对象。DataStore 使用 Kotlin 协程和 Flow 以异步、一致的事务方式存储数据。 …

laravel引入element-ui后,blade模板中使用elementui时,事件未生效问题(下载element-ui到本地直接引入项目)

背景 重构公司后台项目&#xff0c;使用了dcat-admin&#xff0c;但是dcat-admin有些前端功能不能满足需求。因此引入element-ui进行相关界面的优化 具体流程 1.下载element-ui到本地 2.进入如下目录 打开 node_modules\element-ui\lib 复制index.js 打开 node_modules/ele…

[Linux] shell条件语句和if语句

一、条件语句 1.1 测试 test 测试文件的表达式是否成立 格式&#xff1a;test 条件表达式 [ 条件表达式 ] 选项作用-d测试是否为目录-e测试目录或文件是否存在-a测试目录或文件是否存在-f测试是否为文件-r测试当前用户是否有权限读取-w测试当前用户是否有权限写入-x测试当前…

一键合并多个TXT文本,将保存在TXT的快递单号进行一键合并

如果你需要处理大量的TXT文本文件&#xff0c;那么你可能会遇到需要将这些文件合并为一个文件的情况。这不仅涉及到文件的组织和管理&#xff0c;还可能涉及到文件内容的连贯性和完整性。现在&#xff0c;我们有一个强大的工具&#xff0c;可以帮助你轻松实现一键文件整理&…

PCB抄板的一些方法

PCB抄板的技术实现过程简单来说&#xff0c;就是先将要抄板的电路板进行扫描&#xff0c;记录详细的元器件位置&#xff0c;然后将元器件拆下来做成物料清单&#xff08;BOM&#xff09;并安排物料采购&#xff0c;空板则扫描成图片经抄板软件处理还原成pcb板图文件&#xff0c…

私域电商模式全解析:掌握这些方法,让你的生意不再难做!

私域电商是指利用微信、QQ等社交平台将客户流量转化和沉淀&#xff0c;并促使其进行重复购买的电商模式。私域电商具备两个主要特点&#xff0c;分别是“私域”和“电商”。 “私域”指的是将客户添加为好友&#xff0c;并利用微信、QQ、微博等社交平台进行联系和营销的模式。…

智能座舱架构与芯片 - (1) 背景篇

一、软件定义汽车 1.1 什么是软件定义汽车 软件定义汽车(Software Defined Vehicles, SDV)的核心思想是&#xff0c;决定未来汽车的是人工智能为核心的软件技术&#xff0c;而不再是汽车的马力大小&#xff0c;是否真皮座椅&#xff0c;机械性能的好坏。软件定义汽车的终极目…

Servlet实现一个简单的表白墙网站

文章目录 前言效果展示事前准备HTML、CSS、JavaScript分别负责哪些HTML和CSS构架出页面的基本结构和样式JavaScript 实现行为和交互实现服务器端的业务代码整理pom.xmlweb.xmlmessageWall.htmlMessageServlet.java 前言 前面我们学习了 Java 中知名的 HTTP 服务器 tomcat 的安…

栈的生长方向不总是向下

据我了解&#xff0c;栈的生长方向向下&#xff0c;内存地址由高到低 测试 windows下&#xff1a; 符合上述情况 测试Linux下&#xff1a; 由此可见&#xff0c;栈在不同操作系统环境下&#xff0c;生长方向不总是向下

t检验(连续变量)和卡方检验(分类变量)

目录 情形 不同种类的萼片差异 数据类型查看&#xff1a; 差异分析&#xff1a; 不同萼片的种类差异 数据准备 二分类卡方检验 绘图 情形 &#xff1a;当有两列数据进行分析比较时&#xff0c;一列为连续变量&#xff0c;一列数据为分类变量。 rm(list ls()) libra…