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, ...)
#endifint 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, ...)
#endifint 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, ...)
#endifint 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, ...)
#endifint 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就都是已知的了,这样比较适合新手,特别是两边都是经验不足的开发人员。防止思维混乱。

 

小结

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql单表查询,排序,分组查询,运算符

CREATE TABLE emp (empno int(4) NOT NULL, --员工编号ename varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,--员工名字job varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,--员工工作mgr int(4) NULL DEFAULT NU…

【CSS】悬浮动画

文章目录 效果展示代码实现 效果展示 代码实现 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>一颗不甘坠落的流星</title></head><style type"text/css">.bth {/* 添加背景颜色 */backgr…

【周末闲谈】关于计算机的二三事

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 文章目录 前言一、第一台计算机的诞生&#x1f4bb;二、计算机发展历史&#x1f4da;第一代计算机&#x1f4bb;第二代计算机&#x1f4bb;第三代计算机&#x1f4bb;第四代计算机&#x…

chatgpt 与传统3D建模对比分析

推荐&#xff1a;将NSDT场景编辑器加入你的3D工具链 随着人工智能技术的发展&#xff0c;越来越多的领域正逐渐被AI模型所取代。ChatGPT作为一种自然语言处理技术&#xff0c;越来越为人们所熟悉。最近&#xff0c;一些3D建模领域的专家想知道ChatGPT是否可以取代传统的手动3D建…

单机模型并行最佳实践

单机模型并行最佳实践 模型并行在分布式训练技术中被广泛使用。 先前的帖子已经解释了如何使用DataParallel在多个 GPU 上训练神经网络&#xff1b; 此功能将相同的模型复制到所有 GPU&#xff0c;其中每个 GPU 消耗输入数据的不同分区。 尽管它可以极大地加快训练过程&#x…

JVM理论(二)类加载子系统

类加载流程 类加载流程 类加载器子系统负责从文件系统或者网络中加载class文件,class文件的文件头有特定的文件标识(CAFEBABE是JVM识别class文件是否合法的依据)classLoader只负责文件的加载,而执行引擎决定它是否被执行加载类的信息存放在运行时数据区的方法区中,方法区还包括…

从零配置 linux 开发环境

文章目录 目的效果图配置本地 Windows 主机好用工具WSLSSH 连接远程 Linux 开发机配置本机字体【in-prog】配置 vscode 远程连接 配置远程 Linux 主机zsh & oh-my-zsh配置 github 的 SSHneovimvundleinit.vim 文件 vim-plug.lua 文件 tmuxclangcpplint 目的 记录下我的开发…

idea配置本地maven保姆级教程

一、说在前面 idea默认会带有maven插件&#xff0c;原则上是可以不需要配置的。但有个缺点&#xff0c;他是把本地仓库直接安装在了系统盘里面&#xff0c;随着时间的推移&#xff0c;仓库越来越大&#xff0c;笔记本的压力会比较大。 本文是下载自己的maven包&#xff0c;集…

Linux命令(41)之top

Linux命令之top 1.top介绍 linux命令top是用来实时监测服务器资源的使用状况&#xff0c;包含进程、cpu、内存等等 2.top用法 top [参数] top常用参数 参数说明-d屏幕刷新时间间隔-i<time>设置刷新时间间隔-u<user>指定用户名-p<pid>指定进程号 top命令中…

运输层:TCP可靠传输

1.运输层&#xff1a;TCP可靠传输 笔记来源&#xff1a; 湖科大教书匠&#xff1a;TCP可靠传输 声明&#xff1a;该学习笔记来自湖科大教书匠&#xff0c;笔记仅做学习参考 TCP实现可靠传输的方式&#xff1a;以字节为单位的滑动窗口 发送方将31 ~ 41号报文段发送 假设32 ~ 3…

【人工智能与机器学习】基于卷积神经网络CNN的猫狗识别

文章目录 1 引言2 卷积神经网络概述2.1 卷积神经网络的背景介绍2.2 CNN的网络结构2.2.1 卷积层2.2.2 激活函数2.2.3 池化层2.2.4 全连接层 2.3 CNN的训练过程图解2.4 CNN的基本特征2.4.1 局部感知&#xff08;Local Connectivity&#xff09;2.4.2 参数共享(Parameter Sharing)…

深度学习实战41-基于LSTM-GRU模型搭建对糖尿病数据的预测与应用

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下深度学习实战41-基于LSTM-GRU模型搭建对糖尿病数据的预测与应用&#xff0c;本文将向大家介绍一种基于LSTM-GRU的糖尿病预测模型&#xff0c;包括模型的原理、中文糖尿病csv数据样例、利用PyTorch框架进行模型训练与…