Explorar el Código

修改TCP解析响应报文模块

添加异常连接断开重连
添加用户选择退出功能
master
zcn1123 hace 4 años
padre
commit
20a2438741
Se han modificado 7 ficheros con 263 adiciones y 29 borrados
  1. +31
    -6
      Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp
  2. +57
    -0
      Modbus_communication/Modbus_RTU_Salve/common.cpp
  3. +6
    -0
      Modbus_communication/Modbus_RTU_Salve/common.h
  4. +56
    -0
      Modbus_communication/Modbus_TCP/Modbus_TCP_log.txt
  5. +90
    -23
      Modbus_communication/Modbus_TCP/TCP_client.cpp
  6. +22
    -0
      Modbus_communication/Modbus_TCP/common.cpp
  7. +1
    -0
      Modbus_communication/Modbus_TCP/common.h

+ 31
- 6
Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp Ver fichero

@@ -271,8 +271,8 @@ bool Check_Requst_Message_Len(UINT8 *Requst_Message, DWORD Read_len)
if (Requst_Message[1] == 0x0F || Requst_Message[1] == 0x10)
{
unsigned int Number = Requst_Message[4] << 8 | Requst_Message[5];
unsigned int Count_len = Count_Read_date_number(Requst_Message[1], Number) + 9;
if (Read_len != Count_len)
unsigned int Count_len = Count_Read_date_number(Requst_Message[1], Number);
if (Requst_Message[6] != Count_len || Read_len != Count_len + 9)
return false;
}
return true;
@@ -321,6 +321,8 @@ bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWO
{
if (Requst_Message[0] != Device_ID) //检查设备ID一致
return false;
if (Read_len < 8 || Read_len > 256)
return false;
if (!Check_Requst_Message_CRC(Requst_Message, Read_len))//CRC校验报文是否正确
return false;
if (RTU_Enable == 0)
@@ -350,6 +352,7 @@ HANDLE Input_Parameter()
HANDLE Handle_Com;
while (true)
{
GetComm_Name();
string COMM = Input_COMM();
unsigned int Baud_Rate = Input_Baud_Rate();
BYTE Date_Bits = Input_Date_Bits();
@@ -391,11 +394,10 @@ int Modbus_RTU_Salve(void)
printf("发送失败,重新发送第%d次\n",Count);
if (Count > 4)
{
printf("设备端口异常\n");
break;
}
}
/* printf("主站请求 :");
printf("主站请求 :");
for (unsigned int i = 0; i < Read_len; i++)
{
printf("%02x ", Requst_Message[i]);
@@ -407,12 +409,35 @@ int Modbus_RTU_Salve(void)
printf("%02x ", Response_Message[i]);
}
printf("\n\n");
Log_Note(Requst_Message, 0, Read_len);
Log_Note(Response_Message, 1, Response_Message_Len);*/
//Log_Note(Requst_Message, 0, Read_len);
//Log_Note(Response_Message, 1, Response_Message_Len);
}
else
continue;
}
else
{
printf("设备端口异常,请检查设备连接状态\n");
printf("**************************** Press Enter To Contioun ****************************\n");
getchar();
system("cls");
printf("是否重新连接端口: 1 重新连接 0 关闭本软件\n");
int a = 0 ;
do
{
cin >> a;
cin.clear();
cin.sync();
} while (!(a == 0 || a == 1));
if (a == 1)
{
CloseHandle(Handle_Com);
}
else
break;

Handle_Com = Input_Parameter();
}
}
CloseHandle(Handle_Com);
getchar();


+ 57
- 0
Modbus_communication/Modbus_RTU_Salve/common.cpp Ver fichero

@@ -451,3 +451,60 @@ void Log_Note(UINT8 *Message, int flage, int Message_len)
}


bool cmp(string s1, string s2)
{
if (atoi(s1.substr(3).c_str()) < atoi(s2.substr(3).c_str()))//升序
return true;
else
return false;
}

//获取串口号
void GetComList_Reg(std::vector<string>& comList)
{
HKEY hkey;
int result;
int i = 0;

result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
_T("Hardware\\DeviceMap\\SerialComm"),
NULL,
KEY_READ,
&hkey);

if (ERROR_SUCCESS == result) // 打开串口注册表
{
TCHAR portName[0x100], commName[0x100];
DWORD dwLong, dwSize;
do
{
dwSize = sizeof(portName) / sizeof(TCHAR);
dwLong = dwSize;
result = RegEnumValue(hkey, i, portName, &dwLong, NULL, NULL, (LPBYTE)commName, &dwSize);
if (ERROR_NO_MORE_ITEMS == result)
{
// 枚举串口
break; // commName就是串口名字"COM4"
}

comList.push_back(commName);
i++;
} while (1);

RegCloseKey(hkey);
}
}

void GetComm_Name(void)
{
vector<string> comList;
GetComList_Reg(comList);
sort(comList.begin(), comList.end(), cmp);
printf("当前可用端口:");
for (int i = 0; i < comList.size(); i++)
{
cout << comList[i] << " ";
}
printf("\n");
}


+ 6
- 0
Modbus_communication/Modbus_RTU_Salve/common.h Ver fichero

@@ -5,6 +5,11 @@
#include <string>
#include <iostream>
#include <time.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <tchar.h>
using namespace std;

unsigned int Count_Read_date_number(int Function_code, unsigned int Operations_Number);
@@ -18,5 +23,6 @@ BYTE Input_Parity(void);
unsigned int Input_RTU_Enable(void);
UINT16 CRC_16(UINT8 *Data, unsigned int CRC_Len);
void Log_Note(UINT8 *Message, int flage, int Message_len);
void GetComm_Name(void);

#endif

+ 56
- 0
Modbus_communication/Modbus_TCP/Modbus_TCP_log.txt Ver fichero

@@ -193,3 +193,59 @@
2020-9-11 17:19:30 Recv:00 03 00 00 00 06 01 10 00 00 00 01
2020-9-11 17:19:38 Send:00 04 00 00 00 06 01 03 00 00 00 01
2020-9-11 17:19:38 Recv:00 04 00 00 00 05 01 03 02 FF FF
2020-9-12 11:22:50 Send:00 00 00 00 00 06 01 01 00 00 00 01
2020-9-12 11:22:50 Recv:00 00 00 00 00 04 01 01 01 00
2020-9-12 14:55:43 Send:00 00 00 00 00 06 01 01 00 00 00 00
2020-9-12 14:55:48 Send:00 01 00 00 00 06 01 03 00 01 00 01
2020-9-12 14:55:55 Send:00 02 00 00 00 06 01 01 00 00 00 01
2020-9-12 14:56:27 Send:00 03 00 00 00 06 01 01 00 00 00 01
2020-9-12 14:56:35 Send:00 04 00 00 00 06 01 01 00 00 00 01
2020-9-12 15:3:58 Send:00 00 00 00 00 06 01 01 00 00 00 01
2020-9-12 15:10:7 Send:00 01 00 00 00 06 01 01 00 00 00 01
2020-9-12 15:13:40 Send:00 00 00 00 00 06 01 01 00 00 00 01
2020-9-12 15:14:31 Send:00 00 00 00 00 06 01 01 00 00 00 01
2020-9-12 15:14:39 Recv:00 04 00 00 00 06 01 10 00 00 00 01 00 04 00 00 00 06 01 10 00 00 00 01 00 04 00 00 00 06 01 10 00 00 00 01
2020-9-12 15:19:21 Send:00 01 00 00 00 06 01 01 00 00 00 00
2020-9-12 18:10:10 Send:00 00 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:11:7 Send:00 01 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:12:12 Recv:00 01 00 00 00 04 01 01 01 01
2020-9-12 18:24:0 Send:00 00 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:24:47 Recv:00 00 00 00 00 04 01 01 01 01
2020-9-12 18:25:58 Send:00 01 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:26:13 Recv:00 00 00 00 00 04 01 01 01 01 01
2020-9-12 18:26:54 Send:00 02 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:27:24 Recv:00 02 00 00 00 05 01 01 01 01 01
2020-9-12 18:34:7 Send:00 03 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:34:53 Recv:00 03 00 00 00 04 03 01 01
2020-9-12 18:36:23 Send:00 04 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:36:39 Recv:00 03 00 00 00 04 81 01
2020-9-12 18:36:48 Send:00 05 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:36:56 Recv:00 05 00 00 00 04 81 01
2020-9-12 18:38:30 Send:00 06 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:38:37 Recv:00 05 00 00 00 02 81 01
2020-9-12 18:38:51 Send:00 07 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:39:0 Recv:00 07 00 00 00 02 81 01
2020-9-12 18:41:51 Send:00 08 00 00 00 06 01 01 00 00 00 0A
2020-9-12 18:42:10 Recv:00 07 00 00 00 03 01 81 01
2020-9-12 18:42:17 Send:00 09 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:42:33 Recv:00 09 00 00 00 03 01 81 01
2020-9-12 18:45:20 Send:00 0A 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:45:43 Recv:00 0A 00 00 00 03 01 81 02
2020-9-12 18:45:56 Send:00 0B 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:46:13 Recv:00 0B 00 00 00 03 01 81 03
2020-9-12 18:46:29 Send:00 0C 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:46:48 Recv:00 0C 00 00 00 03 01 81 04
2020-9-12 18:48:47 Send:00 0D 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:50:8 Recv:00 0D 03 00 00 04 01 01 01 01
2020-9-12 18:55:44 Send:00 0E 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:57:11 Recv:00 0E 00 00 01 06 01 01 01 01
2020-9-12 18:58:19 Send:00 0F 00 00 00 06 01 01 00 00 00 01
2020-9-12 18:59:33 Recv:00 0F 00 00 00 04 01 81 02 11
2020-9-12 19:3:50 Send:00 00 00 00 00 06 01 01 00 00 00 00
2020-9-12 19:38:43 Send:00 00 00 00 00 06 01 01 00 00 00 01
2020-9-12 19:39:23 Send:00 01 00 00 00 06 01 01 00 00 00 01
2020-9-12 19:39:36 Recv:00 0F 00 00 00 04 01 81 02 11
2020-9-12 19:40:10 Send:00 02 00 00 00 06 01 01 00 00 00 01
2020-9-12 19:40:22 Recv:00 02 00 00 00 04 01 81 02 11
2020-9-12 19:43:41 Send:00 00 00 00 00 06 01 01 00 00 00 01
2020-9-12 19:43:56 Recv:00 00 00 00 00 04 01 81 02 11

+ 90
- 23
Modbus_communication/Modbus_TCP/TCP_client.cpp Ver fichero

@@ -87,8 +87,11 @@ void Input_IP(string& IP, unsigned int *Port_number)
* Port_number 端口号(1-65535)
* 输出 : ClientSocket 连接成功的套接字
*********************************************************************************************/
SOCKET Init_client(string IP, unsigned int Port_number)
SOCKET Init_client()
{
string IP;
unsigned int Port_number;
Input_IP(IP, &Port_number);
if (InitSocket_Version() == 0)
return INVALID_SOCKET;
SOCKET ClientSocket = socket(AF_INET, SOCK_STREAM, 0);
@@ -170,6 +173,32 @@ void Printf_Anomaly_date(UINT8 *Response_Message)
}
}



/*********************************************************************************************
* 功能    : 检测响应报文长度
* 描述   : 对响应报文中存放长度字节进行判断和请求报文对比
* 输入 : Response_Message 响应报文 Request_Message 请求报文 Response_Message_len 接收到的数据长度
* 输出 : true 长度正常 false 长度异常
*********************************************************************************************/
bool Check_Response_Message_len(UINT8 *Response_Message, UINT8 *Request_Message, int Response_Message_len)
{
if ((Response_Message_len - 6) != Response_Message[5])
return false;
unsigned int Operations_Number = Request_Message[10] << 8 | Request_Message[11];
unsigned int Respone_Len = Count_Respone_Len(Request_Message[7], Operations_Number);
if (Request_Message[7] == 0x0F || Request_Message[7] == 0x10)
if (Response_Message_len != 12)
return false;
if (Request_Message[7] == 0x01 || Request_Message[7] == 0x03)
{
if (Respone_Len + 9 != Response_Message_len)
return false;
if (Respone_Len != Response_Message[8])
return false;
}
return true;
}
/*********************************************************************************************
* 功能    : 判断响应报文是否可以正常解析
* 描述   : 通过长度和异常码等判定该响应报文是否可以解析
@@ -183,17 +212,24 @@ bool Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message,
if (i == 4 || i == 5) //后续字节长度
continue;
if (Response_Message[i] != Request_Message[i]) //0 1 传输标识,2 3 协议标识,6设备ID
return false; //一旦不一致,判定为异常报文
return false; //一旦不一致,判定为异常报文数据
}
if (Response_Message[4] != 0x00 || (Response_Message_len - 6) != Response_Message[5]) //4 固定0x00 帧长度判定
if (Response_Message[4] != 0x00) //4 固定0x00 帧长度判定
return false;
if (Response_Message[7] == Request_Message[7] + 0x80 && Response_Message_len == 9)//先处理异常响应

if (Response_Message[7] == Request_Message[7] + 0x80)//先处理异常响应
{
Printf_Anomaly_date(Response_Message);
return true;
if (Response_Message_len == 9)
{
Printf_Anomaly_date(Response_Message);
return true;
}
else
return false;
}

if (!Check_Response_Message_len(Response_Message, Request_Message, Response_Message_len))
return false;
if (Response_Message[7] == 0x01)
Printf_Coil_date(Response_Message, Request_Message);
else if (Response_Message[7] == 0x03)
@@ -217,18 +253,10 @@ bool Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message,
bool Tcp_client()
{
SOCKET ClientSocket;
string IP;
unsigned int Port_number;
do
{
Input_IP(IP, &Port_number);
ClientSocket = Init_client(IP, Port_number);

} while (INVALID_SOCKET == ClientSocket);
if (INVALID_SOCKET == ClientSocket)
{
cout << "初始化主站失败" << endl;
}
ClientSocket = Init_client();
} while (INVALID_SOCKET == ClientSocket);
UINT8 Request_Message[600];
UINT8 Response_Message[600];
TIMEVAL timeout;
@@ -244,7 +272,7 @@ bool Tcp_client()
string Write_date = Input_Write_date(Function_code, Operations_Number);
int Request_Message_len = Crate_TCP_Message(Request_Message, Function_code, Operations_Number, Starting_address, Write_date);
Request_Message[0] = Transmission_Indicator >> 8;
Request_Message[1] = Transmission_Indicator;
Request_Message[1] = (UINT8)Transmission_Indicator;
printf("主站请求 :");
for (int i = 0; i < Request_Message_len; i++)
{
@@ -258,12 +286,31 @@ bool Tcp_client()
Transmission_Indicator = 0x00;
}
Transmission_Indicator++;

if (test == (-1))
{
printf("连接异常,请检查连接状态。\n");
printf("**************************** Press Enter To Close ****************************\n");
break;
printf("**************************** Press Enter To Contioun ****************************\n");
getchar();
system("cls");
closesocket(ClientSocket);
WSACleanup();
printf("是否重新连接服务器: 1 重新连接 0 关闭本软件");
int a = 0;
do
{
cin >> a;
cin.clear();
cin.sync();
} while (!(a == 0 || a == 1));
if (a == 0)
break;
system("cls");
do
{
ClientSocket = Init_client();
} while (INVALID_SOCKET == ClientSocket);
system("cls");
continue;
}
memset(Response_Message, 0, 300);
FD_ZERO(&reads);
@@ -284,8 +331,28 @@ bool Tcp_client()
else if (select(0, &reads, 0, 0, &timeout))
{
printf("连接异常,请检查连接状态。\n");
printf("**************************** Press Enter To Close ****************************\n");
break;
printf("**************************** Press Enter To Contioun ****************************\n");
getchar();
system("cls");
closesocket(ClientSocket);
WSACleanup();
printf("是否重新连接服务器: 1 重新连接 0 关闭本软件\n");
int a = 0;
do
{
cin >> a;
cin.clear();
cin.sync();
} while (!(a == 0 || a == 1));
if (a == 0)
break;
system("cls");
do
{
ClientSocket = Init_client();
} while (INVALID_SOCKET == ClientSocket);
system("cls");
continue;
}
else
cout << "响应超时" << endl;


+ 22
- 0
Modbus_communication/Modbus_TCP/common.cpp Ver fichero

@@ -159,6 +159,28 @@ unsigned int Count_Write_date_number(int Function_code, unsigned int Operations_
return Write_date_number;
}

/*********************************************************************************************
* 功能    : 计算请求报文计算预期响应报文字节数
* 描述   : 通过对应的功能码和操作数量计算对应的数据字节数
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量
* 输出 : Respone_len 预期响应的数据字节数
*********************************************************************************************/
unsigned int Count_Respone_Len(int Function_code, unsigned int Operations_Number)
{
unsigned int Respone_len = 0;
if (Function_code == 0x0F|| Function_code == 0x10)
return Respone_len;
if (Function_code == 0x01) //读线圈
{
Respone_len = Operations_Number / 8;
if (Operations_Number % 8)
Respone_len++;
}
if (Function_code == 0x03)
Respone_len = Operations_Number * 2;
return Respone_len;
}

/*********************************************************************************************
* 功能    : 输入写入数据
* 描述   : 根据写入数量和功能码类型输入相应的数据


+ 1
- 0
Modbus_communication/Modbus_TCP/common.h Ver fichero

@@ -25,6 +25,7 @@ void Crate_MBAP(UINT8 *Message, int Function_code, unsigned int Operations_Numbe
int HexStringtoByte(UINT8 *Message, string Write_date, int Message_len, int Function_code, unsigned int Operations_Number);
int Crate_TCP_Message(UINT8 *Message, int Function_code, unsigned int Operations_Number, unsigned int Starting_address, string Write_date);
void Log_Note(UINT8 *Message, int flage, int Message_len);
unsigned int Count_Respone_Len(int Function_code, unsigned int Operations_Number);


#endif

Cargando…
Cancelar
Guardar