12.4 组播鼠标批量执行

2023-10-26 05:01
文章标签 批量 执行 鼠标 组播 12.4

本文主要是介绍12.4 组播鼠标批量执行,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

组播模式相比单播模式可以提高网络的效率和带宽利用率,因为组播数据包只需要发送一次,就可以被多个接收者接收,而不需要每个接收者都单独发送一份数据包。这在需要同时向多个接收者发送相同数据的场景下特别有用,如视频会议、在线教育、流媒体等。组播模式可以减少网络拥塞,降低网络延迟,并且可以减少网络中的冗余数据。

通过构建组播服务器端与客户端,并配合键盘鼠标控制接口,当服务器端执行一个操作时客户端同步执行,通过此方法读者可轻易的实现一个简单的镜像服务器,当服务器规模庞大而主机系统版本相同时,该功能可实现服务器端执行一次客户端即可实现批量部署的效果。

先来看服务端是如何实现的功能,首先服务端定义umsg结构体,该结构用于存储鼠标坐标值以及鼠标按键状态,当服务器运行后开启组播模式等待客户端上线,当客户端上线则我们通过动态获取本机鼠标位置并封装成结构体传输给上线的客户端,以此来实现镜像功能。

#include <winsock.h>
#include <iostream>#pragma comment(lib, "WSOCK32.lib")using namespace std;// 鼠标状态结构体
typedef struct umsg
{int cursor_pos_x;           // 鼠标X坐标int cursor_pos_y;           // 鼠标Y坐标int cursor_key_state;       // 鼠标按键状态umsg() :cursor_pos_x(), cursor_pos_y(), cursor_key_state(){cursor_pos_x = 0;cursor_pos_y = 0;cursor_key_state = 0;}
}umsg;// 获取鼠标按键
int GetKeyState()
{if (GetAsyncKeyState(VK_LBUTTON) & 0x8000){Sleep(15);return 1;}if (GetAsyncKeyState(VK_RBUTTON) & 0x8000){Sleep(15);return 2;}return 0;
}int main(int argc, char *argv[])
{WSADATA wsaData;struct sockaddr_in addr;int fd;struct ip_mreq mreq;// 初始化套接字if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){std::cout << "初始化失败" << std::endl;return 0;}// 创建套接字 SOCK_DGRAM 采用UDPif ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){std::cout << "套接字创建失败" << std::endl;return 0;}// 设置套接字为组播模式u_int yes = 1;if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0){std::cout << "设置组播模式失败" << std::endl;return 0;}// 0-同一台主机,1-跨主机UCHAR uLoop = 1;setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&uLoop, sizeof(uLoop));memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY);addr.sin_port = htons(9999);// 绑定套接字if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){std::cout << "绑定失败" << std::endl;return 0;}// 设置组播模式中的组信息mreq.imr_multiaddr.s_addr = inet_addr("228.2.3.1");mreq.imr_interface.s_addr = htonl(INADDR_ANY);if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0){int err = GetLastError();std::cout << "设置组失败: " << err << std::endl;return 0;}// 循环while (1){char recv_buffer[4096] = { 0 };char send_buffer[4096] = { 0 };int addrlen = sizeof(addr);int nbytes;// 接收组播数据if ((nbytes = recvfrom(fd, recv_buffer, 4096, 0, (struct sockaddr *) &addr, (int *)&addrlen)) < 0){std::cout << "接收数据包失败" << std::endl;return 0;}recv_buffer[nbytes] = '\0';std::cout << "接收组播数据包: " << recv_buffer << std::endl;umsg msg;// 获取鼠标状态POINT pt;BOOL ref = GetCursorPos(&pt);// 设置鼠标坐标msg.cursor_pos_x = pt.x;msg.cursor_pos_y = pt.y;// 获取鼠标状态值int key_flag = GetKeyState();if (key_flag == 0){msg.cursor_key_state = 0;}else if (key_flag == 1){msg.cursor_key_state = 1;}else if (key_flag == 2){msg.cursor_key_state = 2;}std::cout << "鼠标X = " << msg.cursor_pos_x << " 鼠标Y = " << msg.cursor_pos_y << std::endl;std::cout << "鼠标键位 = " << msg.cursor_key_state << std::endl;// 发送组播数据包sendto(fd, (char *)&msg, 4096, 0, (struct sockaddr *) &addr, sizeof(addr));}return 0;
}

与服务端功能类似,对于客户端来说,收到数据包以后,将其转换为umsg格式结构体,读取其中坐标信息,并执行指定函数对鼠标的状态进行设置,实现鼠标的同步执行。

#include <winsock.h>
#include <iostream>#pragma comment(lib, "WSOCK32.lib")using namespace std;// 鼠标状态结构体
typedef struct umsg
{int cursor_pos_x;           // 鼠标X坐标int cursor_pos_y;           // 鼠标Y坐标int cursor_key_state;       // 鼠标按键状态umsg() :cursor_pos_x(), cursor_pos_y(), cursor_key_state(){cursor_pos_x = 0;cursor_pos_y = 0;cursor_key_state = 0;}
}umsg;int main(int argc, char *argv[])
{WSADATA wsaData;struct sockaddr_in addr;int fd;// 初始化套接字if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){std::cout << "初始化失败" << std::endl;return 0;}// 创建套接字 SOCK_DGRAM 采用UDPif ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){std::cout << "套接字创建失败" << std::endl;return 0;}UCHAR uLoop = 1; // 0-同一台主机,1-跨主机setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&uLoop, sizeof(uLoop));// 设置组播模式组信息memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr("228.2.3.1");addr.sin_port = htons(9999);// 循环while (1){// 发送组播数据包char send_buffer[4096] = "Hello, World!";if (sendto(fd, send_buffer, strlen(send_buffer), 0, (struct sockaddr *) &addr, sizeof(addr)) < 0){std::cout << "发送失败" << std::endl;return 0;}// 接收组播数据int addrlen = sizeof(addr);char recv_buffer[4096] = { 0 };recvfrom(fd, recv_buffer, 4096, 0, (struct sockaddr *) &addr, (int *)&addrlen);std::cout << "接收组播数据包: " << recv_buffer << std::endl;// 格式化数据包为umsg格式umsg* recv_message = (umsg*)recv_buffer;int pos_x = recv_message->cursor_pos_x;int pos_y = recv_message->cursor_pos_y;int key_stat = recv_message->cursor_key_state;// 判断键位并设置if (key_stat == 0){std::cout << "鼠标X: " << pos_x << " 鼠标Y: " << pos_y << endl;SetCursorPos(pos_x, pos_y);}else if (key_stat == 1){std::cout << "左键按下" << std::endl;mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);key_stat = 0;}else if (key_stat == 2){std::cout << "右键按下" << std::endl;mouse_event(MOUSEEVENTF_RIGHTUP | MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);key_stat = 0;}}return 0;
}

读者可以编译上方两段代码,并首先在物理机内启动服务端,在虚拟机内启动客户端,此时当服务端鼠标发生移动时客户端也会跟随移动,服务端执行的操作客户端也会被执行,如下图所示;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/ae8bf78c.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

这篇关于12.4 组播鼠标批量执行的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/285433

相关文章

SpringBoot整合mybatisPlus实现批量插入并获取ID详解

《SpringBoot整合mybatisPlus实现批量插入并获取ID详解》这篇文章主要为大家详细介绍了SpringBoot如何整合mybatisPlus实现批量插入并获取ID,文中的示例代码讲解详细... 目录【1】saveBATch(一万条数据总耗时:2478ms)【2】集合方式foreach(一万条数

Python实现AVIF图片与其他图片格式间的批量转换

《Python实现AVIF图片与其他图片格式间的批量转换》这篇文章主要为大家详细介绍了如何使用Pillow库实现AVIF与其他格式的相互转换,即将AVIF转换为常见的格式,比如JPG或PNG,需要的小... 目录环境配置1.将单个 AVIF 图片转换为 JPG 和 PNG2.批量转换目录下所有 AVIF 图

详解如何通过Python批量转换图片为PDF

《详解如何通过Python批量转换图片为PDF》:本文主要介绍如何基于Python+Tkinter开发的图片批量转PDF工具,可以支持批量添加图片,拖拽等操作,感兴趣的小伙伴可以参考一下... 目录1. 概述2. 功能亮点2.1 主要功能2.2 界面设计3. 使用指南3.1 运行环境3.2 使用步骤4. 核

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并

Jmeter如何向数据库批量插入数据

《Jmeter如何向数据库批量插入数据》:本文主要介绍Jmeter如何向数据库批量插入数据方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Jmeter向数据库批量插入数据Jmeter向mysql数据库中插入数据的入门操作接下来做一下各个元件的配置总结Jmete

CSS模拟 html 的 title 属性(鼠标悬浮显示提示文字效果)

《CSS模拟html的title属性(鼠标悬浮显示提示文字效果)》:本文主要介绍了如何使用CSS模拟HTML的title属性,通过鼠标悬浮显示提示文字效果,通过设置`.tipBox`和`.tipBox.tipContent`的样式,实现了提示内容的隐藏和显示,详细内容请阅读本文,希望能对你有所帮助... 效

Python批量调整Word文档中的字体、段落间距及格式

《Python批量调整Word文档中的字体、段落间距及格式》这篇文章主要为大家详细介绍了如何使用Python的docx库来批量处理Word文档,包括设置首行缩进、字体、字号、行间距、段落对齐方式等,需... 目录关键代码一级标题设置  正文设置完整代码运行结果最近关于批处理格式的问题我查了很多资料,但是都没

通过Python脚本批量复制并规范命名视频文件

《通过Python脚本批量复制并规范命名视频文件》本文介绍了如何通过Python脚本批量复制并规范命名视频文件,实现自动补齐数字编号、保留原始文件、智能识别有效文件等功能,听过代码示例介绍的非常详细,... 目录一、问题场景:杂乱的视频文件名二、完整解决方案三、关键技术解析1. 智能路径处理2. 精准文件名

grom设置全局日志实现执行并打印sql语句

《grom设置全局日志实现执行并打印sql语句》本文主要介绍了grom设置全局日志实现执行并打印sql语句,包括设置日志级别、实现自定义Logger接口以及如何使用GORM的默认logger,通过这些... 目录gorm中的自定义日志gorm中日志的其他操作日志级别Debug自定义 Loggergorm中的