赞
踩
@利用c++多线程实现modbusTCP/ip协议远程读写服务器
主函数如下
#include<iostream> #include"Modbus.h" bool test01(ModBus &m1) { m1.ReadHolingRegisters(0, 60); m1.WriteHolingRegisters(0, 60); return 0; } void test02() { ModBus m1("192.168.1.185", 50200); m1.ModBus_connect(); //ModBus m2("192.168.1.183", 50201); //m2.ModBus_connect(); //ModBus m3("192.168.1.183", 50202); //m3.ModBus_connect(); while (1) { std::thread thread1([&m1]() { test01(m1); }); //std::thread thread2([&m2]() { test01(m2); }); //std::thread thread3([&m3]() { test01(m3); }); thread1.join(); //thread2.join(); //thread3.join(); std::this_thread::sleep_for(std::chrono::seconds(2)); } } int main() { test02(); return 0; }
Modbus.h 头文件
#pragma once #include<vector> #include <winsock.h> #define _CRT_SECURE_NO_WARNINGS #pragma comment(lib, "ws2_32.lib") #include <thread> #include <random> #include <cstdint> #include <cstring> #include <random> using namespace std; class ModBus { public: ModBus(string modbus_address, unsigned modbus_port); bool ModBus_connect(); BOOL ReadHolingRegisters(USHORT start, USHORT length); BOOL ReadHolingRegisters_int(USHORT start, USHORT length); BOOL WriteHolingRegisters(USHORT start, USHORT length); BOOL WriteHolingRegisters_int(USHORT start, USHORT length); public: SOCKET clientSocket; string modbus_address; unsigned modbus_port; };
Modbus源文件
#pragma once #include<iostream> using namespace std; #include<iostream> #include"Modbus.h" uint32_t swapEndianness(uint32_t value) { return ((value & 0xFF) << 24) | (((value >> 8) & 0xFF) << 16) | (((value >> 16) & 0xFF) << 8) | ((value >> 24) & 0xFF); } ModBus::ModBus(string modbus_address, unsigned modbus_port) { this->modbus_address = modbus_address; this->modbus_port = modbus_port; } bool ModBus:: ModBus_connect() { WSADATA wsaData; // 初始化WSADATA为后续调用做准备 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup 失败。" << std::endl; return false; } // 创建套接字 通过套接字,程序能够连接到 Modbus 服务器,发送请求,接收响应,并在不需要连接时关闭套接字释放资源。 clientSocket = socket(AF_INET, SOCK_STREAM, 0); if (clientSocket == INVALID_SOCKET) { std::cerr << "Failed to create socket: " << WSAGetLastError() << std::endl; return false; } sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr((this->modbus_address).data()); // 服务器的 IP 地址 serverAddr.sin_port = htons(this->modbus_port); /* if (bind(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) 服务器连接客户端 { std::cerr << "Connect failed: " << WSAGetLastError() << std::endl; closesocket(clientSocket); return false; }*/ if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { std::cerr << "Connect failed: " << WSAGetLastError() << std::endl; closesocket(clientSocket); return false; } cout << "连接成功" << endl; cout << this->modbus_port << endl; return TRUE; } BOOL ModBus::ReadHolingRegisters(USHORT start, USHORT length) { //五步走 //1.拼接报文 vector <char> send_data; //事务协议 1个字节有8位置 send_data.push_back(0); send_data.push_back(0); send_data.push_back(0); send_data.push_back(0); //长度 send_data.push_back(0); send_data.push_back(6); //单元标识符 send_data.push_back(0x01); //功能码 send_data.push_back(0x03); //起始寄存器地址 send_data.push_back(char(start / 256)); send_data.push_back(char(start % 256)); //长度 send_data.push_back(char(length / 256)); send_data.push_back(char(length % 256)); //2.发送报文 const char* charData = &send_data[0]; int dataSizeToSend = send_data.size(); if (send(clientSocket, charData, dataSizeToSend, 0) == SOCKET_ERROR) { std::cerr << "Send failed: " << WSAGetLastError() << std::endl; /*ModBus_connect();*/ return -1; } std::cout << "Data sent successfully." << std::endl; //3.接收报文,接收数据 char buffer[1024]; int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); if (bytesRead == SOCKET_ERROR) { std::cerr << "Receive failed: " << WSAGetLastError() << std::endl; /*ModBus_connect();*/ return -1; } else { std::cout << "Received " << bytesRead << " bytes." << std::endl; } //4.验证报文 if (bytesRead == 2 * length + 9) { //cout << "长度正确" << endl; } //5.解析报文 前9个字节是固定的不属于数据。 uint32_t* data = (uint32_t*)(buffer + 9); for (int i = 0; i < (length / 2); i++) { data[i] = ntohl(data[i]); } cout << "当前端口为:" << this->modbus_port<< endl; float* new_data = (float*)data; for (int i = 0; i < (length / 2); i++) { cout << "data" << i + 1 << ":" << new_data[i] << " "; } cout << endl; // 1个float 4个字节 转换; //char dataBuffer[120]; //std::memcpy(dataBuffer, buffer + 9, 120); //float values[30]; //for (int i = 0; i < 30; ++i) { // uint32_t rawValue; // std::memcpy(&rawValue, &dataBuffer[i * 4], sizeof(uint32_t)); // // 根据系统字节序转换字节顺序 // rawValue = swapEndianness(rawValue); // std::memcpy(&values[i], &rawValue, sizeof(float)); // //} //for (int i = 0; i < 30; ++i) { // std::cout << "Value " << ": " << values[i] << " "; //} //cout << endl; //小端模式 //const float * data = (float*)(buffer + 9); //float a; //cout << "每个模块的值" << endl; //for (int i = 0; i < (length/2); i++) //{ // cout << (((*(data + i)))) << " "; //} //cout << endl; return 1; } BOOL ModBus::WriteHolingRegisters(USHORT start, USHORT length) { //五步走 //1.拼接报文 vector <char> send_data; //事务 1个字节有8位置 send_data.push_back(0); send_data.push_back(0); //协议 send_data.push_back(0); send_data.push_back(0); //长度 send_data.push_back(0); send_data.push_back(7 + 2 * length); //单元标识符 send_data.push_back(0x01); //功能码 send_data.push_back(0x10); //起始寄存器地址 send_data.push_back(char(start / 256)); send_data.push_back(char(start % 256)); //寄存器数量 send_data.push_back(0); send_data.push_back( length); //字节计数 字节*2 send_data.push_back( 2*length); //cout << send_data.size() << endl; //长度 一个数据占四个字节 // 1.end // 使用指针和类型转换将浮点数转换为字节数组 std::random_device rd; std::mt19937 gen(rd()); // 定义生成浮点数的范围 float lower_bound = 0.0; float upper_bound = 12.0; // 创建均匀分布对象 for (int i = 0; i < (length / 2); i++) { std::uniform_real_distribution<float> distribution(lower_bound, upper_bound); // 生成随机浮点数 float random_float = distribution(gen); /*cout << "float数值:" << random_float<< endl;*/ uint32_t uintValue; uintValue = *reinterpret_cast<uint32_t*>(&random_float); uintValue = htonl(uintValue); char* byteArray = (char*)(&uintValue); // 创建一个4字节的字节数组 for (int j = 0; j < 4; ++j) { send_data.push_back(byteArray[j]); } } // (2)方法 根据系统字节序转换字节顺序 //std::uniform_real_distribution<float> distribution(lower_bound, upper_bound); //float random_float = distribution(gen); //float floatValue = random_float; // 浮点数值 //uint32_t new_rawValue; //std::memcpy(&new_rawValue, &floatValue, sizeof(uint32_t)); //new_rawValue = swapEndianness(new_rawValue); //char byteArray[4]; // 创建一个4字节的字节数组 //std::memcpy(byteArray, &new_rawValue, sizeof(floatValue)); //for (int j = 0; j < 4; ++j) //{ // send_data.push_back(byteArray[j]); //} //2.发送报文 const char* charData = &send_data[0]; int dataSizeToSend = send_data.size(); if (send(clientSocket, charData, dataSizeToSend, 0) == SOCKET_ERROR) { std::cerr << "Send failed: " << WSAGetLastError() << std::endl; /*ModBus_connect();*/ return -1; } //std::cout << "Data sent successfully." << std::endl; //3.接收报文,接收数据 char buffer[1024]; int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); if (bytesRead == SOCKET_ERROR) { std::cerr << "Receive failed: " << WSAGetLastError() << std::endl; /*ModBus_connect();*/ return -1; } else { //std::cout << "Received " << bytesRead << " bytes." << std::endl; } //4.验证报文 if (bytesRead == 12) { cout << "长度正确" << endl; } else { cout << bytesRead << endl; cout << "长度不争取报文有问题" << endl; } return 1; } BOOL ModBus::ReadHolingRegisters_int(USHORT start, USHORT length) { //五步走 //1.拼接报文 vector <char> send_data; //事务协议 1个字节有8位置 send_data.push_back(0); send_data.push_back(0); send_data.push_back(0); send_data.push_back(0); //长度 send_data.push_back(0); send_data.push_back(6); //单元标识符 send_data.push_back(0x01); //功能码 send_data.push_back(0x03); //起始寄存器地址 send_data.push_back(char(start / 256)); send_data.push_back(char(start % 256)); //长度 send_data.push_back(char(length / 256)); send_data.push_back(char(length % 256)); //2.发送报文 const char* charData = &send_data[0]; int dataSizeToSend = send_data.size(); if (send(clientSocket, charData, dataSizeToSend, 0) == SOCKET_ERROR) { std::cerr << "Send failed: " << WSAGetLastError() << std::endl; return -1; } std::cout << "Data sent successfully." << std::endl; //3.接收报文,接收数据 char buffer[1024]; int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); if (bytesRead == SOCKET_ERROR) { std::cerr << "Receive failed: " << WSAGetLastError() << std::endl; return -1; } else { std::cout << "Received " << bytesRead << " bytes." << std::endl; } //4.验证报文 if (bytesRead == 2 * length + 9) { //cout << "长度正确" << endl; } //5.解析报文 前9个字节是固定的不属于数据。 int16_t* data = (int16_t*)(buffer + 9); for (int i = 0; i < (length ); i++) { data[i] = ntohs(data[i]); cout << "data" << i + 1 << ":" << data[i] << " "; } cout << endl; return 1; } BOOL ModBus::WriteHolingRegisters_int(USHORT start, USHORT length) { //五步走 //1.拼接报文 vector <char> send_data; //事务 1个字节有8位置 send_data.push_back(0); send_data.push_back(0); //协议 send_data.push_back(0); send_data.push_back(0); //长度 send_data.push_back(0); send_data.push_back(7 + 2 * length); //单元标识符 send_data.push_back(0x01); //功能码 send_data.push_back(0x10); //起始寄存器地址 send_data.push_back(char(start / 256)); send_data.push_back(char(start % 256)); //寄存器数量 send_data.push_back(0); send_data.push_back(length); //字节计数 字节*2 send_data.push_back(2 * length); //长度 一个数据占四个字节 // 定义生成浮点数的范围 float lower_bound = 0.0; float upper_bound = 12.0; // 创建均匀分布对象 for (int i = 0; i < (length ); i++) { std::random_device rd; std::mt19937 gen(rd()); // 设置种子以确保每次运行生成不同的随机数序列 std::srand(static_cast<unsigned int>(std::time(nullptr))); // 生成随机整数在 [0, 100] 范围内 int randomNumber = std::rand() % 101; // 取模操作将结果限制在 [0, 100] 范围内 uint16_t uintValue; uintValue = *reinterpret_cast<uint16_t*>(&randomNumber); uintValue = htons(uintValue); char* byteArray = (char*)(&uintValue); // 创建一个2字节的字节数组 for (int j = 0; j < 2; j++) { send_data.push_back(byteArray[j]); } } //2.发送报文 const char* charData = &send_data[0]; int dataSizeToSend = send_data.size(); if (send(clientSocket, charData, dataSizeToSend, 0) == SOCKET_ERROR) { std::cerr << "Send failed: " << WSAGetLastError() << std::endl; return -1; } //std::cout << "Data sent successfully." << std::endl; //3.接收报文,接收数据 char buffer[1024]; int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); if (bytesRead == SOCKET_ERROR) { std::cerr << "Receive failed: " << WSAGetLastError() << std::endl; return -1; } else { //std::cout << "Received " << bytesRead << " bytes." << std::endl; } //4.验证报文 if (bytesRead == 12) { cout << "长度正确" << endl; } else { cout << bytesRead << endl; cout << "长度不争取报文有问题" << endl; } return 1; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。