UDP通讯实现

服务器端:

1.获取套接字

cpp 复制代码
	int fd;
	fd=socket(AF_INET,SOCK_DGRAM,0);
	if(fd<0){
		perror("socket");
		exit(0);
	}

#include <sys/types.h>

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

-domain: 指定通信域(通信地址族);

-type: 指定套接字类型; 数据报套接字:SOCK_DGRAM

-protocol: 指定协议; 数据报接字唯一对应TCP,所以无需要指定协议,设为0即可

2.绑定套接字

cpp 复制代码
	struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));
	addr.sin_port=htons(atoi(argv[2]));
	//man inet_aton,判断地址转换是否成功
	if((inet_aton(argv[1],&addr.sin_addr))==0){
		fprintf(stderr,"Invalid address\n");//表示将"Invalid address"给标准错误stderr
		exit(0);
	}
	if(bind(fd,(struct sockaddr *)&addr,sizeof(addr))<0){
		perror("bind");
		exit(0);
	}

函数1:

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

-sockfd:socket函数生成的套接字

-addr:通信结构体

-addrlen:通信结构体的长度

注意:参数addr是通用结构体sockaddr,要将初始化的sock_in结构体强制转换

struct sockaddr_in { sa_family_t sin_family;

/* 地址族: AF_INET */ in_port_t sin_port;

/* 网络字节序的端口号 */ struct in_addr sin_addr;

/*IP地址结构体 */ };

/* IP地址结构体 */ struct in_addr { uint32_t s_addr; /* 网络字节序的IP地址 */ };

函数2:

在C语言中,inet_aton函数用于将表示IPv4地址的字符串转换为网络字节序的32位二进制数。该函数的原型如下:

int inet_aton(const char *cp, struct in_addr *inp);

其中:

  • cp是一个指向表示IPv4地址的字符串的指针。
  • inp是一个指向in_addr结构的指针,用于存储转换后的IPv4地址。

函数返回值为整型,如果字符串成功转换为IPv4地址,则返回1;如果转换失败,则返回0。

函数3:

`bzero()` 函数用于将指定长度的内存区域清零,即将所有字节初始化为0。它通常用于清空敏感的数据或准备数据结构。`bzero()` 函数在许多系统中已经被废弃,应该使用更现代的函数`memset()` 来替代。其原型如下:

void bzero(void *s, size_t n);

其中,参数 `s` 是指向要清零的内存区域的指针,参数 `n` 是要清零的字节数。

3.接收数据

cpp 复制代码
	while(1){
		bzero(buf,BUFSIZ);
		recvfrom(fd,buf,BUFSIZ,0,NULL,NULL);
		printf("buf=%s\n",buf);
	}
	close(fd);

函数原型:ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,

struct sockaddr *src_addr, socklen_t *addrlen);

功能:接收数据,并将接收到的数据存放到buf指向的缓冲区中。

参数说明:

  • sockfd:要接收数据的套接字文件描述符。

  • buf:指向用于存放接收数据的缓冲区。

  • len:缓冲区的长度。

  • flags:一些控制接收操作的标志。

  • src_addr:指向发送方的地址结构体的指针。

  • addrlen:发送方地址结构体的长度。

返回值:成功接收到数据时,返回接收到的数据的长度;失败时,返回-1并设置errno。

原始代码

cpp 复制代码
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<strings.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
int main(int argc ,char *argv[]){
	int fd;
	char buf[BUFSIZ]={};
	struct sockaddr_in addr;
	if(argc<3){
		fprintf(stderr,"%s<addr><port>\n",argv[0]);
		exit(0);
	}
	fd=socket(AF_INET,SOCK_DGRAM,0);
	if(fd<0){
		perror("socket");
		exit(0);
	}
	bzero(&addr,sizeof(addr));
	addr.sin_port=htons(atoi(argv[2]));
	//man inet_aton,判断地址转换是否成功
	if((inet_aton(argv[1],&addr.sin_addr))==0){
		fprintf(stderr,"Invalid address\n");//表示将"Invalid address"给标准错误stderr
		exit(0);
	}
	if(bind(fd,(struct sockaddr *)&addr,sizeof(addr))<0){
		perror("bind");
		exit(0);
	}
	while(1){
		bzero(buf,BUFSIZ);
		recvfrom(fd,buf,BUFSIZ,0,NULL,NULL);
		printf("buf=%s\n",buf);
	}
	close(fd);
	return 0;
}

客户端:

1.获取套接字

cpp 复制代码
	int fd;
	fd=socket(AF_INET,SOCK_DGRAM,0);
	if(fd<0){
		perror("socket");
		exit(0);
	}

#include <sys/types.h>

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

-domain: 指定通信域(通信地址族);

-type: 指定套接字类型; 数据报套接字:SOCK_DGRAM

-protocol: 指定协议; 数据报接字唯一对应TCP,所以无需要指定协议,设为0即可

2.发送数据

cpp 复制代码
	char buf[BUFSIZ]={};
	struct sockaddr_in addr;
	socklen_t addrlen;
	addrlen=sizeof(addr);
    bzero(&addr,sizeof(addr));
	addr.sin_port=htons(atoi(argv[2]));
	//man inet_aton,判断地址转换是否成功
	if((inet_aton(argv[1],&addr.sin_addr))==0){
		fprintf(stderr,"Invalid address\n");//表示将"Invalid address"给标准错误stderr
		exit(0);
	}

	while(1){
		bzero(buf,BUFSIZ);
		printf("input>");
		fgets(buf,BUFSIZ,stdin);
		sendto(fd,buf,strlen(buf),0,(struct sockaddr *)&addr,addrlen);
	}

函数1:

在C语言中,inet_aton函数用于将表示IPv4地址的字符串转换为网络字节序的32位二进制数。该函数的原型如下:

int inet_aton(const char *cp, struct in_addr *inp);

其中:

  • cp是一个指向表示IPv4地址的字符串的指针。
  • inp是一个指向in_addr结构的指针,用于存储转换后的IPv4地址。

函数返回值为整型,如果字符串成功转换为IPv4地址,则返回1;如果转换失败,则返回0。

函数2:

`bzero()` 函数用于将指定长度的内存区域清零,即将所有字节初始化为0。它通常用于清空敏感的数据或准备数据结构。`bzero()` 函数在许多系统中已经被废弃,应该使用更现代的函数`memset()` 来替代。其原型如下:

void bzero(void *s, size_t n);

其中,参数 `s` 是指向要清零的内存区域的指针,参数 `n` 是要清零的字节数。

函数3:

sendto函数用于向指定的套接字发送数据。其声明如下:

```c

#include <sys/types.h>

#include <sys/socket.h>

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`: 目标地址结构体的长度。

成功发送数据时,sendto函数返回发送的字节数。如果发生错误,则返回-1,并设置errno变量指示错误原因。

注意:

1.nc -u +IP地址+端口号,连接服务器,本地回环

2.udp停止服务器端,再开启后,客户端也是可以正常发送,服务器端正常接收

原始代码:

cpp 复制代码
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<strings.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>
int main(int argc ,char *argv[]){
	int fd;
	char buf[BUFSIZ]={};
	struct sockaddr_in addr;
	socklen_t addrlen;
	addrlen=sizeof(addr);
	if(argc<3){
		fprintf(stderr,"%s<addr><port>\n",argv[0]);
		exit(0);
	}
	fd=socket(AF_INET,SOCK_DGRAM,0);
	if(fd<0){
		perror("socket");
		exit(0);
	}
	bzero(&addr,sizeof(addr));
	addr.sin_port=htons(atoi(argv[2]));
	//man inet_aton,判断地址转换是否成功
	if((inet_aton(argv[1],&addr.sin_addr))==0){
		fprintf(stderr,"Invalid address\n");//表示将"Invalid address"给标准错误stderr
		exit(0);
	}

	while(1){
		bzero(buf,BUFSIZ);
		printf("input>");
		fgets(buf,BUFSIZ,stdin);
		sendto(fd,buf,strlen(buf),0,(struct sockaddr *)&addr,addrlen);
	}
	close(fd);
	return 0;
}
相关推荐
中云DDoS CC防护蔡蔡6 小时前
DDOS和CC攻击谁更可怕
运维·服务器·经验分享·网络安全·ddos
Ruiery6 小时前
Linux 6.6内核内存管理深度解析(十六):mmap — 用户态“申请内存“的真相
linux·运维·服务器
2501_915106326 小时前
抓包抓到乱码或压缩字节怎么解析,TraceEagle五种查看模式和一键解码
网络协议·计算机网络·网络安全·ios·adb·https·udp
欧米欧7 小时前
Linux系统篇(七),环境变量的底层溯源,核心获取机制与安全应用
linux·运维·服务器
情 九7 小时前
MCP 实战 06:把 HTTP 接口接成工具,让 AI 帮你查数据
人工智能·网络协议·http·mcp
Ruiery7 小时前
Linux 6.6内核内存管理深度解析(十八):KASLR 内核地址空间随机化
linux·运维·服务器·安全
qetfw7 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
前端精髓8 小时前
调用大模型API
运维·服务器·microsoft
Da Da 泓8 小时前
五子棋 Web 端测试用例报告
前端·网络·websocket·网络协议·测试用例·项目
逆风的蚂蚁9 小时前
linux服务器性能调整怎么落地?我把 CPU 调度、I/O 优先级和内核参数这几个旋钮都拧了一遍
linux·运维·服务器