当前位置:   article > 正文

c++编写modbusTCP/ip协议远程读写服务器_c++ modbustcp

c++ modbustcp

@利用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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

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;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

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;
	
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/559242
推荐阅读
相关标签
  

闽ICP备14008679号