Linux系统编程-->UDP编程:C/S模型实战详解

目录

基于UDP协议的编程

特点

udp客户端流程​编辑

socket

bind(可选)

[sendto(发送函数)------- 先发](#sendto(发送函数)------- 先发)

功能

参数

返回值

udp服务端流程​编辑

socket_udp

bind

[recvfrom(接收函数)------ 先收](#recvfrom(接收函数)------ 先收)

功能

参数

返回值

练习1

udp_client.c

udp_server.c

练习2

udp_client.c

udp_server.c


基于UDP协议的编程

编程模型:C/S

特点

  • 无连接
  • 不可靠
  • 数据报

udp客户端流程

socket

bind(可选)

sendto(发送函数)------- 先发

**ssize_t****send(**int sockfd, const void *buf, size_t len, int flags);

ssize_tsendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);

功能
  • 将数据发送到指定的地址上
参数
  • sockfd:进行发送用到的socket的fd
  • buf:要发送的数据
  • len:要发送的数据的长度
  • flags:标志,默认写0表示默认发送方式
  • dest_addr:表示要发送到的目的地址
  • addrlen:表示目的地址的大小
返回值
  • 成功返回 发送出去了的字节个数
  • 失败返回 -1并且errno被设置

udp服务端流程

socket_udp

eg:int fd = socket(AF_INET,SOCK_DGRAM,0);

bind

recvfrom(接收函数)------ 先收

ssize_trecv(int sockfd, void *buf, size_t len, int flags);

ssize_trecvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);

功能
  • 接收数据
参数
  • sockfd:进行发送用到的socket的fd
  • buf:接收到的数据存放的位置
  • len:要接收多少个字节的长度
  • flags:标志,默认写0表示默认发送方式
  • dest_addr:表示接收到的 源地址
  • addrlen:表示值结果参数,用的时候初始化为 实际用到 src_addr类型的大小,函数返回将会带出真正src_addr地址的大小
返回值
  • 成功返回 接收到的的字节个数
  • 失败返回 -1并且errno被设置

练习1

udp_client.c

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <strings.h>
#include <string.h>

int main(int argc, const char *argv[])
{
	//1.socket
	int fd = socket(AF_INET,SOCK_DGRAM,0);
	if(fd < 0)
	{
		perror("socket fail");
		return -1;
	}

	
	//服务器的地址信息
	struct sockaddr_in seraddr;
	bzero(&seraddr,sizeof(seraddr));
	seraddr.sin_family = AF_INET;
	seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	seraddr.sin_port = htons(50000);
	
	//2.sendto
	char buf[1024];
	while(1)
	{
		printf("client>");
	    fgets(buf,sizeof(buf),stdin);
		sendto(fd,buf,strlen(buf)+1,0,(struct sockaddr *)&seraddr,sizeof(seraddr));
		recvfrom(fd,buf,sizeof(buf),0,NULL,NULL);
		printf("buf:%s\n",buf);
	}

	return 0;
}

udp_server.c

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <strings.h>
#include <string.h>

int main(int argc, const char *argv[])
{
	//1.socket
	int fd = socket(AF_INET,SOCK_DGRAM,0);
	if(fd < 0)
	{
		perror("socket fail");
		return -1;
	}

	//2.bind
	
	//服务器的地址信息
	struct sockaddr_in seraddr;
	bzero(&seraddr,sizeof(seraddr));
	seraddr.sin_family = AF_INET;
	seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	seraddr.sin_port = htons(50000);

	if(bind(fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
	{
		perror("bind fail");
		return -1;
	}

	//3.recvfrom
	char buf[1024];
	char sbuf[1024];
	struct sockaddr_in srcaddr;
	bzero(&srcaddr,sizeof(srcaddr));
	socklen_t len = sizeof(srcaddr);

	while(1)
	{
		recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&srcaddr,&len);
		printf("buf:%s\n",buf);
		sprintf(sbuf,"ser:%s",buf);
		sendto(fd,sbuf,strlen(sbuf)+1,0,(struct sockaddr *)&srcaddr,len);
	}
	return 0;
}

练习2

udp_client.c

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>	       /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
int fd = 0;
struct sockaddr_in seraddr;
char buf[1024] = "hello udp!";
pthread_t tid[2];

void * do_send (void *arg)
{
	while(1)
	{
		printf(">");
		fgets(buf,sizeof(buf),stdin);
		sendto(fd,buf,strlen(buf)+1,0,(struct sockaddr *)&seraddr,sizeof(seraddr));
		if (strncmp(buf,"quit",4) ==0)
		  break;
	}	
	pthread_cancel(tid[1]);
	return NULL;
}

void * do_recv (void *arg)
{
	while(1)
	{
		char rbuf[1024] = {0};
		recvfrom(fd,rbuf,sizeof(rbuf),0,NULL,NULL);
		printf("recv buf = %s\n",rbuf);
		if (strncmp(rbuf,"quit",4) ==0)
		{
		  break;
		}
	}	

	pthread_cancel(tid[0]);
	return NULL;
}

int main(int argc, const char *argv[])
{
	//1.socket 
	 fd = socket(AF_INET,SOCK_DGRAM,0);
	if (fd < 0)
	{
		perror("socket fail");
		return -1;
	}

	//2.sendto 
	//服务器的地址信息 
	bzero(&seraddr,sizeof(seraddr));
	seraddr.sin_family = AF_INET;
	seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	seraddr.sin_port = htons(50000);

    //创建线程
	int ret = pthread_create(&tid[0],NULL,do_send,NULL);
	if (ret !=0 )
	{
		errno = ret;
		perror("pthread_create fail");
		return -1;
	}
	 ret = pthread_create(&tid[1],NULL,do_recv,NULL);
	if (ret !=0 )
	{
		errno = ret;
		perror("pthread_create fail");
		return -1;
	}

	pthread_join(tid[0],NULL);
	pthread_join(tid[1],NULL);
	close(fd);
	return 0;
}

udp_server.c

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>	       /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
struct sockaddr_in srcaddr;
int fd;
char buf[1024] = "hello udp!";
pthread_t tid[2];

void * do_send (void *arg)
{
	while(1)
	{
		printf(">");
		fgets(buf,sizeof(buf),stdin);
		sendto(fd,buf,strlen(buf)+1,0,(struct sockaddr *)&srcaddr,sizeof(srcaddr));
		if (strncmp(buf,"quit",4) ==0)
		{
		  break;
		}
	}	
	pthread_cancel(tid[1]);
	return NULL;
}

void * do_recv (void *arg)
{
	while(1)
	{
		char rbuf[1024] = {0};
		recvfrom(fd,rbuf,sizeof(rbuf),0,NULL,NULL);
		printf("recv buf = %s\n",rbuf);
		if (strncmp(rbuf,"quit",4) ==0)
		{
		  break;
		}
	}	
	pthread_cancel(tid[0]);
	return NULL;
}
int main(int argc, const char *argv[])
{
	//1.socket 
	fd = socket(AF_INET,SOCK_DGRAM,0);
	if (fd < 0)
	{
		perror("socket fail");
		return -1;
	}
	
	//2.bind 
	//服务器的地址信息 
	struct sockaddr_in seraddr;
	bzero(&seraddr,sizeof(seraddr));
	seraddr.sin_family = AF_INET;
	seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	seraddr.sin_port = htons(50000);
	
	if (bind (fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
	{
		perror("bind fail");
		return -1;
	}
	
	//3.recvfrom 
	char buf[1024];
	socklen_t len = sizeof(srcaddr);
	bzero(&srcaddr,sizeof(srcaddr));
	recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *)&srcaddr,&len);
	printf("-----clinet info------\n");
	printf("client ip = %s\n",inet_ntoa(srcaddr.sin_addr));
	printf("client port = %d\n",ntohs(srcaddr.sin_port));
	printf("buf = %s\n",buf);
    
    //创建线程
	int ret = pthread_create(&tid[0],NULL,do_send,NULL);
	if (ret !=0 )
	{
		errno = ret;
		perror("pthread_create fail");
		return -1;
	}
	 ret = pthread_create(&tid[1],NULL,do_recv,NULL);
	if (ret !=0 )
	{
		errno = ret;
		perror("pthread_create fail");
		return -1;
	}
	pthread_join(tid[0],NULL);
	pthread_join(tid[1],NULL);
	close(fd);
	return 0;
}
相关推荐
志栋智能3 分钟前
超自动化巡检:如何应对海量增长的基础设施?
运维·自动化
苏宸啊6 分钟前
磁盘结构、存储原理
linux
代码讲故事7 分钟前
Redis生产环境批量的key需要删除,如何优雅实现且不影响线上环境?有密码认证的如何实现批量删除?有哪些实现方法?
运维·redis·缓存·高并发·删除·批量·生产环境
只要微微辣18 分钟前
Vue3 + TS 企业级 WebSocket 封装实战:高可用、自动重连、心跳检测与业务解耦方案
网络·websocket·网络协议
Irene199132 分钟前
两种 Linux 发行版:Ubuntu 与 CentOS Shell 环境核心差异对比(查看 Linux 版本,Hadoop 是什么)
linux·ubuntu·centos
j7~33 分钟前
【Linux系统】基础IO(文件描述)(1)
linux·服务器·c++·文件·基础io
MXsoft61834 分钟前
**配置文件频繁变更导致故障?版本控制****+****合规检查必不可少**
运维
星辰&与海35 分钟前
多个串口加输出
linux
广州灵眸科技有限公司35 分钟前
瑞芯微(EASY EAI)RV1126B 模型部署API说明
linux·开发语言·网络·人工智能·深度学习·算法·yolo
gjc59236 分钟前
Linux MySQL服务器SSH多端口配置:解决22端口禁直连,兼顾安全与运维
linux·运维·服务器·mysql·ssh