c++编写modbusTCP/ip协议远程读写服务器
创始人
2024-11-06 16:10:37

@利用c++多线程实现modbusTCP/ip协议远程读写服务器

主函数如下

#include #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 #include  #define _CRT_SECURE_NO_WARNINGS #pragma comment(lib, "ws2_32.lib")  #include  #include  #include  #include  #include   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 using namespace std; #include #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  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  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 distribution(lower_bound, upper_bound); 			// 生成随机浮点数 			float random_float = distribution(gen); 			/*cout << "float数值:" << random_float<< endl;*/ 			uint32_t uintValue; 			uintValue = *reinterpret_cast(&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 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  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  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(std::time(nullptr)));  			// 生成随机整数在 [0, 100] 范围内 			int randomNumber = std::rand() % 101; // 取模操作将结果限制在 [0, 100] 范围内  			uint16_t uintValue; 			uintValue = *reinterpret_cast(&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; 	 	} 

相关内容

热门资讯

裸辞做“一人公司”,我后悔了 去年这个时候,一位以色列程序员正在东南亚旅行。他顺手把一个在脑子里转了很久的想法做成了产品,一个让任...
南京建成国内首个Pre-6G试... 4月21日,2026全球6G技术与产业生态大会在南京开幕。全息互动技术展台前,一名远在北京的工作人员...
超梵求职受邀参加“2025抖音... 超梵求职受邀参加“2025抖音巨量引擎成人教育行业生态大会”,探讨分享优质内容传播,服务万千学员。 ...
摩托罗拉Razr 2026(R... IT之家 4 月 22 日消息,摩托罗拉宣布新一代 Razr 折叠手机将于 4 月 29 日在美国发...
库克卸任,特纳斯领航:苹果新纪... 苹果首席执行官蒂姆·库克将卸任,硬件工程主管约翰·特纳斯将接任,苹果公司今天宣布此事。 库克将在夏季...