socket编程---UDP

news2024/11/27 0:30:36

目录

一、socket

二、socket接口

1.流程原理

2.代码


前言

提示:这里可以添加本文要记录的大概内容:

        socket编程又称套接字编程,指进行网络通信程序的编写


提示:以下是本篇文章正文内容,下面案例可供参考

一、socket

网络通信就是将原始数据进行tcp/ip四层封装,通过网卡发送实现通信

网络通信分为:客户端、服务端。

        客户端:在客户这一端的进程,是主动发送请求的一端。客户端必须提前知道服务端的

                       地址与端口才能给服务端发送请求。

        服务端:提供服务的一端进程,是被动接收请求从而进行处理的一端。

二、socket接口

1.UDP通信流程原理

        sockaddr 是一个通用的套接字地址结构体,包含了一个地址族和地址数据,主要用来存储和传递套接字地址信息的。

        struct sockaddr { unsigned short sa_family; // 地址族 char sa_data[14]; // 地址信息 };

字节序转换接口---将主机字节序转化为网络字节序,字节序是存储多字节数据的

        uint16_t htons(uint16_val);        uint16_t ntons(uint16_val);     —   返回uint16_t数据

        uint32_t htonl(uint32_t val)        uint32_t ntonl(uint32_t val)     —   返回uint32_t数据

           所以2字节只能使用s进行转换,4字节只能属于l,这是指定的不能使用其他的

        

        in_addr_t inet_addr(const char* ip)    //将字符串IP地址转换为网络字节序整形IP地址

        const char* inet_ntoa(struct in_addr_t inet_addr;)         //将网络字节序整形IP地址转换

                                                                                                 为字符串IP地址

socket接口:

        int socket(int domain, int type, int protocol);     //创建socket,返回一个socket描述符

                domain:指定了套接字使用的协议        AF_INET:用IPv4网络协议

                       AF_INET6:用IPv6网络协议        AF_UNIX或AF_LOCAL:本地进程间通信

                type:指定套接字的类型

                        SOCK_STREAM:字节流传输通常用于TCP

                        SOCK_DGRAM:数据报传输通常用于UDP

                protocol:协议类型:通常设置为0

                        IPPROTO_TCP:TCP协议

                        IPPROTO_UDP:UDP协议

                返回值:失败返回-1

绑定地址接口

        int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen) //为创建的套接字绑定一个

                                                                                                          地址

                sockfd:创建套接字返回的描述符

                addr:指向sockaddr结构体指针,包含要绑定的地址信息

                addrlen:地址长度,取决于IP协议类型

                返回值:成功返回0,失败返回-1

发送数据接口:

        ssize_t sendto(

                                int sockfd,        //返回的套接字描述符                                                                                                                                                                                                          

                                void *buf,       //要发送数据的缓冲区指针

                                size_t len,,        //要发送的数据的长度--字节

                                int flags,            //通常设置为0-阻塞发送, MSG_DONTWAIT--非阻塞

                                struct sockaddr *_addr,        //一个指向sockaddr结构体指针,实际

                                                                                     使用中通常会使用 sockaddr_in(对于

                                                                                     IPv4)或 sockaddr_in6(对于IPv6)-

                                                                                     目的端地址信息

                                socklen_t addrlen        地址长度

                                )

                返回值:成功返回实际发送的数据长度,失败返回-1

接收数据接口

        ssize_t recvfrom(

                                int sockfd,

                                void *buf        //存放接收数据的缓冲区指针--空间地址

                                size_t len        //要接收数据的长度

                                int flags,        //

                                struct sockaddr *dest_addr,        //对端地址信息

                                socklen_t addrlen         //用于设定想要获取的地址长度

                                   )

                返回值:成功返回实际接收到的数据长度,失败返回-1

关闭套接字

        int close(int sockfd);

UDP协议:

        无连接、不可靠、面向数据报

        无连接:只要知道对方的地址就可以给对方发送数据

        不可靠:数据没有丢包检测,丢了就没了,且不保证有序

        面向数据包:传输以快为单位,有最大数据传输限制

其传输性能较高,多用于视频、音频等资源传输 

 

2.代码

服务端

// udp服务端程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>//htons字节序转换接口
#include <netinet/in.h>
#include <sys/socket.h>
#include <error.h>

int main(int argc, char *argv[]){
        //argc表示命令行参数个数。如果你在命令行中运行程序 ./myprogram arg1 arg2,那么 argc 的值将为3("./myprogram", arg1, arg2)
        //  ./udp_ 192.168.x.x 9000
    if(argc != 3){
        perror("./udp_ 172.23.62.176 9000");
    }
    char *ip_ = argv[1];        //argv[0]是程序的名称,argv[1]是第一个参数ip地址
    uint16_t port_ = atoi(argv[2]);     //将字符串转化整数
//创建套接字
    int socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(socketfd < 0){
        perror("socket error");
        return -1;
    }
//绑定地址
    struct sockaddr_in addr;    //IPv4的结构体
        //配置结构体
    addr.sin_family = AF_INET;//地址族
    addr.sin_port  = htons(port_);      //导入ip地址
    addr.sin_addr.s_addr = inet_addr(ip_);
    socklen_t addrlen = sizeof(struct sockaddr_in); //计算接收的地址长度
    int bind_ = bind(socketfd, (struct sockaddr*) &addr, addrlen);
    if(bind_ < 0){
        perror("bind error");
        return -1;
    }
    while(1){
//接收数据
        char buf[1024] = {0};
        struct sockaddr_in cliaddr;
        socklen_t addrlen = sizeof(struct sockaddr_in);
        ssize_t recv = recvfrom(socketfd, buf, 1023, 0, (struct sockaddr*)&cliaddr, &addrlen);
        if(recv < 0){
           perror("recvfrom error");
           return -1;
        }
        uint16_t cliport = ntohs(cliaddr.sin_port);
        const char *cliip = inet_ntoa(cliaddr.sin_addr);
        printf("client[%s:%d] say: %s\n",cliip, cliport, buf);

//发送数据
        printf("server say:");
        fflush(stdout);
        fgets(buf, 1023, stdin);//从键盘获取数据
        int send = sendto(socketfd, buf, strlen(buf), 0, (struct sockaddr*)&cliaddr, addrlen);
        if(send < 0){
           perror("sendto error");
           return -1;
        }

    }
//关闭套接字
    close(socketfd);


return 0;
}

客户端

#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <error.h>

#define CHECK_RET(r) if((r) == false){return -1;}

class UdpSocket {
        private:
                int _socketfd;  //定义一个套接字
        public:
                UdpSocket() :_socketfd(-1) {}
                ~UdpSocket() { Close(); }
                bool Socket() {//创建套接字
                        _socketfd =  socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                        if(_socketfd < 0){
                                perror("Socket error");
                                return false;
                        }
                        return true;
                }
                bool Bind(const std::string &ip, uint16_t port){        //绑定地址信息
                        struct sockaddr_in addr;
                        addr.sin_family = AF_INET;
                        addr.sin_port = htons(port);
                        addr.sin_addr.s_addr = inet_addr(ip.c_str());
                        socklen_t addrlen = sizeof(struct sockaddr_in);
                        int bend_ = bind(_socketfd, (struct sockaddr*)&addr, addrlen);
                        if(bend_ < 0){
                                perror("Bind error");
                                return false;
                        }
                        return true;
                }
                bool Send(const std::string &body, const std::string& ip, uint16_t port){       //发送数据
                        struct sockaddr_in addr;
                        addr.sin_family = AF_INET;
                        addr.sin_port = htons(port);
                        addr.sin_addr.s_addr = inet_addr(ip.c_str());
                        socklen_t addrlen = sizeof(struct sockaddr_in);
                        ssize_t send = sendto(_socketfd, body.c_str(), body.size(), 0, (struct sockaddr*)&addr, addrlen);
                        if(send < 0){
                                perror("Send error");
                                return false;
                        }
                        return true;
                }
                bool Recv(std::string* body, std::string *ip = NULL, uint16_t *port = NULL){    //接收数据
                        struct sockaddr_in addr;
                        socklen_t addrlen = sizeof(struct sockaddr_in);
                        char tmp[4096] = {0};
                        ssize_t recv = recvfrom(_socketfd, tmp, 4096, 0, (struct sockaddr*)&addr, &addrlen);
                        if(recv < 0){
                                perror("Recv error");
                                return false;
                        }
                        if(ip != NULL) *ip = inet_ntoa(addr.sin_addr);
                        if(port != NULL) *port = ntohs(addr.sin_port);
                        body->assign(tmp, recv);
                        return true;
                }
                bool Close(){   //关闭套接字
                        if(_socketfd < 0){
                                return true;
                        }
                        close(_socketfd);
                        _socketfd = -1;
                        return true;
                }
};


int main(int argc, char* argv[])
{
        if(argc != 3){
                std::cout <<"./udp 172.23.62.176 9000\n";
                return -1;
        }
        UdpSocket us;   //实例化对象
//创建套接字
        CHECK_RET(us.Socket());
        while(1){
                std::string buf;
                std::cout <<"client say:";
                fflush(stdout); //刷新输出缓冲区
                std::cin >> buf;//向缓冲区写入数据
//发送数据
                CHECK_RET(us.Send(buf, argv[1], std::stoi(argv[2])));
//接收数据
                buf.clear();    //清空缓冲区
                CHECK_RET(us.Recv(&buf));
                std::cout << "server say:" << buf << std::endl;
        }
//关闭套接字
        us.Close();
        return 0;
}

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

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

相关文章

R语言机器学习算法实战系列(十四): CatBoost分类算法+SHAP值 (categorical data gradient boosting)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍CatBoost的原理CatBoost的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割设置数据对象调节参数训练模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC Curv…

创建ODBC数据源SQLConfigDataSource函数的用法

网络上没有这个函数能实际落地的用法说明&#xff0c;我实践后整理一下&#xff1a; 1.头文件与额外依赖库&#xff1a; #include <odbcinst.h> #pragma comment(lib, "legacy_stdio_definitions.lib") 2.调用函数&#xff1a; if (!SQLConfigDataSourceW(…

HCIP-HarmonyOS Application Developer V1.0 笔记(一)

HarmonyOS的系统特性 硬件互助&#xff0c;资源共享;一次开发&#xff0c;多端部署;统一OS&#xff0c;弹性部署。 分布式软总线&#xff1a;分布式任务调度、分布式数据管理、分布式硬件虚拟化的基座 18N的独立设备 1个手机&#xff0c;8种设备&#xff08;车机&#xff0c…

upload-labs靶场Pass-21

upload-labs靶场Pass-21 本关上传方法众多&#xff0c;但是应该考察的是数组后缀绕过&#xff0c;所以我的上传围绕此展开 1.分析源码 $is_upload false; // 初始化上传状态为false $msg null; // 初始化消息变量为null// 检查是否有文件上传 if(!empty($_FILES[upload_fi…

【undefined reference to xxx】zookeeper库编译和安装 / sylar项目ubuntu20系统编译

最近学习sylar项目&#xff0c;编译项目时遇到链接库不匹配的问题&#xff0c;记录下自己解决问题过程&#xff0c;虽然过程很艰难&#xff0c;但还是解决了&#xff0c;以下内容供大家参考&#xff01; undefined reference to 问题分析 项目编译报错 /usr/bin/ld: ../lib/lib…

网络服务ssh

Linux 网络基础 一、知识回顾 网络地址&#xff1a;互联网协议地址&#xff08;IP地址&#xff09;为互联网上每一个网络或主机分配一个逻辑地址&#xff0c;IP地址工作在网络层。 ​ IP的分类&#xff1a;IPV4 IPV6 物理地址&#xff1a;物理地址&#xff08;MAC地址&…

Git获取本地仓库和常用指令

一、获取本地仓库 1&#xff09;在电脑的任意位置创建一个空目录&#xff08;例如test01&#xff09;作为我们的本地Git仓库 2&#xff09;进入这个目录中&#xff0c;点击右键打开Git bash窗口 3&#xff09;执行命令git init&#xff08;初始化当前目录为一个git仓库&…

解决报错:JDK版本不正确

加载maven过程中&#xff0c;控制台报错&#xff1a; Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.…

Webserver(1.8)操作函数

目录 文件属性操作函数access函数chmod函数chown函数truncate函数 目录操作函数mkdir函数rmdir函数rename函数chdir函数*getcwd函数 目录遍历函数*opendir函数*readdir函数closedir函数 dup、dup2函数dupdup2 fcntl函数 文件属性操作函数 access函数 判断某个文件是否有某个权…

解决ElasticSearch启动成功却无法在浏览器访问问题

目录 前言&#xff1a; 问题复现 &#xff1a; 解决问题&#xff1a; 1、修改sysctl.conf文件 2、在sysctl.conf文件增加这段东西 3、 然后保存退出&#xff0c;输入以下命令使其生效 结语&#xff1a; 前言&#xff1a; 这篇文章是小白我今天突然启动es&#xff0c;发现e…

【tomcat系列漏洞利用】

Tomcat 服务器是一个开源的轻量级Web应用服务器&#xff0c;在中小型系统和并发量小的场合下被普遍使用。主要组件&#xff1a;服务器Server&#xff0c;服务Service&#xff0c;连接器Connector、容器Container。连接器Connector和容器Container是Tomcat的核心。一个Container…

如何在Linux系统中使用SSH Key认证进行无密码登录

如何在Linux系统中使用SSH Key认证进行无密码登录 SSH Key认证简介 安装SSH 在Debian/Ubuntu系统中检查 在CentOS/RHEL系统中检查 生成SSH密钥 复制公钥到远程服务器 配置SSH服务端 编辑SSH配置文件 重启SSH服务 测试无密码登录 SSH Key认证的高级配置 设置密钥的权限 限制密…

开发流程初学者指南——需求分析

目录 从零开始理解需求分析什么是需求分析&#xff1f;需求分析的目标需求分析的基本原则需求分析的各个阶段需求分析的常用方法和工具编写需求文档总结 从零开始理解需求分析 需求分析是软件开发过程中不可或缺的一环&#xff0c;它帮助我们明确用户的需求&#xff0c;确保最…

MySQL Workbench工作台汉化

一、下载汉化包 通过百度网盘分享的文件&#xff1a;MySQL汉化包.rar 链接&#xff1a;https://pan.baidu.com/s/1PaJSU9dvVnQQWEESHSue5Q 二、汉化过程 注意&#xff1a;替换之前一定要记得把两个文件复制出来存着&#xff0c;防止替换失败修改了文件 找到MySQL的工作台da…

AI数字人应用场景超全解析(下)

​​一、AI数字人技术发展趋势 1、技术迭代与创新 AI数字人技术的迅猛进步&#xff0c;得益于人工智能、计算机图形学、动作捕捉及3D建模等领域的突破性进展。深度学习算法的优化&#xff0c;让AI数字人的语言理解和生成能力愈发自然&#xff0c;能够提供更加精准和个性化的交…

实战-任意文件下载

实战-任意文件下载 1、开局 开局一个弱口令&#xff0c;正常来讲我们一般是弱口令或者sql&#xff0c;或者未授权 那么这次运气比较好&#xff0c;直接弱口令进去了 直接访问看看有没有功能点&#xff0c;正常做测试我们一定要先找功能点 发现一个文件上传点&#xff0c;不…

激光自动对焦显微系统的原理和作用

原理 激光自动对焦原理&#xff1a; &#xff08;1&#xff09;激光自动对焦显微系统利用激光束的自聚焦特性实现精确焦点控制。在检测过程中&#xff0c;激光束通过照明针孔形成点光源&#xff0c;对样品表面进行扫描。 &#xff08;2&#xff09;被照射的点在探测针孔处成像…

【数据集】全球30弧秒网格人为热通量数据(AHF)

【数据集】全球30弧秒网格人为热通量数据(AHF) 数据概述数据下载数据处理基于Python绘制研究区内人为热通量数据(AHF)基于Python插值获取2020年人为热通量数据参考人为热通量(anthropogenic heat flux)数据是指由人类活动引起的地表热量变化的定量数据。这些数据通常用于…

电子邮件防泄密系统怎么选?分享五款邮件加密工具,好不好用你说的算!(宝藏篇)

电子邮件防泄密系统怎么选&#xff1f; 根据国际IT安全公司的研究&#xff0c;有70%的企业在担心电子邮件可能泄密&#xff0c;约一半员工承认曾错误发送不当或机密邮件。 尽管许多企业已经意识到了"邮件危机"&#xff0c;但仍未找到有效解决方案。 邮件发送不受控…

由小流氓从线下转线上看软件需求的第一性原理

在我上初、高中的时候&#xff0c;我们这里的治安是很差的&#xff0c;人称“匪城”&#xff01;街面上游荡着大大小小的流氓、二流子&#xff01;时不时干上一架&#xff0c;欺负一下老实人或做小生意的&#xff0c;我们这里市民真是不堪其扰&#xff01;很多电视剧将这些流氓…