服务端和客户端通信--UDP(含完整源代码)

2023-05-16

UDP通信实验

实验设备:   

目标系统:Windows

软件工具:vs2022/vc6/dev 

实验要求:

  1. 完成UDP服务端和客户端的程序编写;
  2. 分别实现UDP一对一通信和广播通信功能。

实验内容:-static-libgcc

一对一通信

服务器和客户端编程详细步骤:

1、加载/释放Winsock库,创建套接字(WSAStartup()/socket())。

加载方法:

WSADATA wsa;

/*初始化socket资源*/

if (WSAStartup(MAKEWORD(1,1),&wsa) != 0)

{

    return;   //代表失败

}

释放方法:

WSACleanup();

2、绑定IP地址、端口等信息到socket上

server.sin_family = AF_INET;

          server.sin_port = htons(12345);   本地监听端口

          server.sin_addr.s_addr = inet_addr(ip);

    

3、发送数据。用返回的套接字和客户端进行通信(函数recvfrom()sendto())  

  sendto():

int ret = recvfrom(int sockfd,void *buf,size_t len,0, struct sockaddr *to ,   int fromlen);

第一个参数为服务端的udp监听套接字

第二个参数为发送数据的缓冲区

第三个参数为缓存区的大小

第四个参数一般为0;

第五个参数一般为:记录地址信息,ip信息的结构体 。

第六个参数为:第五个参数的大小。

返回值:成功返回实际发送出去的信息的字节数,失败返回-1

recvfrom():

int ret = recvfrom(int sockfd,void *buf,size_t len,0, struct sockaddr *from,socket_t *fromlen);

第一个参数为服务端的udp监听套接字

第二个参数为接收数据的缓冲区

第三个参数为缓存区的大小

第四个参数一般为0;

第五个参数一般为:记录地址信息,ip信息的结构体 。

第六个参数为:第五个参数的大小,取地址。

返回值:成功返回接收到的信息的字节数,失败返回-1

服务端: 等待客户端接入.char buf[1024].

接收数据:recvfrom(Command_Sock,buf, …)

发送数据:sendto(Command_Sock,buf, …)

客户端: 请求与服务端连接.char buf[1024].

            发送数据:sendto(Client_Sock,buf, …)

          或

           接收数据:recvfrom(Client_Sock,buf, …)

4、关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。

closesocket(Listen_Sock)

closesocket(Command_Sock)

注意:在dev里面编译会出现报错,需要在项目管理—参数—添加libws2_32.a动态库,该库在C:\Program Files (x86)\Dev-Cpp\MinGW64\x86_64-w64-mingw32\lib\libws2_32.a路径下。

代码执行结果

 

服务器端完整代码

 

#include<stdio.h>

#include<stdlib.h>

#include<Winsock2.h>

int main (int agrc,char*argv[])

{

     SOCKET socket1;

     WSADATA wsaData;

     int ErrorCode;

     if(WSAStartup(MAKEWORD(2,1),&wsaData))// windows socket dll;

     {

        printf("Winsock启动失败!!\n");

        WSACleanup();

        return 0;

     }

   

     printf("Winsock start...\n");

     const char* ip="127.0.0.1";

     struct sockaddr_in server;

     int len = sizeof(server);

     server.sin_family = AF_INET;

     server.sin_port = htons(12345); 

     server.sin_addr.s_addr = inet_addr(ip);

   

     socket1 = socket(AF_INET,SOCK_DGRAM,0);

     while (1)

     {

        char buffer[1024] = "/0";

        printf("请输入要发送的信息:\n");

        scanf("%s",buffer);

        //printf("%s",buffer);

        if(strcmp(buffer,"bye")==0)

        {

           printf("exit,bye!!\n");

           Sleep(100);

           closesocket(socket1);

           break;

        }

      

        if(sendto(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&server,len)!=SOCKET_ERROR)

        {

            printf("发送完毕\n");

            Sleep(100);

            if(recvfrom(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&server,&len) != SOCKET_ERROR)

                printf("recevie from server: %s\n",buffer);                                          

        } 

     }

     closesocket(socket1);

     system("pause");

     return 0;

}

客户端完整代码

#include<stdio.h>

#include<stdlib.h>

#include<Winsock2.h>

int main (int agrc,char*argv[])

{

     SOCKET socket1;

     WSADATA wsaData;

     int ErrorCode;

     if(WSAStartup(MAKEWORD(2,1),&wsaData))// windows socket dll;

     {

        printf("Winsock启动失败!!\n");

        WSACleanup();

        return 0;

     }

   

     printf("Winsock start...\n");

     struct sockaddr_in local;

     struct sockaddr_in client;

     int len = sizeof(client);

     local.sin_family = AF_INET;

     local.sin_port = htons(12345);  //the port need listened

     local.sin_addr.s_addr = INADDR_ANY; //localhost

   

     socket1 = socket(AF_INET,SOCK_DGRAM,0);

     bind(socket1,(struct sockaddr*)&local,sizeof(local));

   

     while (1)

     {

        char buffer[1024] = "/0";

        printf("等待来自服务器发送的信息:\n");

        if(recvfrom(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&client,&len) != SOCKET_ERROR)

        {

                printf("接收到的信息为: [%s]---%s\n",inet_ntoa(client.sin_addr),buffer);

                //send sth to the client

                sendto(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&client,len);

        }                                            

     }

     closesocket(socket1);

     system("pause");

     return 0;

}

UDP广播通信

服务器和客户端编程详细步骤:

分析

广播通信是一对多的通信方式,会将消息分发给整个局域网内的所有主机,客户端需要绑定服务端广播使用的端口才能够接收到广播消息。广播地址以192.168.22.3网段为例:192.168.22.255 代表该网段的广播地址,发送给该地址的数据包被所有主机接收。

sendto("你好",192.168.22.255);

发送端

  1. 建立套接字;
  2. 设置该套接字允许进行广播;

     3、将数据发送到广播地址中:sendto(buf,192.168.22.255);

     4、关闭

接收端(服务器)

  1. 建立套接字;
  2. 绑定广播ip地址(192.168.22.255)和端口号9999
  3. 接收数据
  4. 关闭

具体实现过程

广播发送端

1创建数据报套接字 UDP

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

2、设置socketfd套接字文件描述符的属性为 广播 。

int on=1;

setsockopt(sockfd , SOL_SOCKET,SO_BROADCAST,&on, sizeof(on));

3、发送数据 ,指定接收方为广播地址

struct sockaddr_in sendAddr;

sendAddr.sin_family = AF_INET;

sendAddr.sin_port = htons(9999);

sendAddr.sin_addr.s_addr = inet_addr("192.168.22.255");

sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&sendAddr,sizeof(sendAddr));

4、关闭

close();

广播接收方(服务器端)

1创建用户数据报套接字

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

2、绑定(192.168.14.255)广播IP地址和端口号 (10000)

注意:绑定的端口必须和发送方指定的端口相同

struct sockaddr_in ownAddr;

ownAddr.sin_family = AF_INET;

ownAddr.sin_port = htons(10000);

ownAddr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY(0.0.0.0) 代表本机所有的地址

3、接收数据


recvfrom;  

4、关闭套接字


close();  

  

源代码:

发送端

#include <stdio.h>

#include <unistd.h>

#include <string.h>


#include <Winsock2.h>  

#include <windows.h>

 

#define GUANG_IP  "192.168.22.255"

#define GUANG_PORT   9999

int main()

{

    //建立套接字

    int socket_fd = socket(AF_INET,SOCK_DGRAM,0);

    if(socket_fd < 0)

    {

       perror("sokcet fail");

       return -1;

    }

   

   

    //设置广播属性

    int on=1;

    setsockopt(socket_fd , SOL_SOCKET,SO_BROADCAST,&on, sizeof(on)); 

   

    //给广播地址发送数据

    struct sockaddr_in send_addr;

    send_addr.sin_family = AF_INET;

    send_addr.sin_port = htons(GUANG_PORT);

    send_addr.sin_addr.s_addr = inet_addr(GUANG_IP);//广播地址

   

    char buf[1024] = {0};

    while(1)

    {  

       bzero(buf,sizeof(buf));

       scanf("%s",buf);

       //发送的是实际的长度

       sendto(socket_fd,buf,strlen(buf),0,(struct sockaddr *)&send_addr,sizeof(send_addr));

    }

   

    //关闭套接字

    close(socket_fd);

}

接收端

#include <stdio.h>

#include <unistd.h>

#include <string.h>


#include <Winsock2.h>  

#include <windows.h>

#define GUANG_IP  "192.168.22.255"

#define GUANG_PORT   9999

int main()

{

    //建立套接字

    int socket_fd = socket(AF_INET,SOCK_DGRAM,0);

    if(socket_fd < 0)

    {

       perror("sokcet fail");

       return -1;

    }

   

    //绑定广播地址

    struct sockaddr_in my_addr;

    my_addr.sin_family = AF_INET;

    my_addr.sin_port = htons(GUANG_PORT);

    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY本机任意IP地址--常用方法

    bind(socket_fd,(struct sockaddr *)&my_addr,sizeof(my_addr));

   

    char buf[1024] = {0};

    int ret;

    struct sockaddr_in recv_addr;

    socklen_t addrlen = sizeof(recv_addr);

    while(1)

    {  

       bzero(buf,sizeof(buf));//清空缓冲区

       ret = recvfrom(socket_fd,buf,sizeof(buf),0,(struct sockaddr *)&recv_addr,&addrlen);

       char *ip = inet_ntoa(recv_addr.sin_addr);

       int port = ntohs(recv_addr.sin_port);

       printf("[ip:%s port:%d] buf:%s ret:%d\n",ip,port,buf,ret);

    }

   

    //关闭套接字

    close(socket_fd);

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

服务端和客户端通信--UDP(含完整源代码) 的相关文章

  • leetcode:21合并两个有序连表——slist

    思路分析 链表 xff1a 头节点为空 xff0c 每个节点有一个指针 xff0c 指向下一个节点的地址 俩链表节点之间比较 xff0c 用遍历 96 96 for xff0c 因为是list xff0c 可以直接通过迭代器 xff08 指
  • leetcode:53最大子数组和

    思路分析 有2个变量是一直变化的 1 最大集合的第一个元素 2 存放最大的变量 0 变量初始化 span class token keyword int span res span class token operator 61 span
  • Ubuntu安装docker及出现问题解决

    Ubuntu安装docker及出现问题解决 文章目录 Ubuntu安装docker及出现问题解决一 安装docker二 解决docker安装成功后 xff0c docker命令无法正常使用的问题 一 安装docker docker的安装可参
  • stl大全

    什么是STL xff1f 大佬 xff1a 为什么C 43 43 比C更受人欢迎呢 xff1f 除了C 43 43 的编译令人感到更舒适 xff0c C 43 43 的标准模板库 xff08 STL xff09 也占了很重要的原因 当你还在
  • input 图片上传

    使用 在vue项目中使用input上传图片给后台时 xff0c 需要对图片文件流和请求头进行一些处理 1 获取上传图片文件流 span class token tag span class token tag span class toke
  • Unix环境高级编程代码(实时更新)

    实例1 3 列出一个目录中所有文件 xff08 ls c xff09 include 34 apue h 34 include lt dirent h gt int main int argc char argv DIR dp struct
  • ROS入门(二):launch文件解析

    ROS入门 xff08 二 xff09 xff1a launch文件解析 文章目录 ROS入门 xff08 二 xff09 xff1a launch文件解析一 launch文件的运行二 launch文件格式1 浏览顺序 xff08 Eval
  • RLException: [**] is neither a launch file in package [**] nor is [**] a launch file name,.......

    按照网上现有对这个问题的解决方法 xff1a 方法1 xff0c 在工作空间下source 方法2 xff1a 对其进行路径添加 这个问题的来源还有一种来源 xff0c 你得确定你在终端运行的这个launch文件名是否写对 xff0c 打开
  • Linux 安装node.js和npm教程

    第一步 xff1a 去node js官网下载安装包 或者直接 wget https nodejs org dist v10 15 0 node v10 15 0 linux x64 tar xz 第二步 xff1a 解压 tar xf no
  • could not establish connection to “hostname”

    解决方案 Try to delete the fingerprint a single line that corresponds to this particular connection not the whole file saved
  • 基于UCOSIII的环境检测项目

    基于UCOSIII的环境检测项目 运用STM32F103C8T6开发板为项目核心板 xff0c 并加入UCOSIII实时操作系统 在操作系统基础上 xff0c 搭配外围传感器实现基于STM32环境检测项目开发 主要运用库函数在操作系统基础上
  • 进程与线程

    进程与线程 讲线程之前要了解 xff1a 进程间的通信 xff08 Inter Process Communication IPC xff1a 理论上 xff0c 进程之间是独立的 xff0c 但实际上往往是多个进程之间的互相配合完成复杂的
  • STM32的八种工作模式

    一 模式介绍 STM32单片机具有高性能 低成本 低功耗的优点 xff0c 与它打交道就必须先了解它的几种工作模式 xff0c 它共有八种IO口模式 xff0c 分别是 xff1a 模拟输入 浮空输入 上拉输入 下拉输入 开漏输出 推挽输出
  • matlab学习笔记

    matlab笔记 上课期间自己整理的一系列matlab相关用法的笔记 xff0c 自认为也并不非常有条理 xff0c 但还是囤放在这里 xff0c 供需要的人查阅 取用 写在前面 help 43 函数名 xff1a 查找某函数的使用方法lo
  • 计算机组成原理——总线

    一 总线概述 1 xff0e 基本概念 xff08 1 xff09 总线简图 每个总线可能由很多根信号线组成 xff08 2 xff09 总线的物理实现 如上图 xff0c 4根信号线组成 一根 总线 xff0c 所有硬件部件都可以通过这根
  • 计算物理学复习笔记(一) 连续随机变量的抽样(直接、变换抽样,三类舍选法)

    文章目录 前言 前置知识一 直接抽样法二 变换抽样法三 舍选法1 第一类舍选法2 第二类舍选法3 第三类舍选法 总结 前言 使用教材 xff1a 马文淦 计算物理学 xff0c 限于篇幅 xff0c 这本书上部分知识写得并不十分详细 xff
  • Keil MDK配置ARM汇编/C语言混合开发环境

    Keil MDK配置ARM开发环境 1 安装Keil MDK 安装方法这里不再说明 xff0c 懂得都懂 xff01 x1f436 2 安装ARM开发包 在Keil MDK5之后 xff0c 不再原生支持ARM7 9 xff0c 需要自行安
  • ESP8266初学(一) 遇问题大全及解决方案(持续更新)

    最近开始学习wifi模块 xff0c 谁知一开始用PC连接调试wifi模块就遇到了很多问题 一 输入指令后没有反应 刚起步就头大 快乐地接好各种接口各种线 xff0c 连上电脑发现它冒蓝光光了 xff0c 好耶 xff01 然后兴致勃勃打开
  • PTA实验题:6-4 派生类的定义和使用 (10 分)

    按要求完成下面的程序 xff1a 1 定义一个Animal类 xff0c 包含一个void类型的无参的speak方法 xff0c 输出 animal language 2 定义一个Cat类 xff0c 公有继承自Animal类 xff0c
  • 模块学习(一)——编码电机

    想实现对电机的测速 xff0c 因此开始接触编码电机 此次采用的是RS365编码器电机 一 编码电机的初步了解 通过编码电机可以测出速度 常见一般编码电机分成两种 xff0c 一是光电编码器 xff0c 另一个是霍尔编码器 有六个接口 xf

随机推荐

  • nuxt如何处理用户登录状态持久化:nuxtServerInit 页面渲染前的store处理

    在一般的vue cli项目中 xff0c 我们可以用vuex persistedstate xff0c 它可以使vuex的状态持久化 xff0c 页面刷新都不会丢失 xff0c 原理当然是localStorage啦 xff01 当然也可以使
  • C语言查找字符

    C语言查找字符 相关文章路径 xff1a C语言求字符串的长度 gt C语言字符串的复制 gt C语言的字符串的联接 gt C语言字符串的比较 gt C语言查找字符 gt C语言BF算法 gt C语言输出字符串 gt C语言输入字符串 C
  • CPU、MPU、MCU、SOC的概念和区别

    概念 1 cpu cpu central processing unit 是一台计算机的运算核心和控制核心 xff0c CPU由运算器 控制器和寄存器以及实现他们联系的数据 控制总线构成 xff0c cpu典型的三级流水线操作是取值 译码
  • VScode报错:undefined reference to ‘WinMain’ collect2.exe: error: ld returned 1 exit status

    这是因为vs code并不会你点击了运行后就自动保存 xff0c 需要自己Ctrl 43 s保存一下 没保存显示一个圆点
  • 解决Realsense摄像头插着开机后,需要重新插拔程序才能正常工作

    安装 uhubctl 的过程 span class token function sudo span span class token function apt get span span class token function inst
  • Jetson TX2 刷机

    文章目录 准备工作1 host端 xff08 ubuntu xff09 配置2 连接线3 安装 NVIDIA SDK Manager 开始刷机STEP1STEP2STEP3STEP4 准备工作 1 host端 xff08 ubuntu xf
  • 链表头结点的插入和删除

    看了不少博客 xff0c 大都讲的比较详细到关于链表节点的删除和插入 xff0c 但因为没找到相关的头结点插入和删除的博客 xff0c 所以打算自己写一下方便大家查阅 下面是已经给出的链表的抽象数据结构 然后 然后下面是定义的插入结点的构造
  • gazebo无人机仿真显示:failsafe enabled: no rc

    修改qgc地面站参数 COM RC IN MODE 更改为 34 Joystick No RC Checks 34 这允许操纵杆输入并禁用 RC 输入检查 NAV RCL ACT to 34 Disabled 34 这可确保在没有无线遥控的
  • 力扣77组合(c++)

    力扣77组合 c 43 43 力扣题目链接 思路 这是一道经典的回溯算法题 xff0c 回溯法解决的问题都可以抽象为树形结构 xff08 N叉树 xff09 xff0c 我们可以通过树形结构来理解回溯算法 那么我把组合问题抽象为如下树形结构
  • 我的创作纪念日

    x1f36c 博主介绍 x1f468 x1f393 博主介绍 xff1a 大家好 xff0c 我是 PowerShell xff0c 很高兴认识大家 主攻领域 xff1a 渗透领域 数据通信 通讯安全 web安全 面试分析 x1f389 点
  • IDEA创建一个springboot项目教程(过程中各种报错解决)

    是不是不知道如何创建一个springboot项目 xff1f 是不是创建项目总是失败 xff1f 今天手把手带你创建一个springboot项目 配置maven 我们在创建一个springboot项目时一定要先配好maven配置文件sett
  • PHPWord相关

    phpword中进行换行操作 xff1a re 39 work experience 39 61 str replace array 34 r 34 34 n 34 34 r n 34 34 lt w br gt 34 re 39 work
  • 文件操作fwrite写txt文件乱码怎么办,我这里有方法解决

    很多大一新生到了期末做课设时 xff0c 遇到文件操作 总会有人不明白为什么写入的内容会乱码 先引入一些知识 xff1b 文件有二进制文件 xff0c 文本文件 二进制文件是按内存写入的 xff1b 文本文件是按格式写入的 xff1b 因此
  • DC电源口实物VCC引脚和GND引脚

    从后往前看 xff08 前面是电源线插进来的地方 xff09 xff0c 前面和左面是GND xff0c 后面是VCC
  • Docker入门

    前言 这就是一个简单的docker入门 因为可能现在用的少 笔者后面就有了些许草率 Docker 一篇入门 这里有阮一峰老师的docker简介传送门 这里有个语雀大佬的笔记传送门 后序也可以参考这个文章 一 Docker 简介 1 基本概述
  • java枚举类详解

    一 初始枚举 枚举类型是Java 5中新增特性的一部分 xff0c 它是一种特殊的数据类型 xff0c 之所以特殊是因为它既是一种类 class 类型却又比类类型多了些特殊的约束 xff0c 但是这些约束的存在也造就了枚举类型的简洁性 安全
  • vue报错:Component name “xxx“ should always be multi-word

    这个问题困扰我这个菜鸡很久了 xff0c 当我run serve的时候总是会报错Component name xxx should always be multi word 一直以为是命名的问题 xff0c 可是改了又改还是不行 xff0c
  • C语言学习---通过指针形参修改实参的值/交换两个数字的值---原理深究

    C语言学习 通过指针形参修改实参的值 交换两个数字的值 原理深究 要通过函数调用修改实参的值 xff0c 首先我们要明白函数调用过程中的传参方式与返回方式 xff1a 传参方式 xff1a 在c语言里面 xff0c 所有的参数传递都是单向的
  • [已解决]Git无法连接远程

    如果你是开了代理的情况下 xff0c Git失效了可以参考我的解决方法 今天Git忽然抽风了 xff0c 显示连接失败 正在获取 origin kex exchange identification Connection closed by
  • 服务端和客户端通信--UDP(含完整源代码)

    UDP通信实验 实验设备 xff1a 目标系统 xff1a Windows 软件工具 xff1a vs2022 vc6 dev 实验要求 xff1a 完成UDP服务端和客户端的程序编写 xff1b 分别实现UDP一对一通信和广播通信功能 实