带你手把手实现简单的UDP

news2024/9/9 4:47:46

预备知识

网络编程套接字-CSDN博客

因为UDP是无连接,不可靠,并且以数据报进行传输数据的方式,所以我们实现的时候只需要用到socket和bind即可

一.服务端

1.1 创建套接字

创建套接字很简单,只需要调用socket函数即可参数AF_INETipv4然后SOCK_DGRAM代表使用的UDP进行传输,创建完套接字后,需要进行判断套接字是否创建成功

int serfd=0;
	serfd=socket(AF_INET,SOCK_DGRAM,0);
	if(serfd<0)
	{
		perror("socke failed");
		return -1;
	}
	printf("socket success\n");

1.2 绑定套接字ip地址和端口信息

因为我们使用的是ipv4 所以我们传入的结构为sockaddr_in类型,并把他的协议家族和ip和prot进行传入,然后调用bind函数进行绑定,绑定完成后记得判断是否绑定成功。

int ret=0;
	struct sockaddr_in seraddr={0};
	seraddr.sin_family=AF_INET;
	seraddr.sin_addr.s_addr=inet_addr(argv[1]);
	seraddr.sin_port=htons(atoi(argv[2]));
	
	ret=bind(serfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
	if(ret<0)
	{
		perror("bind failed");
		close(serfd);
		return -1;
	}

1.3 接收和发送信息

接收recvfrom和发送sendto用这俩个函数即可,可以看预备知识这俩个函数怎么使用,这里用的是死循环,一直可以接收发送进行数据传输。

while(1)
{
	int addrlen=0;
	char buf[1024]={0};
	struct sockaddr_in clientaddr={0};
	addrlen=sizeof(clientaddr);
	ret = recvfrom(serfd,buf,sizeof(buf),0,(struct sockaddr *)&clientaddr,(socklen_t*)&addrlen);
	if(ret<0)
	{
		perror("recvfrom failed");
		close(serfd);
		return -1;
	}
	printf("IP=%s,port=%u\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
	printf("recvfrom success\n");
	printf("receive:  %s\n",buf);
//向客户端发送消息	
	memset(buf,0,sizeof(buf));
	scanf("%s",buf);
	ret=sendto(serfd,buf,strlen(buf),0,(struct sockaddr *)&clientaddr,addrlen);
	if(ret<0)
	{
		perror("sendto failed");
		close(serfd);
		return -1;
	}
	printf("sendto success\n");
}
	close(serfd);
	return 0;
}

二. 客户端

2.1 创建套接字

想要进行传输,首要就是创建套接字,

int clifd = 0;
    clifd = socket(AF_INET, SOCK_DGRAM, 0);
    if (clifd < 0)
    {
        perror("socke failed");
        return -1;
    }
    printf("socket success\n");

2.2 发送和接受数据

客户端不用bind信息,知道服务端的ip和端口,直接进行传输信息即可,代码原理跟服务端相同,只不过客户端先进行发送数据

while (1)
    {
        int tolen = 0;
        int ret = 0;
        char buf[1024] = {0};
        scanf("%s", buf);

        struct sockaddr_in seraddr = {0};
        seraddr.sin_family = AF_INET;
        seraddr.sin_addr.s_addr = inet_addr(argv[1]);
        seraddr.sin_port = htons(atoi(argv[2]));
        tolen = sizeof(seraddr);
        ret = sendto(clifd, buf, strlen(buf), 0, (struct sockaddr *)&seraddr, tolen);
        if (ret < 0)
        {
            perror("sendto failed");
            close(clifd);
            return -1;
        }
        printf("sendto success\n");
        // 接收发送自服务器的消息
        ret = recvfrom(clifd, buf, sizeof(buf), 0, NULL, NULL);
        if (ret < 0)
        {
            perror("recvfrom failed");
            close(clifd);
            return -1;
        }
        printf("recvfrom success\n");
        printf("receive:  %s\n", buf);
    }
    close(clifd);

三.整体代码

3.1 服务端

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<unistd.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>


//创建UDP实现服务器和客户端的通信

int main(int argc, char *argv[])
{
     if (argc != 3)
    {
        printf("Usage ./dict_server [ip] [port]\n");
        return 1;
    }


//创建socket连接
	int serfd=0;
	serfd=socket(AF_INET,SOCK_DGRAM,0);
	if(serfd<0)
	{
		perror("socke failed");
		return -1;
	}
	printf("socket success\n");
//绑定IP地址和端口信息
	int ret=0;
	struct sockaddr_in seraddr={0};
	seraddr.sin_family=AF_INET;
	seraddr.sin_addr.s_addr=inet_addr(argv[1]);
	seraddr.sin_port=htons(atoi(argv[2]));
	
	ret=bind(serfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
	if(ret<0)
	{
		perror("bind failed");
		close(serfd);
		return -1;
	}
	printf("bind success\n");
//接收发送自客户端的消息
while(1)
{
	int addrlen=0;
	char buf[1024]={0};
	struct sockaddr_in clientaddr={0};
	addrlen=sizeof(clientaddr);
	ret = recvfrom(serfd,buf,sizeof(buf),0,(struct sockaddr *)&clientaddr,(socklen_t*)&addrlen);
	if(ret<0)
	{
		perror("recvfrom failed");
		close(serfd);
		return -1;
	}
	printf("IP=%s,port=%u\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
	printf("recvfrom success\n");
	printf("receive:  %s\n",buf);
//向客户端发送消息	
	memset(buf,0,sizeof(buf));
	scanf("%s",buf);
	ret=sendto(serfd,buf,strlen(buf),0,(struct sockaddr *)&clientaddr,addrlen);
	if(ret<0)
	{
		perror("sendto failed");
		close(serfd);
		return -1;
	}
	printf("sendto success\n");
}
	close(serfd);
	return 0;
}

3.2 客户端

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>

// 创建UDP实现服务器和客户端的通信
// 创建socket连接
int main(int argc, char *argv[])
{

    if (argc != 3)
    {
        printf("Usage ./dict_server [ip] [port]\n");
        return 1;
    }

    // 创建socket连接
    int clifd = 0;
    clifd = socket(AF_INET, SOCK_DGRAM, 0);
    if (clifd < 0)
    {
        perror("socke failed");
        return -1;
    }
    printf("socket success\n");
    // 向服务器发送消息
    while (1)
    {
        int tolen = 0;
        int ret = 0;
        char buf[1024] = {0};
        scanf("%s", buf);

        struct sockaddr_in seraddr = {0};
        seraddr.sin_family = AF_INET;
        seraddr.sin_addr.s_addr = inet_addr(argv[1]);
        seraddr.sin_port = htons(atoi(argv[2]));
        tolen = sizeof(seraddr);
        ret = sendto(clifd, buf, strlen(buf), 0, (struct sockaddr *)&seraddr, tolen);
        if (ret < 0)
        {
            perror("sendto failed");
            close(clifd);
            return -1;
        }
        printf("sendto success\n");
        // 接收发送自服务器的消息
        ret = recvfrom(clifd, buf, sizeof(buf), 0, NULL, NULL);
        if (ret < 0)
        {
            perror("recvfrom failed");
            close(clifd);
            return -1;
        }
        printf("recvfrom success\n");
        printf("receive:  %s\n", buf);
    }
    close(clifd);

    return 0;
}

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

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

相关文章

决策树可解释性分析

决策树可解释性分析 决策树是一种广泛使用的机器学习算法&#xff0c;以其直观的结构和可解释性而闻名。在许多应用场景中&#xff0c;尤其是金融、医疗等领域&#xff0c;模型的可解释性至关重要。本文将从决策路径、节点信息、特征重要性等多个方面分析决策树的可解释性&…

Thymeleaf(看这一篇就够了)

目录&#xff1a; Thymeleaf变量输出操作字符串&时间条件判断迭代遍历使用状态变量获取域中的数据URL写法相关配置 Thymeleaf Thymeleaf是一款用于渲染XML/HTML5内容的模板引擎&#xff0c;类似JSP。它可以轻易的与SpringMVC等Web框架进行集成作为Web应用的模板引擎。Spri…

暄桐林曦老师推荐书单——《菜根谭》

暄桐是一间传统美学教育教室&#xff0c;创办于2011年&#xff0c;林曦是创办人和授课老师&#xff0c;教授以书法为主的传统文化和技艺&#xff0c;皆在以书法为起点&#xff0c;亲近中国传统之美&#xff0c;以实践和所得&#xff0c;滋养当下生活。      在暄桐教室的课…

机械运动、工控机概念整理

Signal &#xff1a; 信号 pul 【pulse】是驱动脉冲信号&#xff0c;发一个脉冲&#xff0c;电机走一步。 dir是方向控制信号&#xff0c;控制电机正转或反转。 ena是使能信号&#xff0c;这个信号必须开启&#xff0c;才能驱动电机。 voltage&#xff1a; 电压 VCC&#…

Python软件开发:AI毕业设计生成器引领未来

&#x1f31f; 革新软件开发&#xff1a;Python毕业设计生成器引领未来 &#x1f680; 目录 &#x1f31f; 革新软件开发&#xff1a;Python毕业设计生成器引领未来 &#x1f680;&#x1f393; 课题简介&#x1f31f; 开发目的&#x1f4c8; 开发意义 &#x1f4da; 研究方法&…

[ BLE4.0 ] 伦茨ST17H66开发-串口UART0的接收与发送

目录 一、前言 二、实现步骤 1.设置回调函数 2.关闭睡眠模式 三、效果展示 四、工程源代码 一、前言 串口通信在任何一款单片机开发中都是尤为重要的。本文涉及的开发所使用的例程依然是基于[ BLE4.0 ] 伦茨ST17H66开发-OSAL系统中添加自己的Task任务文章的工程源码&#x…

进程间通信--套接字socket

前面提到的管道、消息队列、共享内存、信号和信号量都是在同一台主机上进行进程间通信&#xff0c;那要想跨网络与不同主机上的进程之间通信&#xff0c;就需要Socket通信了。 实际上&#xff0c;Socket通信不仅可以跨网络与不同主机的进程间通信&#xff0c;还可以在同主机上…

一键升级GIS场景视觉效果,告别繁琐操作

在当今的数字化时代&#xff0c;GIS&#xff08;地理信息系统&#xff09;不再仅仅只能通过一些二维示意图或简陋的三维地形图表示&#xff0c;它可以通过专业的软件简单升级视效。想象一下&#xff0c;在你的GIS场景中&#xff0c;阳光明媚的天气、突如其来的暴风雨、缭绕的晨…

工时管理平台核心功能解析:你需要了解的

国内外主流的10款工时管理平台对比&#xff1a;PingCode、Worktile、Todoist、ClickUp、滴答清单、专注清单、一木清单、NarTick、Tweek、朝暮计划。 在选择合适的工时管理平台时&#xff0c;你是否感到挑战重重&#xff1f;市场上的各种选项似乎都声称能够提升效率和减轻管理负…

【SQL Server点滴积累】SQL Server 2016数据库邮件(Database Mail)功能故障的解决方法

今天和大家分享SQL Server 2016数据库邮件(Database Mail)功能故障的解决方法 故障现象&#xff1a; 在SQL Server 2016中配置完成数据库邮件(Database Mail)功能后&#xff0c;当你尝试发送测试邮件后&#xff0c;既收不到测试邮件&#xff0c;也不显示错误消息 KB3186435 -…

Python数值计算(11)——拉格朗日插值

本篇介绍一下多项式插值中&#xff0c;拉格朗日法的原理及其实现。 1. 一点数学知识 先引用数学背景。如果给定N个点&#xff0c;然后要求一个多项式通过这N个点&#xff0c;最简单直接的方式是列出线性方程求解&#xff0c;N个点可以确定N个未知量&#xff0c;则所求的拟合多…

下面关于枚举的描述正确的一项是?

A. 枚举中定义的每一个枚举项其类型都是String&#xff1b; B. 在Java中可以直接继承java.util.Enum类实现枚举类的定义&#xff1b; C. 利用枚举类中的values()方法可以取得全部的枚举项&#xff1b; D. 枚举中定义的构造方法只能够使用private权限声明&#xff1b; 答案选择…

springboot山东外事职业大学校园食堂点餐系统-计算机毕业设计源码10417

摘 要 近年来&#xff0c;随着国民收入的提高&#xff0c;各行业取得长足进步&#xff0c;也带动了互联网行业的快速发展&#xff0c;许多传统行业开始与互联网相结合&#xff0c;通过数字化转型打造新的发展生态。 本文针对山东外事大学校园食堂点餐系统的需求&#xff0c;基于…

Java内存区域与内存溢出异常详解

在Java编程中&#xff0c;理解Java虚拟机的内存布局及其管理机制对于开发高效、稳定的应用程序至关重要。Java虚拟机的内存主要分为几个运行时区域&#xff0c;这些区域各司其职&#xff0c;共同支撑起Java程序的运行。本文将详细探讨Java虚拟机的内存区域以及这些区域如何与内…

Yolov模型的使用及数据集准备(1)LabelImg的下载和使用

1、LabelImg下载&#xff1a; labelimg简单来说就是打标签用的软件&#xff0c;当需要使用自定义数据集进行模型训练时&#xff0c;往往需要使用该软件来打标签。 下载地址&#xff1a;GitHub - HumanSignal/labelImg 1.1下载之后对压缩包进行解压 2、打开电脑的anaconda pro…

MyBatis XML配置文件

目录 一、引入依赖 二、配置数据库的连接信息 三、实现持久层代码 3.1 添加mapper接口 3.2 添加UserInfoXMLMapper.xml 3.3 增删改查操作 3.3.1 增(insert) 3.3.2 删(delete) 3.3.3 改(update) 3.3.4 查(select) 本篇内容仍然衔接上篇内容&#xff0c;使用的代码及案…

8G 显存玩转书生大模型 Demo

创建可用环境 # 创建环境 conda create -n demo python3.10 -y # 激活环境 conda activate demo # 安装 torch conda install pytorch2.1.2 torchvision0.16.2 torchaudio2.1.2 pytorch-cuda12.1 -c pytorch -c nvidia -y # 安装其他依赖 pip install transformers4.38 pip in…

Moving Object Segmentation: All You Need Is SAM(and Flow) 论文详解

系列文章目录 文章目录 系列文章目录前言摘要1 引言2 相关工作3 SAM Preliminaries4 帧级分割Ⅰ&#xff1a;以流作为输入5 帧级分割Ⅱ&#xff1a;以流为提示6 序列级掩膜关联7 实验7.1 数据集7.2 评价指标7 .3 实施细节7.4 消融实验7.5 定量结果7 .定性可视化 8 结论致谢附录…

01 - 计算机组成原理与体系结构

文章目录 一&#xff0c;计算机系统硬件基本组成硬件软件 二&#xff0c;CPU的功能与组成功能组成运算器控制器 三&#xff0c;数据表示计算机的基本单位进制转换原码&#xff0c;反码&#xff0c;补码&#xff0c;移码数值表示范围浮点数表示 四&#xff0c;寻址五&#xff0c…

【Unity模型】古代亚洲建筑

在Unity Asset Store上&#xff0c;一款名为"Ancient Asian Buildings Pack"&#xff08;古代亚洲建筑包&#xff09;的3D模型资源包&#xff0c;为广大开发者和设计师提供了一个将古代亚洲建筑风格融入Unity项目的机会。本文将详细介绍这款资源包的特点、使用方式以…