首页 > 编程语言 >网络编程中UDP协议通信

网络编程中UDP协议通信

时间:2024-06-05 19:55:18浏览次数:32  
标签:UDP struct 编程 通信 tm 缓冲区 接字 include

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
//使用前应设置端口号  通信时应保持一致
#define DESTHOST 60000

用于发送信息使用的函数接口

注:创建套接字时第二个参数应指定UDP协议指定的宏

/*******************************************************************
 *
 *	函数名称:	sendinfo
 *	函数功能:   使用UDP协议向指定IP发送信息的线程
 *	函数参数:
 *	返回结果:
 * 	注意事项:   None
 * 	函数作者:   [email protected]
 *	创建日期:   2024/06/05
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
void *sendinfo(void *arg)
{
	// 1.创建udp套接字
	int socketfd = socket(AF_INET,	  // IPV4指定参数
						  SOCK_DGRAM, // UDP指定参数
						  0);
	if (socketfd == -1) // 错误处理,套接字文件描述符为-1,表示创建失败
	{
		fprintf(stderr, "udp socket error,errno:%d,%s\n", errno, strerror(errno));
		exit(1);
	}

	// 2.定义数据缓冲区
	char sendbuf[128] = {0};									  // 用于储存想要发送的数据缓冲区
	char timenow[128] = {0};									  // 用于储存发送数据的时间缓冲区
	char ipbuf[30] = {0};										  // 定义缓冲区储存IP地址
	struct tm *now = (struct tm *)calloc(1, sizeof(struct tm *)); // 用于记录当前时间的结构体
	time_t data;												  // 记录标准秒数
	struct sockaddr_in destaddr;								  // 定义记录套接字目标主机信息的结构体
	destaddr.sin_family = AF_INET;								  // IPV4指定参数
	destaddr.sin_port = htons(DESTHOST);						  // 服务器端口,必须转换为网络字节序

	while (1)
	{
		printf("请输入想要发送的消息:\n");
		data = time(NULL);										// 获取标准秒数
		now = localtime(&data);									// 将标准秒数转换成指定格式存入结构体中
		sprintf(timenow, "%04d年%02d月%02d日 %02d:%02d:%02d  ", // 将指定格式的时间写入缓冲区中
				now->tm_year + 1900,
				now->tm_mon + 1,
				now->tm_mday,
				now->tm_hour,
				now->tm_min,
				now->tm_sec);
		scanf("%s", sendbuf);	  // 将想要发送的数据存入缓冲区中
		strcat(timenow, sendbuf); // 将日期和发送的信息拼接存入timenow缓冲区
		printf("%s\n", timenow);
		printf("请输入想要通信的IP地址(例:192.168.64.xxx):\n");
		scanf("%s", ipbuf); // 从终端输入想要通信的目标主机IP
		destaddr.sin_addr.s_addr = inet_addr(ipbuf);
		// 向目标主机发送信息
		sendto(socketfd,					 // 套接字文件描述符
			   timenow,						 // 想要发送的信息缓冲区
			   sizeof(timenow),				 // 缓冲区大小
			   0,							 // 发送信息的标志,默认为0
			   (struct sockaddr *)&destaddr, // UDP指定目标主机IP信息
			   sizeof(destaddr));			 // 主机IP结构体的大小
	}

	return 0;
}

用于接收信息的函数接口

注:创建套接字时第二个参数应指定UDP协议指定的宏

/*******************************************************************
 *
 *	函数名称:	recvinfo
 *	函数功能:   使用UDP协议接收信息的线程
 *	函数参数:
 *	返回结果:
 * 	注意事项:   None
 * 	函数作者:   [email protected]
 *	创建日期:   2024/06/05
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
void *recvinfo(void *arg)
{
	// 1.创建udp套接字
	int socketfd = socket(AF_INET,	  // IPV4指定参数
						  SOCK_DGRAM, // UDP指定参数
						  0);
	if (socketfd == -1) // 错误处理,套接字文件描述符为-1,表示创建失败
	{
		fprintf(stderr, "udp socket error,errno:%d,%s\n", errno, strerror(errno));
		exit(1);
	}
	// 2.创建接收数据缓冲区
	char recvbuf[128] = {0};
	struct sockaddr_in clent;				   // 定义接收套接字源信的结构体
	clent.sin_family = AF_INET;				   // IPV4指定参数
	clent.sin_port = htons(DESTHOST);		   // 服务器端口,必须转换为网络字节序
	clent.sin_addr.s_addr = htonl(INADDR_ANY); // 选择接收所有IP来源的信息

	// 3.将套接字与接收结构体进行绑定
	bind(socketfd, (struct sockaddr *)&clent, sizeof(struct sockaddr));
	struct sockaddr_in sourceaddr;
	socklen_t le = sizeof(sourceaddr);

	while (1)
	{
		recvfrom(socketfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&sourceaddr, &le);
		printf("[%s]:%s\n", inet_ntoa(sourceaddr.sin_addr), recvbuf);
		bzero(recvbuf, sizeof(recvbuf));
	}
}

主函数中的测试程序

两个函数应该同时运行,recvfrom()函数默认会阻塞,并且不应该影响其他任务,所以使用两个线程运行

int main()
{
	// 2.创建接收数据的线程
	pthread_t recvthread;
	pthread_create(&recvthread, NULL, recvinfo, NULL);

	// 1.创建发送数据的线程
	pthread_t sendthread;
	pthread_create(&sendthread, NULL, sendinfo, NULL);

	// 3.等待子线程结束并释放资源
	pthread_join(sendthread, NULL);
	pthread_join(recvthread, NULL);

	return 0;
}

编译指令:

 gcc "udp_pathname".c -o "udp_pathname" -pthread

运行指令:

./"udp_pathname"

以下为发送消息

image

以下为指定ip所接收到的信息

image

注意事项:

1.UDP协议通信是一种面向无连接,不可靠的通信方式,所以在使用前应获得对方IP,以及端口号。
2.使用该协议发送信息,当对方不在线时,会出现丢包情况,所以使用前请确保双方同时在线

标签:UDP,struct,编程,通信,tm,缓冲区,接字,include
From: https://www.cnblogs.com/lzlwyh/p/18233668

相关文章

  • ### 探索Java开发中的关键问题:从性能优化到安全性,全方位提升你的编程技能
    在这篇文章中,我们将深入探讨Java开发中最受关注的关键问题,并提供实用的解决方案,帮助你在编程之路上不断精进。以下是我们将覆盖的主要内容:1. **性能优化**     * **垃圾回收(GarbageCollection)**    * **问题**:不同垃圾回收器的选择和调优。......
  • 进程间的通信(信号通信)
    进程间的通信(信号通信)进程的信号通信是操作系统中进程间通信(IPC)的一种方式,它允许一个进程向另一个进程发送一个信号,从而改变另一个进程的状态或执行某个操作。信号是异步的,意味着信号的发送和接收并不依赖于接收进程的执行状态。信号通信的基本概念信号类型:操作系统定义了一系......
  • TCP协议网络通信
    TCP协议网络通信目录TCP协议网络通信头文件/宏定义客户端服务器验证结果客户端服务器头文件/宏定义#include<stdio.h>#include<stdlib.h>#include<string.h>#include<arpa/inet.h>#include<netinet/in.h>#include<sys/types.h>#include<sys/socket.h>#includ......
  • TCP和UDP
    TCP和UDPTCP的可靠性特性序列号(Sequencing):TCP为每个传输的数据段分配一个唯一的序列号,接收端可以根据这些序列号重新组装数据。确认与重传(AcknowledgmentandRetransmission):TCP使用确认机制来确认数据段是否成功到达。如果接收端没有收到某个数据段,发送端会重传它。流量控......
  • 程序分享--常见算法/编程面试题:整数转罗马数字
    关注我,持续分享逻辑思维&管理思维&面试题;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;推荐专栏《10天学会使用asp.net编程AI大模型》,目前已完成所有内容,持续上传中。一顿烧烤不到的费用,让人能紧跟时代的浪潮。从普通网站,到公众号、小程序,再到AI大模型网站。干货满满......
  • 提供高达 58 Gbps 的收发器速率、AGFA023R31C2E1VB/AGFA023R31C2I1V/AGFA023R31C2I2VB
    Agilex7FPGA产品系列包括业界最高性能的FPGA和SoC。英特尔Agilex7FPGA和SoC由高性能的F系列、I系列和M系列FPGA组成,为要求最高的应用提供了一系列的高级功能。•具有业界最高数据速率的收发器—高达116Gbps•业界首创的PCIExpress*(PCIe*)5.0和ComputeExpressLi......
  • STM32学习(USART通信协议)
            本文章时本人根据江科大视频所记录的笔记,希望对大家的学习能提供帮助。1.通信接口通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统(stm32内部芯片无法得到的数据,需要连接外部芯片获取)通信协议:制定通信的规则,通信双方按照协议规则进行数据收发USAR......
  • 简化stream流等工具类(函数式编程的应用案例)
    操作集合publicclassCollectionUtils{publicstaticbooleancontainsAny(Objectsource,Object...targets){returnasList(targets).contains(source);}publicstaticbooleanisAnyEmpty(Collection<?>...collections){retu......
  • 接上篇,客户端实现,图形界面编程,利用socket和UCP/TCP编写,客户端和服务器端程序可以进行
     1.项目结构 1.1基本架构本项目采用基于Java的`Swing`库进行图形界面开发,并使用`Socket`进行网络通信。项目包名为`org.example.tcp`。 1.2模块划分项目主要分为以下几个模块:图形用户界面(GUI)模块网络通信模块线程处理模块 2.GUI设计 2.1主窗口设计 2.1.1......
  • 【JS】JavaScript编程语言-谷歌浏览器调试之前端代码(2024-06-05)
    1、在浏览器中调试调试是指在一个脚本中找出并修复错误的过程。所有的现代浏览器和大多数其他环境都支持调试工具——开发者工具中的一个令调试更加容易的特殊用户界面。它也可以让我们一步步地跟踪代码以查看当前实际运行情况。在这里我们将会使用Chrome(谷歌浏览器)。2......