UDP客户端和服务器

UDP客户端,也就是首先主动发送数据的一方,也就是发起服务请求的一方。

UDP服务器,也就是首先等待接收数据,并对接收的数据进行处理,返回计算结果的一方,也就是提供服务的一方。

在下面实验中使用到的函数

int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);
int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
int send(int s, const void *msg, size_t len, int flags);
in_addr_t inet_addr(const char *cp);
uint16_t htons(uint16_t hostshort);

 udp客户端测试

测试代码 

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>

#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

int main(int argc, char *argv[])
{
    int client_socket;
    client_socket = socket(AF_INET,SOCK_DGRAM,0);
    DEBUG_INFO("client_socket = %d",client_socket);

    struct sockaddr_in server_addr;
    server_addr.sin_port = htons(6600);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.0.5");
    char buf[100];
    snprintf(buf,sizeof(buf),"time=%d",time(NULL));

    DEBUG_INFO("server_addr %s:%d on socket %d\n",
                           inet_ntoa(server_addr.sin_addr),
                           htons(server_addr.sin_port),
                           client_socket);
    socklen_t addrlen = sizeof(server_addr);
    int send_len = sendto(client_socket,buf,strlen(buf),0,&server_addr,sizeof(server_addr));
    memset(buf,0,sizeof(buf));
    DEBUG_INFO("sendto %s:%d \n",
                           inet_ntoa(server_addr.sin_addr),
                           htons(server_addr.sin_port));
    int read_len = recvfrom(client_socket,buf,sizeof(buf),0,&server_addr,&addrlen);
    DEBUG_INFO("recvfrom %s:%d  -- %s\n",
                           inet_ntoa(server_addr.sin_addr),
                           htons(server_addr.sin_port),
                           buf);
    
    sleep(5);
    return 0;
}

UDP接收端(服务器)

执行代码:

  

实验解析 

 UDP客户端向192.168.0.5:6600 地址发送时间值,UDP接受端,也就是调试助手,返回一个字符串。然后UDP客户端等待5秒退出。这可以用来实现一个NTP服务器

UDP服务端 

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>

// #define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>

#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

int main(int argc, char *argv[])
{
    int server_socket;
    int res = 0;
    int on = 1;
    server_socket = socket(AF_INET,SOCK_DGRAM,0);
    DEBUG_INFO("server_socket = %d",server_socket);

    if(setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR,&on,sizeof(on)) < 0){
        perror("setsockopt");
        exit(-1);
    }

    struct sockaddr_in server_addr;
    server_addr.sin_port = htons(6600);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.0.11");

    res = bind(server_socket,(const struct sockaddr *)&server_addr,sizeof(server_addr));
    if(res == -1){
        perror("bind");
        return -1;
    }
    int len = 0;
    char buf[100];
    socklen_t addrlen;
    struct sockaddr_in client_server;
    while(1){
        memset(buf,0,sizeof(buf));
        memcpy(&client_server,&server_addr,sizeof(client_server));
        addrlen = sizeof(client_server);
        recvfrom(server_socket,buf,sizeof(buf),0,&client_server,&addrlen);
        DEBUG_INFO("buf = %s",buf);
        DEBUG_INFO("recfrom %s:%d  -- %s\n",
                           inet_ntoa(client_server.sin_addr),
                           htons(client_server.sin_port),
                           buf);
        addrlen = sizeof(client_server);
        sendto(server_socket,buf,strlen(buf),0,&client_server,addrlen);
    }
    
    sleep(5);
    return 0;
}

修改客户端中的IP地址为192.168.0.11,也就是虚拟机的IP地址

 实验解析:

服务器等待接收数据。客户端向服务端发送数据,服务器端接收数据后,将数据原样返回。然后服务端继续等待接收数据。客户端发送完毕后等待接收,接收到数据后睡眠5秒退出程序。

使用connect的客户端 

虽然UDP是无连接的,但是connect函数依然有效,它高速操作系统,默认从哪里接收数据,默认向谁发送数据。这样就可以使用read,wirte、send、recv这四个没有指定地址的函数来收发数据了。

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>

#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

int main(int argc, char *argv[])
{
    int client_socket;
    int res = 0;
    client_socket = socket(AF_INET,SOCK_DGRAM,0);
    DEBUG_INFO("client_socket = %d",client_socket);

    struct sockaddr_in remote_addr;
    remote_addr.sin_port = htons(6600);
    remote_addr.sin_family = AF_INET;
    remote_addr.sin_addr.s_addr = inet_addr("192.168.0.11");
    char buf[100];
    snprintf(buf,sizeof(buf),"time=%d",time(NULL));

    DEBUG_INFO("remote_addr %s:%d on socket %d\n",
                           inet_ntoa(remote_addr.sin_addr),
                           htons(remote_addr.sin_port),
                           client_socket);
    
    res = connect(client_socket,&remote_addr,sizeof(remote_addr));
    int send_len = send(client_socket,buf,strlen(buf),0);
    memset(buf,0,sizeof(buf));
    int read_len = recv(client_socket,buf,sizeof(buf),0);

    DEBUG_INFO("recv %s:%d  -- %s\n",
                           inet_ntoa(remote_addr.sin_addr),
                           htons(remote_addr.sin_port),
                           buf);
    
    sleep(5);
    return 0;
}

 测试结果:

既是客户端和也是服务端

如果一个客户端,偶尔也要提供服务的话,那么它绑定(bind)一个明确的本地端口是有必要的,这样别人就知道应该如何主动向它发起通讯了。下面是使用bind绑定本地端口的客户端代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>

#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

int main(int argc, char *argv[])
{
    int client_socket;
    int res = 0;
    client_socket = socket(AF_INET,SOCK_DGRAM,0);
    DEBUG_INFO("client_socket = %d",client_socket);

    struct sockaddr_in remote_addr;
    remote_addr.sin_port = htons(6600);
    remote_addr.sin_family = AF_INET;
    remote_addr.sin_addr.s_addr = inet_addr("192.168.0.11");

    DEBUG_INFO("INADDR_ANY = %d",INADDR_ANY);
    struct sockaddr_in local_addr;
    local_addr.sin_port = htons(6700);
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = INADDR_ANY;//inet_addr("192.168.0.11");

    res = bind(client_socket,(const struct sockaddr *)&local_addr,sizeof(local_addr));
    if(res == -1){
        perror("bind");
        return -1;
    }

    char buf[100];
    snprintf(buf,sizeof(buf),"time=%d",time(NULL));

    DEBUG_INFO("remote_addr %s:%d on socket %d\n",
                           inet_ntoa(remote_addr.sin_addr),
                           htons(remote_addr.sin_port),
                           client_socket);
    
    res = connect(client_socket,&remote_addr,sizeof(remote_addr));
    int send_len = send(client_socket,buf,strlen(buf),0);
    memset(buf,0,sizeof(buf));
    int read_len = recv(client_socket,buf,sizeof(buf),0);

    DEBUG_INFO("recv %s:%d  -- %s\n",
                           inet_ntoa(remote_addr.sin_addr),
                           htons(remote_addr.sin_port),
                           buf);
    
    sleep(5);
    return 0;
}

执行结果: 

 实验解析:

服务端使用前面的测试代码。这样通讯两端的IP和PORT就都是已知的了,这样比较适合新手,特别是两边都是经验不足的开发人员。防止思维混乱。

 

小结

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux进度条

Linux进度条 一.基本概念1.回车和换行2.缓冲区2.实现倒计时 二.进度条 一.基本概念 1.回车和换行 回车&#xff1a;指光标移到该行的起始位置&#xff08;\r&#xff09;。 换行&#xff1a;换到下一行&#xff08;\n&#xff09;。 在c语音里\n将回车和换行相结合了。 2.缓冲…

存在CSRF漏洞的CMS练习

前言 作者简介&#xff1a;不知名白帽&#xff0c;网络安全学习者。 博客主页&#xff1a;不知名白帽的博客_CSDN博客-网络安全,CTF,内网渗透领域博主 网络安全交流社区&#xff1a;https://bbs.csdn.net/forums/angluoanquan CMS 链接&#xff1a;https://pan.baidu.com/s/13F…

Windows操作系统安全加固

Windows操作系统安全加固 一、安全加固基本思路1.1、安全基线1.2、系统信息审查 二、Windows安全配置加固2.1、漏洞修复——补丁安装2.2、漏洞修复——端口封禁2.2.1、windows高危端口加固实践——封禁135端口对外开放 2.3、安全配置加固——账号口令 一、安全加固基本思路 1.…

LinuxI2C应用编程——访问EEPROM

文章目录 介绍读芯片手册代码编译运行 阅读博文&#xff1a;LinuxI2C应用编程——I2C-Tools的使用 介绍 EEPROM (Electrically Erasable Programmable read only memory)&#xff0c;指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。 读芯片手册 首先按如图…

cmake操作目录

目录 cmake如何使用子目录 demo cmake生成build目录结构 如果指定子目录编译文件名字(binaryDir) 如果指定子目录编译的路径(binaryDir) 子目录相关的作用域 demo 子目录中定义project cmake如何使用子目录 如果项目比较小的话,我们将所有源码文件放到一个目录里面是没…

java环境搭建2-idea安装激活

windows环境装Java开发环境与idea安装激活 安装jdk安装idea激活idea新建项目开启Java学习 java环境搭建2-idea安装激活 之前安装了wslLinux子环境的Java开发环境,但是再许多地方没有人使用vscode进行Java开发,因为环境配置很麻烦,还有各种插件. windows环境装Java开发环境与ide…

django-vue-admin curd_demo 快速crud教程

django-vue-admin curd_demo 快速crud教程 快速CRUD开发教程&#xff1a;https://bbs.django-vue-admin.com/article/9.html 如何在 env.py 文件配置Mysql数据库&#xff1a;https://bbs.django-vue-admin.com/question/4.html 导入导出配置教程&#xff1a;https://bbs.djang…

机器学习总览

机器学习 1.什么是机器学习&#xff1f; 机器学习是使计算机像人类一样学习与行动的科学&#xff0c;并通过观察与现实世界交互的形式向计算机提供数据和信息&#xff0c;从而随着时间的推移以自主的方式改善其学习。 通过经验提高某些任务性能的计算机程序。 人工智能>机器…

人工智能与Chat GPT

一本书全面掌握ChatGPT&#xff0c;既有向ChatGPT提问的技巧&#xff0c; 也有构建自己的ChatGPT模型的方法&#xff0c;涵盖开发背景、关联技术、使用方法、应用形式、实用案例等 人工智能是我们这个时代最热门的话题&#xff0c;人们既希望它能代替我们做一些工作&#xff0c…

tecplot360 只显示指定phase的设定体积分数的区域

tecplot360 只显示指定phase的设定体积分数的区域 到数入据抽取切面设定显示体积分数范围 参考1&#xff1a; Tecplot中如何提取水线面&#xff08;自由表面&#xff09;并绘图 参考2&#xff1a; 两相流计算中&#xff0c;如何用Tecplot提取水相断面平均物理量&#xff1f; …

HTTP 协议的基本格式

目录 1.基本格式 首行 请求报头 关于cookie 关于Referer 响应的报文 首行 关于状态码 1.基本格式 让我们来看看fiddler抓包的下的实际报文情况 首行 在http1.1中&#xff0c;有如下方法 POST、GET、HEAD、PUT、OPTIONS、DELETE、TRACE、CONNECT 在我们抓包遇到的环境中&…

【花雕】全国青少年机器人技术一级考试备考实操搭建手册8

随着科技的不断进步&#xff0c;机器人技术已经成为了一个重要的领域。在这个领域中&#xff0c;机械结构是机器人设计中至关重要的一部分&#xff0c;它决定了机器人的形态、运动方式和工作效率。对于青少年机器人爱好者来说&#xff0c;了解机械结构的基础知识&#xff0c;掌…

Stable Diffusion WebUI Ubuntu 22.04 LTS RTX2060 6G 极限显存出图

模型 默认选中 chilloutmix_Ni.safetensors&#xff0c;重启webui.sh进程 正向词 best quality, ultra high res, (photorealistic:1.4), 1girl, <lora:koreanDollLikeness_v15:1> ,<lora:yaeMikoRealistic_yaemikoMixed:1>, 反向词 paintings, sketches, (…

基于simulink使用光流法跟踪汽车(附源码)

一、前言 此示例演示如何使用光流估计在视频序列中检测和跟踪汽车。 二、模型 下图显示了使用光流跟踪汽车模型&#xff1a; 三、用光流结果跟踪汽车 该模型使用光流估计技术来估计视频序列的每一帧中的运动矢量。通过阈值化运动矢量&#xff0c;该模型创建包含移动对象斑点…

K8S安全管理

1 安全管理 1.1 安全框架 1.1.1 认证框架 学习目标 这一节&#xff0c;我们从 基础知识、认证流程、小结 三个方面来学习。 基础知识 资源操作 用户访问k8s业务应用的流程&#xff1a;方法一&#xff1a;无需api_server认证用户 -- ingress|service -- pod方法二&#xf…

什么事RPC并实现一个简单的RPC

1. 基本的RPC模型 主要介绍RPC是什么&#xff0c;基本的RPC代码&#xff0c;RPC与REST的区别&#xff0c;gRPC的使用 1.1 基本概念 RPC&#xff08;Remote Procedure Call&#xff09;远程过程调用&#xff0c;简单的理解是一个节点请求另一个节点提供的服务本地过程调用&am…

K8S的概念和基本应用

学习视频&#xff1a;Kubernetes基本概念和应用_哔哩哔哩_bilibili 零 . 架构概览 master节点&#xff1a;管理调度集群资源&#xff0c;一般为多节点构成&#xff0c;可以是物理机&#xff0c;也可以是虚拟机。worker节点&#xff1a;资源的提供者&#xff0c;一般为多节点构…

day03 重新学python——python函数

文章目录 一、python函数1.函数介绍2.函数的定义3.函数的参数4.函数的返回值5.函数的说明文档6.函数的嵌套调用7.变量的作用域8.综合案例 一、python函数 1.函数介绍 函数&#xff1a;即组织好的、课重复利用&#xff0c;用来实现特殊功能的代码段&#xff0c;这样可以提高代码…

揭秘python函数:编程艺术的核心力量(3)

文章目录 前言递归lambda表达式lambda 的参数形式无参数位置参数关键字参数缺省参数可变参数1.包裹位置传递2.包裹关键字传递 带判断条件的lambda表达式列表数据按照字典key的值进行排序 高阶函数的使用内置高阶函数1.map()2.reduce()3.filter() 前言 前面我们已经学习了 pyth…

uniapp 小程序 vue TypeError: Cannot read property ‘toString‘ of undefined

是因为对字符串使用toString的时候页面中的数据还没有加载 。错误代码&#xff1a; 可以使用 v-if 修改为&#xff1a;