作者 | SHA1 | 备注 | 提交日期 |
---|---|---|---|
|
65358c4c02 | 1 | 4 年前 |
|
5fa8c62734 | 调整TCP/RTU代码结构 | 4 年前 |
|
54667d8bbb | 调整RTU从站代码结构 | 4 年前 |
|
772632a9f2 | 调整了TCP主站代码结构 | 4 年前 |
@@ -406,3 +406,35 @@ | |||
2020-9-10 15:53:22 Send:01 85 01 83 50 | |||
2020-9-10 15:53:24 Recv:01 01 00 11 00 01 AD CF | |||
2020-9-10 15:53:24 Send:01 01 01 00 51 88 | |||
2020-9-16 19:2:31 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:31 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:33 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:33 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:33 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:33 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:34 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:34 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:35 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:35 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:35 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:35 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:37 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:37 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:38 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:38 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:38 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:38 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:39 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:39 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:39 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:39 Recv:09 90 03 8D C3 | |||
2020-9-16 19:2:40 Send:09 10 00 00 00 01 03 00 00 00 50 6C | |||
2020-9-16 19:2:40 Recv:09 90 03 8D C3 | |||
2020-9-16 19:3:14 Send:09 10 00 00 00 01 02 00 00 C1 90 | |||
2020-9-16 19:3:14 Recv:09 10 00 00 00 01 00 81 | |||
2020-9-16 19:3:15 Send:09 10 00 00 00 01 02 00 00 C1 90 | |||
2020-9-16 19:3:15 Recv:09 10 00 00 00 01 00 81 | |||
2020-9-16 19:3:34 Send:09 03 00 00 00 01 85 42 | |||
2020-9-16 19:3:34 Recv:09 03 02 00 00 59 85 | |||
2020-9-16 19:3:35 Send:09 03 00 00 00 01 85 42 | |||
2020-9-16 19:3:35 Recv:09 03 02 00 00 59 85 |
@@ -27,29 +27,29 @@ void Init_Coil_Register(void) | |||
* 输入 : Bitset_Address Bitset的起始地址 Read_Number 要读取的位数 | |||
* 返回值 : Date 转换后的UNIT8数据 | |||
**********************************************************************************************/ | |||
UINT8 Bitset_to_Uint8(unsigned int Bitset_Address, unsigned int Read_Number) | |||
UINT8 Bitset_to_Uint8(unsigned int bitset_address, unsigned int read_number) | |||
{ | |||
UINT8 Date = 0x00; | |||
UINT8 date = 0x00; | |||
if (Read_Number >= 8) | |||
if (read_number >= 8) | |||
{ | |||
unsigned int len = Bitset_Address + 7; | |||
unsigned int len = bitset_address + 7; | |||
for (unsigned int i = 0; i < 8; i++) | |||
{ | |||
Date = Date << 1; | |||
Date = Date | (int)Coil_date[len--]; | |||
date = date << 1; | |||
date = date | (int)Coil_date[len--]; | |||
} | |||
} | |||
else | |||
{ | |||
unsigned int len = Bitset_Address + Read_Number-1; | |||
for (unsigned int i = 0; i < Read_Number; i++) | |||
unsigned int len = bitset_address + read_number - 1; | |||
for (unsigned int i = 0; i < read_number; i++) | |||
{ | |||
Date = Date << 1; | |||
Date = Date | (int)Coil_date[len--]; | |||
date = date << 1; | |||
date = date | (int)Coil_date[len--]; | |||
} | |||
} | |||
return Date; | |||
return date; | |||
} | |||
/********************************************************************************************* | |||
@@ -58,15 +58,15 @@ UINT8 Bitset_to_Uint8(unsigned int Bitset_Address, unsigned int Read_Number) | |||
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文 | |||
* 返回值 : 无 | |||
**********************************************************************************************/ | |||
void Create_Abnormal_Code_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, UINT8 Abnormal_Code) | |||
void Create_Abnormal_Code_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, UINT8 abnormal_code) | |||
{ | |||
Response_Message[0] = Device_ID; | |||
Response_Message[1] = Requst_Message[1] + 0x80; | |||
Response_Message[2] = Abnormal_Code; | |||
Response_Message[2] = abnormal_code; | |||
Response_Message_Len = 3; | |||
UINT16 CRC_date = CRC_16(Response_Message, 3); | |||
Response_Message[3] = CRC_date >> 8;//CRC_H | |||
Response_Message[4] = (UINT8)CRC_date; //CRC_L | |||
UINT16 crc_date = CRC_16(Response_Message, 3); | |||
Response_Message[3] = crc_date >> 8;//CRC_H | |||
Response_Message[4] = (UINT8)crc_date; //CRC_L | |||
Response_Message_Len = 5; | |||
} | |||
@@ -78,25 +78,25 @@ void Create_Abnormal_Code_Response_Message(UINT8 *Requst_Message, UINT8 *Respons | |||
**********************************************************************************************/ | |||
void Create_0x01_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message) | |||
{ | |||
unsigned int Start_Address = Requst_Message[2] << 8 | Requst_Message[3]; | |||
unsigned int Address_range = Start_Address + (Requst_Message[4] << 8 | Requst_Message[5]); | |||
if (Address_range < MAX_Address)//判断地址是否超限 | |||
unsigned int start_Address = Requst_Message[2] << 8 | Requst_Message[3]; | |||
unsigned int address_range = start_Address + (Requst_Message[4] << 8 | Requst_Message[5]); | |||
if (address_range < MAX_Address)//判断地址是否超限 | |||
{ | |||
unsigned int Read_Number = Requst_Message[4] << 8 | Requst_Message[5];//要读取的位数 | |||
unsigned int Read_Len = Count_Read_date_number(Requst_Message[1], Read_Number); //要读取的字节数 | |||
for (unsigned int i = 3; i < Read_Len + 3; i++) | |||
unsigned int read_number = Requst_Message[4] << 8 | Requst_Message[5];//要读取的位数 | |||
unsigned int read_len = Count_Read_date_number(Requst_Message[1], read_number); //要读取的字节数 | |||
for (unsigned int i = 3; i < read_len + 3; i++) | |||
{ | |||
Response_Message[i] = Bitset_to_Uint8(Start_Address, Read_Number); | |||
Start_Address += 8; | |||
Read_Number -= 8; | |||
Response_Message[i] = Bitset_to_Uint8(start_Address, read_number); | |||
start_Address += 8; | |||
read_number -= 8; | |||
} | |||
Response_Message[0] = Device_ID; | |||
Response_Message[1] = Requst_Message[1]; | |||
Response_Message[2] = Read_Len; //响应报文中的后续字节数 | |||
UINT16 CRC_date = CRC_16(Response_Message, Read_Len+3); | |||
Response_Message_Len = Read_Len + 2 + 3; | |||
Response_Message[Response_Message_Len - 2] = CRC_date>>8;//CRC_H | |||
Response_Message[Response_Message_Len - 1] = (UINT8)CRC_date; //CRC_L | |||
Response_Message[2] = read_len; //响应报文中的后续字节数 | |||
UINT16 crc_date = CRC_16(Response_Message, read_len + 3); | |||
Response_Message_Len = read_len + 2 + 3; | |||
Response_Message[Response_Message_Len - 2] = crc_date >> 8;//CRC_H | |||
Response_Message[Response_Message_Len - 1] = (UINT8)crc_date; //CRC_L | |||
} | |||
else | |||
{ | |||
@@ -112,26 +112,25 @@ void Create_0x01_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message | |||
**********************************************************************************************/ | |||
void Create_0x03_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message) | |||
{ | |||
unsigned int Start_Address = Requst_Message[2] << 8 | Requst_Message[3]; | |||
unsigned int Address_range = Start_Address + (Requst_Message[4] << 8 | Requst_Message[5]); | |||
if (Address_range < MAX_Address) //判断地址是否超限 | |||
unsigned int start_Address = Requst_Message[2] << 8 | Requst_Message[3]; | |||
unsigned int address_range = start_Address + (Requst_Message[4] << 8 | Requst_Message[5]); | |||
if (address_range < MAX_Address) //判断地址是否超限 | |||
{ | |||
unsigned int Read_Number = Requst_Message[4] << 8 | Requst_Message[5];//要读取的寄存器数量 | |||
unsigned int Read_Len = Count_Read_date_number(Requst_Message[1 | |||
], Read_Number); //要读取的字节数 | |||
for (unsigned int i = 3; i < Read_Len + 3; i= i + 2) | |||
unsigned int read_number = Requst_Message[4] << 8 | Requst_Message[5];//要读取的寄存器数量 | |||
unsigned int read_len = Count_Read_date_number(Requst_Message[1], read_number); //要读取的字节数 | |||
for (unsigned int i = 3; i < read_len + 3; i = i + 2) | |||
{ | |||
Response_Message[i] = Register[Start_Address] >> 8; | |||
Response_Message[i + 1] = (UINT8)Register[Start_Address]; | |||
Start_Address += 1; | |||
Response_Message[i] = Register[start_Address] >> 8; | |||
Response_Message[i + 1] = (UINT8)Register[start_Address]; | |||
start_Address += 1; | |||
} | |||
Response_Message[0] = Device_ID; | |||
Response_Message[1] = Requst_Message[1]; | |||
Response_Message[2] = Read_Len; //响应报文中的后续字节数 | |||
UINT16 CRC_date = CRC_16(Response_Message, Read_Len + 3); | |||
Response_Message_Len = Read_Len + 2 + 3; | |||
Response_Message[Response_Message_Len - 2] = CRC_date >> 8;//CRC_H | |||
Response_Message[Response_Message_Len - 1] = (UINT8)CRC_date; //CRC_L | |||
Response_Message[2] = read_len; //响应报文中的后续字节数 | |||
UINT16 crc_date = CRC_16(Response_Message, read_len + 3); | |||
Response_Message_Len = read_len + 2 + 3; | |||
Response_Message[Response_Message_Len - 2] = crc_date >> 8;//CRC_H | |||
Response_Message[Response_Message_Len - 1] = (UINT8)crc_date; //CRC_L | |||
} | |||
else //地址超限 | |||
{ | |||
@@ -145,22 +144,22 @@ void Create_0x03_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message | |||
* 输入 : Write_date_Message 要写入的数据 Write_Number要写入的位数 Start_Address起始地址 | |||
* 返回值 : 无 | |||
**********************************************************************************************/ | |||
void Write_Coil_date(UINT8 Write_date_Message, unsigned int Write_Number, unsigned int Start_Address) | |||
void Write_Coil_date(UINT8 write_date_message, unsigned int write_number, unsigned int start_address) | |||
{ | |||
if (Write_Number >= 8) | |||
if (write_number >= 8) | |||
{ | |||
for (unsigned int i = Start_Address; i < Start_Address+8; i++) | |||
for (unsigned int i = start_address; i < start_address + 8; i++) | |||
{ | |||
Coil_date[i] = Write_date_Message & 1; | |||
Write_date_Message = Write_date_Message >> 1; | |||
Coil_date[i] = write_date_message & 1; | |||
write_date_message = write_date_message >> 1; | |||
} | |||
} | |||
else | |||
{ | |||
for (unsigned int i = Start_Address; i < Start_Address + Write_Number; i++) | |||
for (unsigned int i = start_address; i < start_address + write_number; i++) | |||
{ | |||
Coil_date[i] = Write_date_Message & 1; | |||
Write_date_Message = Write_date_Message >> 1; | |||
Coil_date[i] = write_date_message & 1; | |||
write_date_message = write_date_message >> 1; | |||
} | |||
} | |||
} | |||
@@ -173,16 +172,16 @@ void Write_Coil_date(UINT8 Write_date_Message, unsigned int Write_Number, unsign | |||
**********************************************************************************************/ | |||
void Create_0x0F_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message) | |||
{ | |||
unsigned int Start_Address = Requst_Message[2] << 8 | Requst_Message[3]; | |||
unsigned int Address_range = Start_Address + (Requst_Message[4] << 8 | Requst_Message[5]); | |||
if (Address_range < MAX_Address)//判断地址是否超限 | |||
unsigned int start_Address = Requst_Message[2] << 8 | Requst_Message[3]; | |||
unsigned int address_range = start_Address + (Requst_Message[4] << 8 | Requst_Message[5]); | |||
if (address_range < MAX_Address)//判断地址是否超限 | |||
{ | |||
unsigned int Write_Number = Requst_Message[4] << 8 | Requst_Message[5];//要写入的位数 | |||
unsigned int write_Number = Requst_Message[4] << 8 | Requst_Message[5];//要写入的位数 | |||
for (int i = 7; i < Requst_Message[6]+7; i++)//执行写入线圈操作 | |||
{ | |||
Write_Coil_date(Requst_Message[i], Write_Number, Start_Address); | |||
Write_Number -= 8; | |||
Start_Address += 8; | |||
Write_Coil_date(Requst_Message[i], write_Number, start_Address); | |||
write_Number -= 8; | |||
start_Address += 8; | |||
} | |||
Response_Message[0] = Device_ID; | |||
Response_Message[1] = Requst_Message[1]; | |||
@@ -190,11 +189,10 @@ void Create_0x0F_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message | |||
Response_Message[3] = Requst_Message[3]; | |||
Response_Message[4] = Requst_Message[4]; | |||
Response_Message[5] = Requst_Message[5]; | |||
UINT16 CRC_date = CRC_16(Response_Message, 6); | |||
Response_Message[6] = CRC_date >> 8;//CRC_H | |||
Response_Message[7] = (UINT8)CRC_date; //CRC_L | |||
UINT16 crc_date = CRC_16(Response_Message, 6); | |||
Response_Message[6] = crc_date >> 8;//CRC_H | |||
Response_Message[7] = (UINT8)crc_date; //CRC_L | |||
Response_Message_Len = 8; | |||
} | |||
else //地址超限 | |||
{ | |||
@@ -210,15 +208,14 @@ void Create_0x0F_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message | |||
**********************************************************************************************/ | |||
void Create_0x10_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message) | |||
{ | |||
unsigned int Start_Address = Requst_Message[2] << 8 | Requst_Message[3]; | |||
unsigned int Address_range = Start_Address + (Requst_Message[4] << 8 | Requst_Message[5]); | |||
if (Address_range < MAX_Address)//判断地址是否超限 | |||
unsigned int start_Address = Requst_Message[2] << 8 | Requst_Message[3]; | |||
unsigned int address_range = start_Address + (Requst_Message[4] << 8 | Requst_Message[5]); | |||
if (address_range < MAX_Address)//判断地址是否超限 | |||
{ | |||
unsigned int Write_Number = Requst_Message[4] << 8 | Requst_Message[5];//要写入的寄存器个数 | |||
for (int i = 7; i < Requst_Message[6] + 7; i = i + 2)//执行写入寄存器操作 | |||
{ | |||
Register[Start_Address] = Requst_Message[i] << 8 | Requst_Message[i+1]; | |||
Start_Address++; | |||
Register[start_Address] = Requst_Message[i] << 8 | Requst_Message[i + 1]; | |||
start_Address++; | |||
} | |||
Response_Message[0] = Device_ID; | |||
Response_Message[1] = Requst_Message[1]; | |||
@@ -226,9 +223,9 @@ void Create_0x10_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message | |||
Response_Message[3] = Requst_Message[3]; | |||
Response_Message[4] = Requst_Message[4]; | |||
Response_Message[5] = Requst_Message[5]; | |||
UINT16 CRC_date = CRC_16(Response_Message, 6); | |||
Response_Message[6] = CRC_date >> 8;//CRC_H | |||
Response_Message[7] = (UINT8)CRC_date; //CRC_L | |||
UINT16 crc_date = CRC_16(Response_Message, 6); | |||
Response_Message[6] = crc_date >> 8;//CRC_H | |||
Response_Message[7] = (UINT8)crc_date; //CRC_L | |||
Response_Message_Len = 8; | |||
} | |||
else //地址超限 | |||
@@ -245,11 +242,11 @@ void Create_0x10_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message | |||
* 返回值 : true CRC校验通过 | |||
* false CRC校验不通过 | |||
**********************************************************************************************/ | |||
bool Check_Requst_Message_CRC(UINT8 *Requst_Message, DWORD Read_len) | |||
bool Check_Requst_Message_CRC(UINT8 *Requst_Message, DWORD read_len) | |||
{ | |||
UINT16 CRC_data = CRC_16(Requst_Message, Read_len-2); | |||
UINT16 Message_CRC = Requst_Message[Read_len - 2] << 8 | Requst_Message[Read_len - 1]; | |||
if (CRC_data != Message_CRC) | |||
UINT16 crc_data = CRC_16(Requst_Message, read_len - 2); | |||
UINT16 message_crc = Requst_Message[read_len - 2] << 8 | Requst_Message[read_len - 1]; | |||
if (crc_data != message_crc) | |||
return false; | |||
return true; | |||
} | |||
@@ -261,18 +258,18 @@ bool Check_Requst_Message_CRC(UINT8 *Requst_Message, DWORD Read_len) | |||
* 返回值 : true 长度校验通过 | |||
* false 长度校验不通过 | |||
**********************************************************************************************/ | |||
bool Check_Requst_Message_Len(UINT8 *Requst_Message, DWORD Read_len) | |||
bool Check_Requst_Message_Len(UINT8 *Requst_Message, DWORD read_len) | |||
{ | |||
if (Requst_Message[1] == 0x01 || Requst_Message[1] == 0x03) | |||
{ | |||
if (Read_len != 8) | |||
if (read_len != 8) | |||
return false; | |||
} | |||
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); | |||
if (Requst_Message[6] != Count_len || Read_len != Count_len + 9) | |||
unsigned int number = Requst_Message[4] << 8 | Requst_Message[5]; | |||
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; | |||
@@ -287,25 +284,25 @@ bool Check_Requst_Message_Len(UINT8 *Requst_Message, DWORD Read_len) | |||
**********************************************************************************************/ | |||
bool Check_Operation_Number_Requst_Message(UINT8 *Requst_Message) | |||
{ | |||
unsigned int Operation_Number = Requst_Message[4] << 8 | Requst_Message[5]; | |||
unsigned int operation_number = Requst_Message[4] << 8 | Requst_Message[5]; | |||
if (Requst_Message[1] == 0x01) | |||
{ | |||
if (Operation_Number == 0 || Operation_Number > 2000) | |||
if (operation_number == 0 || operation_number > 2000) | |||
return false; | |||
} | |||
if (Requst_Message[1] == 0x03) | |||
{ | |||
if (Operation_Number == 0 || Operation_Number > 125) | |||
if (operation_number == 0 || operation_number > 125) | |||
return false; | |||
} | |||
if (Requst_Message[1] == 0x0F) | |||
{ | |||
if (Operation_Number < 1 || Operation_Number > 1968) | |||
if (operation_number < 1 || operation_number > 1968) | |||
return false; | |||
} | |||
if (Requst_Message[1] == 0x10) | |||
{ | |||
if (Operation_Number < 1 || Operation_Number > 123) | |||
if (operation_number < 1 || operation_number > 123) | |||
return false; | |||
} | |||
return true; | |||
@@ -317,20 +314,20 @@ bool Check_Operation_Number_Requst_Message(UINT8 *Requst_Message) | |||
* 返回值 : true 生成响应报文 | |||
* false 不生成响应报文 | |||
**********************************************************************************************/ | |||
bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD Read_len) | |||
bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD read_len) | |||
{ | |||
if (Requst_Message[0] != Device_ID) //检查设备ID一致 | |||
return false; | |||
if (Read_len < 8 || Read_len > 256) | |||
if (read_len < 8 || read_len > 256) | |||
return false; | |||
if (!Check_Requst_Message_CRC(Requst_Message, Read_len))//CRC校验报文是否正确 | |||
if (!Check_Requst_Message_CRC(Requst_Message, read_len))//CRC校验报文是否正确 | |||
return false; | |||
if (RTU_Enable == 0) | |||
{ | |||
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x04); | |||
return true; | |||
} | |||
if (!Check_Requst_Message_Len(Requst_Message, Read_len) || !Check_Operation_Number_Requst_Message(Requst_Message))//检查请求报文长度是否正确 | |||
if (!Check_Requst_Message_Len(Requst_Message, read_len) || !Check_Operation_Number_Requst_Message(Requst_Message))//检查请求报文长度是否正确 | |||
{ | |||
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x03); | |||
return true; | |||
@@ -347,97 +344,35 @@ bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWO | |||
} | |||
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(); | |||
BYTE Stop_Bits = Input_Stop_Bits(Date_Bits); | |||
BYTE Parity = Input_Parity(); | |||
Handle_Com = Init_COM((LPCTSTR)COMM.c_str(), Baud_Rate, Date_Bits, Stop_Bits, Parity); | |||
if (Handle_Com == INVALID_HANDLE_VALUE) | |||
{ | |||
cout << "初始化串口失败,请重新输入设备信息\n" << endl; | |||
} | |||
else | |||
{ | |||
printf("初始化串口成功\n"); | |||
break; | |||
} | |||
} | |||
return Handle_Com; | |||
} | |||
int Modbus_RTU_Salve(void) | |||
{ | |||
UINT8 Requst_Message[MAX_NUMBER]; | |||
UINT8 Response_Message[MAX_NUMBER]; | |||
DWORD requst_message_len = 0; | |||
HANDLE Handle_Com = Input_Parameter(); | |||
Init_Coil_Register(); | |||
DWORD Read_len; | |||
int Count = 0; | |||
while (true) | |||
{ | |||
PurgeComm(Handle_Com, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT);//清除缓存 | |||
BOOL Read_flage = ReadFile(Handle_Com, Requst_Message, 300, &Read_len, NULL); //阻塞等待接收请求报文 | |||
if (Read_flage && (Read_len > 0)) | |||
if (!Recv_date(&Handle_Com, Requst_Message, &requst_message_len))//接收 | |||
{ | |||
if (Create_Response_Message(Requst_Message, Response_Message, Read_len)) | |||
{ | |||
while (!SendData(Handle_Com, (char*)Response_Message, Response_Message_Len)) | |||
{ | |||
Count++; | |||
printf("发送失败,重新发送第%d次\n",Count); | |||
if (Count > 4) | |||
{ | |||
break; | |||
} | |||
} | |||
printf("主站请求 :"); | |||
for (unsigned int i = 0; i < Read_len; i++) | |||
{ | |||
printf("%02x ", Requst_Message[i]); | |||
} | |||
printf("\n"); | |||
printf("从站响应 :"); | |||
for (unsigned int i = 0; i < Response_Message_Len; i++) | |||
{ | |||
printf("%02x ", Response_Message[i]); | |||
} | |||
printf("\n\n"); | |||
//Log_Note(Requst_Message, 0, Read_len); | |||
//Log_Note(Response_Message, 1, Response_Message_Len); | |||
} | |||
else | |||
continue; | |||
break;//用户选择退出 | |||
} | |||
else | |||
if (requst_message_len == 0) | |||
continue;//长度为0 重新连接了 | |||
if (Create_Response_Message(Requst_Message, Response_Message, requst_message_len))//解析 | |||
{ | |||
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) | |||
if(!SendData(Handle_Com, (char*)Response_Message, Response_Message_Len))//发送 | |||
{ | |||
CloseHandle(Handle_Com); | |||
printf("发送响应报文失败\n"); | |||
continue; | |||
} | |||
else | |||
break; | |||
Handle_Com = Input_Parameter(); | |||
Printf_Message(Requst_Message, 1, requst_message_len); | |||
Printf_Message(Response_Message, 0, Response_Message_Len); | |||
} | |||
else | |||
continue;//无响应 | |||
} | |||
CloseHandle(Handle_Com); | |||
getchar(); | |||
@@ -6,6 +6,7 @@ | |||
#define MAX_Address 9999 | |||
#define MAX_NUMBER 300 | |||
int Modbus_RTU_Salve(void); | |||
bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD Read_len); | |||
void Init_Coil_Register(void); | |||
@@ -8,9 +8,9 @@ | |||
* stop_bit : 停止位 | |||
* parity : 奇偶校验。默认为无校验。NOPARITY 0; ODDPARITY 1;EVENPARITY 2 | |||
********************************************************************************************/ | |||
HANDLE Init_COM(LPCTSTR Port, int baud_rate, BYTE date_bits, BYTE stop_bit, BYTE parity) | |||
HANDLE Init_COM(LPCTSTR port, int baud_rate, BYTE date_bits, BYTE stop_bit, BYTE parity) | |||
{ | |||
HANDLE Handle_Com = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);//同步方式打开串口 | |||
HANDLE Handle_Com = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);//同步方式打开串口 | |||
if (INVALID_HANDLE_VALUE == Handle_Com) | |||
{ | |||
return INVALID_HANDLE_VALUE; | |||
@@ -41,7 +41,8 @@ HANDLE Init_COM(LPCTSTR Port, int baud_rate, BYTE date_bits, BYTE stop_bit, BYTE | |||
dcb.fParity = TRUE; //奇偶校验开启 | |||
dcb.Parity = parity; //校验模式 | |||
} | |||
cout << SetCommState(Handle_Com, &dcb) << endl; | |||
if (!SetCommState(Handle_Com, &dcb)) | |||
return INVALID_HANDLE_VALUE; | |||
PurgeComm(Handle_Com, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT);//清除缓存 | |||
//设置串口读写时间 | |||
COMMTIMEOUTS CommTimeOuts; | |||
@@ -65,49 +66,58 @@ HANDLE Init_COM(LPCTSTR Port, int baud_rate, BYTE date_bits, BYTE stop_bit, BYTE | |||
* data : 要写入的数据 | |||
* len : 写入数据的长度 | |||
**********************************************************************************************/ | |||
bool SendData(HANDLE m_hComm, char* data, int len) | |||
bool SendData(HANDLE m_hcomm, char* data, int len) | |||
{ | |||
if (m_hComm == INVALID_HANDLE_VALUE) | |||
if (m_hcomm == INVALID_HANDLE_VALUE) | |||
return FALSE; | |||
//清空串口 | |||
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR); | |||
//写串口 | |||
PurgeComm(m_hcomm, PURGE_RXCLEAR | PURGE_TXCLEAR); | |||
DWORD dwWrite = 0; | |||
DWORD dwRet = WriteFile(m_hComm, data, len, &dwWrite, NULL); | |||
//清空串口 | |||
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR); | |||
if (!dwRet) | |||
return FALSE; | |||
return TRUE; | |||
int count = 0; | |||
while (!WriteFile(m_hcomm, data, len, &dwWrite, NULL)) | |||
{ | |||
count++; | |||
if (count > 4) | |||
return false; | |||
} | |||
return true; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : Ms延时器 | |||
* 描述 : ms级准确延时 | |||
* 输入 : lTime 延时的ms数 | |||
* 返回值 : 无 | |||
**********************************************************************************************/ | |||
void MSleep(long lTime) | |||
bool Abnormal_Connection(HANDLE *handle_com) | |||
{ | |||
LARGE_INTEGER litmp; | |||
LONGLONG QPart1, QPart2; | |||
double dfMinus, dfFreq, dfTim, dfSpec; | |||
QueryPerformanceFrequency(&litmp); | |||
dfFreq = (double)litmp.QuadPart; | |||
QueryPerformanceCounter(&litmp); | |||
QPart1 = litmp.QuadPart; | |||
dfSpec = 0.000001*lTime; | |||
printf("设备端口异常,请检查设备连接状态\n"); | |||
printf("**************************** Press Enter To Contioun ****************************\n"); | |||
getchar(); | |||
system("cls"); | |||
printf("是否重新连接端口: 1 重新连接 0 关闭本软件\n"); | |||
int flage = 0; | |||
do | |||
{ | |||
QueryPerformanceCounter(&litmp); | |||
QPart2 = litmp.QuadPart; | |||
dfMinus = (double)(QPart2 - QPart1); | |||
dfTim = dfMinus / dfFreq; | |||
} while (dfTim<dfSpec); | |||
cin >> flage; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (!(flage == 0 || flage == 1)); | |||
if (flage == 0) | |||
{ | |||
return false; | |||
} | |||
CloseHandle(*handle_com); | |||
*handle_com = Input_Parameter(); | |||
return true; | |||
} | |||
bool Recv_date(HANDLE *handle_com, UINT8 *Requst_Message, DWORD *read_len) | |||
{ | |||
PurgeComm(*handle_com, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT);//清除缓存 | |||
BOOL read_flage = ReadFile(*handle_com, Requst_Message, 300, &(*read_len), NULL); //阻塞等待接收请求报文 | |||
if (read_flage && (*read_len > 0)) | |||
{ | |||
return true; | |||
} | |||
if (!Abnormal_Connection(handle_com)) | |||
return false; | |||
return true; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 检查端口名称 | |||
* 描述 : 判断端口名称是否正确 | |||
@@ -115,20 +125,20 @@ void MSleep(long lTime) | |||
* 返回值 : true 端口名正确 | |||
* false 端口名错误 | |||
**********************************************************************************************/ | |||
bool Check_Input_COMM(string Comm) | |||
bool Check_Input_COMM(string comm) | |||
{ | |||
string compare1 = "com"; | |||
string compare2 = "COM"; | |||
for (unsigned int i = 0; i < 3; i++) | |||
{ | |||
if (Comm[i] != compare1[i] && Comm[i] != compare2[i]) | |||
if (comm[i] != compare1[i] && comm[i] != compare2[i]) | |||
return false; | |||
} | |||
if (Comm[3] == 0x30) | |||
if (comm[3] == 0x30) | |||
return false; | |||
for (unsigned int i = 4; i < Comm.length(); i++) | |||
for (unsigned int i = 4; i < comm.length(); i++) | |||
{ | |||
if (Comm[i] >= 0x30 && Comm[i] <= 0x39) | |||
if (comm[i] >= 0x30 && comm[i] <= 0x39) | |||
continue; | |||
} | |||
return true; | |||
@@ -143,7 +153,7 @@ bool Check_Input_COMM(string Comm) | |||
string Input_COMM(void) | |||
{ | |||
int flage = 1; | |||
string Comm; | |||
string comm; | |||
do | |||
{ | |||
if (flage == 1) | |||
@@ -153,11 +163,11 @@ string Input_COMM(void) | |||
} | |||
else | |||
printf("请重新输入端口名称:"); | |||
cin >> Comm; | |||
cin >> comm; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (!Check_Input_COMM(Comm)); | |||
return Comm; | |||
} while (!Check_Input_COMM(comm)); | |||
return comm; | |||
} | |||
/********************************************************************************************* | |||
@@ -167,12 +177,12 @@ string Input_COMM(void) | |||
* 返回值 : true 波特率正确 | |||
* false 波特率错误 | |||
**********************************************************************************************/ | |||
bool Check_Input_Baud_Rate(unsigned int Baud_Rate) | |||
bool Check_Input_Baud_Rate(unsigned int baud_rate) | |||
{ | |||
unsigned int Compare_Baud_Rate[9] = {300,600,1200,2400,4800,9600,14400,19200,38400}; | |||
unsigned int compare_baud_rate[9] = {300,600,1200,2400,4800,9600,14400,19200,38400}; | |||
for (int i = 0; i < 9; i++) | |||
{ | |||
if (Baud_Rate == Compare_Baud_Rate[i]) | |||
if (baud_rate == compare_baud_rate[i]) | |||
return true; | |||
} | |||
return false; | |||
@@ -186,7 +196,7 @@ bool Check_Input_Baud_Rate(unsigned int Baud_Rate) | |||
**********************************************************************************************/ | |||
unsigned int Input_Baud_Rate(void) | |||
{ | |||
unsigned int Baud_Rate; | |||
unsigned int baud_rate; | |||
int flage = 1; | |||
printf("支持的波特率有:300,600,1200,2400,4800,9600,14400,19200,38400 \n"); | |||
do | |||
@@ -198,11 +208,11 @@ unsigned int Input_Baud_Rate(void) | |||
} | |||
else | |||
printf("请重新输入串口波特率:"); | |||
cin >> Baud_Rate; | |||
cin >> baud_rate; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (!Check_Input_Baud_Rate(Baud_Rate)); | |||
return Baud_Rate; | |||
} while (!Check_Input_Baud_Rate(baud_rate)); | |||
return baud_rate; | |||
} | |||
@@ -214,9 +224,9 @@ unsigned int Input_Baud_Rate(void) | |||
**********************************************************************************************/ | |||
BYTE Input_Date_Bits(void) | |||
{ | |||
BYTE Date_Bits; | |||
BYTE date_bits; | |||
int flage = 1; | |||
unsigned int data_bits = 0; | |||
unsigned int data_bits_temp = 0; | |||
printf("支持的数据位有:5,6,7,8 \n"); | |||
do | |||
{ | |||
@@ -227,12 +237,12 @@ BYTE Input_Date_Bits(void) | |||
} | |||
else | |||
printf("请重新输入有效数据位:"); | |||
cin >> data_bits; | |||
cin >> data_bits_temp; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (!(data_bits == 5 || data_bits == 6 || data_bits == 7 || data_bits == 8)); | |||
Date_Bits = (BYTE)data_bits; | |||
return Date_Bits; | |||
} while (!(data_bits_temp == 5 || data_bits_temp == 6 || data_bits_temp == 7 || data_bits_temp == 8)); | |||
date_bits = (BYTE)data_bits_temp; | |||
return date_bits; | |||
} | |||
/********************************************************************************************* | |||
@@ -243,13 +253,13 @@ BYTE Input_Date_Bits(void) | |||
* 返回值 : true 停止位正确 | |||
* false 停止位错误 | |||
**********************************************************************************************/ | |||
bool Check_Input_Stop_Bits(BYTE Date_Bits, BYTE Stop_Bits) | |||
bool Check_Input_Stop_Bits(BYTE date_bits, BYTE stop_bits) | |||
{ | |||
if (Stop_Bits == 0 || Stop_Bits == 1 || Stop_Bits == 2) | |||
if (stop_bits == 0 || stop_bits == 1 || stop_bits == 2) | |||
{ | |||
if (Stop_Bits == 1 && (Date_Bits == 6 || Date_Bits == 7 || Date_Bits == 8)) | |||
if (stop_bits == 1 && (date_bits == 6 || date_bits == 7 || date_bits == 8)) | |||
return false; | |||
if (Stop_Bits == 2 && Date_Bits == 5) | |||
if (stop_bits == 2 && date_bits == 5) | |||
return false; | |||
} | |||
else | |||
@@ -266,11 +276,11 @@ bool Check_Input_Stop_Bits(BYTE Date_Bits, BYTE Stop_Bits) | |||
* Date_Bits=5时 Stop_Bits不能为2 | |||
* 返回值 : Stop_Bits 数据位 | |||
**********************************************************************************************/ | |||
BYTE Input_Stop_Bits(BYTE Date_Bits) | |||
BYTE Input_Stop_Bits(BYTE date_bits) | |||
{ | |||
BYTE Stop_Bits; | |||
BYTE stop_bits; | |||
int flage = 1; | |||
unsigned int stop_bits = 0; | |||
unsigned int temp = 0; | |||
printf("支持的停止位有:0,1,2 \n"); | |||
do | |||
{ | |||
@@ -281,12 +291,12 @@ BYTE Input_Stop_Bits(BYTE Date_Bits) | |||
} | |||
else | |||
printf("请重新输入停止位:"); | |||
cin >> stop_bits; | |||
cin >> temp; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (!Check_Input_Stop_Bits(Date_Bits, (BYTE)stop_bits)); | |||
Stop_Bits = (BYTE)stop_bits; | |||
return Stop_Bits; | |||
} while (!Check_Input_Stop_Bits(date_bits, (BYTE)temp)); | |||
stop_bits = (BYTE)temp; | |||
return stop_bits; | |||
} | |||
/********************************************************************************************* | |||
@@ -297,9 +307,9 @@ BYTE Input_Stop_Bits(BYTE Date_Bits) | |||
**********************************************************************************************/ | |||
BYTE Input_Parity(void) | |||
{ | |||
BYTE Parity; | |||
BYTE parity; | |||
int flage = 1; | |||
unsigned int parity = 0; | |||
unsigned int temp = 0; | |||
printf("支持的校验位有:0- 无校验 1- 奇校验 2- 偶校验 \n"); | |||
do | |||
{ | |||
@@ -310,40 +320,14 @@ BYTE Input_Parity(void) | |||
} | |||
else | |||
printf("请重新输入校验位:"); | |||
cin >> parity; | |||
cin >> temp; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (!(parity == 1 || parity == 0 || parity == 2)); | |||
Parity = (BYTE)parity; | |||
return Parity; | |||
} while (!(temp == 1 || temp == 0 || temp == 2)); | |||
parity = (BYTE)temp; | |||
return parity; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 选择校验位 | |||
* 描述 : 获取串口通信的校验位 | |||
* 输入 : 无 | |||
* 返回值 : Parity 校验位 | |||
**********************************************************************************************/ | |||
unsigned int Input_RTU_Enable(void) | |||
{ | |||
unsigned int RTU_Enable; | |||
int flage = 1; | |||
printf("请选择设备是否故障 0: 故障 1:未故障\n"); | |||
do | |||
{ | |||
if (flage == 1) | |||
{ | |||
printf("请输入故障码:"); | |||
flage = 0; | |||
} | |||
else | |||
printf("请重新输入故障码:"); | |||
cin >> RTU_Enable; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (!(RTU_Enable == 1 || RTU_Enable == 0)); | |||
return RTU_Enable; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 计算写入数据的字节数 | |||
@@ -351,18 +335,18 @@ unsigned int Input_RTU_Enable(void) | |||
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量 | |||
* 输出 : Read_date_number 写入数据的字节数 | |||
*********************************************************************************************/ | |||
unsigned int Count_Read_date_number(int Function_code, unsigned int Operations_Number) | |||
unsigned int Count_Read_date_number(int function_code, unsigned int operations_number) | |||
{ | |||
unsigned int Read_date_number = 0; | |||
if (Function_code == 0x01 || Function_code == 0x0F) //读线圈 | |||
unsigned int read_date_number = 0; | |||
if (function_code == 0x01 || function_code == 0x0F) //读线圈 | |||
{ | |||
Read_date_number = Operations_Number / 8; | |||
if (Operations_Number % 8) | |||
Read_date_number++; | |||
read_date_number = operations_number / 8; | |||
if (operations_number % 8) | |||
read_date_number++; | |||
} | |||
if (Function_code == 0x03 || Function_code == 0x10)//读寄存器 | |||
Read_date_number = Operations_Number * 2; | |||
return Read_date_number; | |||
if (function_code == 0x03 || function_code == 0x10)//读寄存器 | |||
read_date_number = operations_number * 2; | |||
return read_date_number; | |||
} | |||
@@ -372,32 +356,32 @@ unsigned int Count_Read_date_number(int Function_code, unsigned int Operations_N | |||
* 输入 : *Data 计算校验数据 CRC_Len 数据长度 | |||
* 返回值 : Ret_CRC_date CRC校验结果 | |||
**********************************************************************************************/ | |||
UINT16 CRC_16(UINT8 *Data, unsigned int CRC_Len) | |||
UINT16 CRC_16(UINT8 *data, unsigned int crc_len) | |||
{ | |||
UINT16 CRC_date = 0XFFFF;//16位crc寄存器预置 | |||
UINT16 crc_date = 0XFFFF;//16位crc寄存器预置 | |||
UINT16 temp; | |||
unsigned int i = 0, j = 0; | |||
for (i = 0; i < CRC_Len; i++) | |||
for (i = 0; i < crc_len; i++) | |||
{ | |||
temp = *Data & 0X00FF;//将八位数据与CRC寄存器亦或 | |||
Data++; | |||
CRC_date ^= temp; | |||
temp = *data & 0X00FF;//将八位数据与CRC寄存器亦或 | |||
data++; | |||
crc_date ^= temp; | |||
for (j = 0; j < 8; j++) | |||
{ | |||
if (CRC_date & 0X0001)//判断右移出的是不是1,如果是1则与多项式进行异或。 | |||
if (crc_date & 0X0001)//判断右移出的是不是1,如果是1则与多项式进行异或。 | |||
{ | |||
CRC_date >>= 1; | |||
CRC_date ^= 0XA001; | |||
crc_date >>= 1; | |||
crc_date ^= 0XA001; | |||
} | |||
else | |||
{ | |||
CRC_date >>= 1; | |||
crc_date >>= 1; | |||
} | |||
} | |||
} | |||
UINT16 Ret_CRC_date = CRC_date >> 8; | |||
Ret_CRC_date = Ret_CRC_date | CRC_date << 8; | |||
return Ret_CRC_date; | |||
UINT16 ret_crc_date = crc_date >> 8; | |||
ret_crc_date = ret_crc_date | crc_date << 8; | |||
return ret_crc_date; | |||
} | |||
/********************************************************************************************* | |||
@@ -407,17 +391,16 @@ UINT16 CRC_16(UINT8 *Data, unsigned int CRC_Len) | |||
* Message_len 报文数据长度 | |||
* 输出 : 无 | |||
*********************************************************************************************/ | |||
void Log_Note(UINT8 *Message, int flage, int Message_len) | |||
void Log_Note(UINT8 *Message, int flage, int message_len) | |||
{ | |||
FILE *fp = NULL; | |||
time_t timep; | |||
struct tm *p; | |||
time(&timep); | |||
p = gmtime(&timep); | |||
string Recv_str = to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday) | |||
string recv_str = to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday) | |||
+ " " + to_string(8 + p->tm_hour) + ":" + to_string(p->tm_min) + ":" + to_string(p->tm_sec) + " Recv:"; | |||
string Send_str = to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday) | |||
string send_str = to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday) | |||
+ " " + to_string(8 + p->tm_hour) + ":" + to_string(p->tm_min) + ":" + to_string(p->tm_sec) + " Send:"; | |||
/* 打开文件用于读写 */ | |||
@@ -430,8 +413,8 @@ void Log_Note(UINT8 *Message, int flage, int Message_len) | |||
if (flage == 1) | |||
{ | |||
fwrite(Send_str.c_str(), Send_str.length(), 1, fp); | |||
for (int i = 0; i < Message_len; i++) | |||
fwrite(send_str.c_str(), send_str.length(), 1, fp); | |||
for (int i = 0; i < message_len; i++) | |||
{ | |||
fprintf(fp, "%02X ", Message[i]); | |||
} | |||
@@ -439,8 +422,8 @@ void Log_Note(UINT8 *Message, int flage, int Message_len) | |||
} | |||
else | |||
{ | |||
fwrite(Recv_str.c_str(), Recv_str.length(), 1, fp); | |||
for (int i = 0; i < Message_len; i++) | |||
fwrite(recv_str.c_str(), recv_str.length(), 1, fp); | |||
for (int i = 0; i < message_len; i++) | |||
{ | |||
fprintf(fp, "%02X ", Message[i]); | |||
} | |||
@@ -459,7 +442,6 @@ bool cmp(string s1, string s2) | |||
return false; | |||
} | |||
//获取串口号 | |||
void GetComList_Reg(std::vector<string>& comList) | |||
{ | |||
HKEY hkey; | |||
@@ -501,10 +483,51 @@ void GetComm_Name(void) | |||
GetComList_Reg(comList); | |||
sort(comList.begin(), comList.end(), cmp); | |||
printf("当前可用端口:"); | |||
for (int i = 0; i < comList.size(); i++) | |||
for (unsigned int i = 0; i < comList.size(); i++) | |||
{ | |||
cout << comList[i] << " "; | |||
} | |||
printf("\n"); | |||
} | |||
HANDLE Input_Parameter(void) | |||
{ | |||
HANDLE handle_com; | |||
while (true) | |||
{ | |||
GetComm_Name(); | |||
string COMM = Input_COMM(); | |||
unsigned int baud_rate = Input_Baud_Rate(); | |||
BYTE date_bits = Input_Date_Bits(); | |||
BYTE stop_bits = Input_Stop_Bits(date_bits); | |||
BYTE parity = Input_Parity(); | |||
handle_com = Init_COM((LPCTSTR)COMM.c_str(), baud_rate, date_bits, stop_bits, parity); | |||
if (handle_com == INVALID_HANDLE_VALUE) | |||
{ | |||
cout << "初始化串口失败,请重新输入设备信息\n" << endl; | |||
} | |||
else | |||
{ | |||
printf("初始化串口成功\n"); | |||
break; | |||
} | |||
} | |||
return handle_com; | |||
} | |||
void Printf_Message(UINT8 *Message, int flage, int message_len) | |||
{ | |||
if (flage == 1) | |||
printf("主站请求 :"); | |||
else | |||
printf("从站响应 :"); | |||
for (int i = 0; i < message_len; i++) | |||
{ | |||
printf("%02X ", Message[i]); | |||
} | |||
printf("\n"); | |||
if (LOG_NOTE_SWITCH) | |||
Log_Note(Message, flage, message_len); | |||
} | |||
@@ -12,17 +12,14 @@ | |||
#include <tchar.h> | |||
using namespace std; | |||
unsigned int Count_Read_date_number(int Function_code, unsigned int Operations_Number); | |||
HANDLE Init_COM(LPCTSTR Port, int baud_rate, BYTE date_bits, BYTE stop_bit, BYTE parity); | |||
bool SendData(HANDLE m_hComm, char* data, int len); | |||
string Input_COMM(void); | |||
unsigned int Input_Baud_Rate(void); | |||
BYTE Input_Date_Bits(void); | |||
BYTE Input_Stop_Bits(BYTE Date_Bits); | |||
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); | |||
#define LOG_NOTE_SWITCH 1 | |||
HANDLE Input_Parameter(void); | |||
void Printf_Message(UINT8 *Message, int flage, int message_len); | |||
UINT16 CRC_16(UINT8 *data, unsigned int crc_len); | |||
unsigned int Count_Read_date_number(int function_code, unsigned int operations_number); | |||
bool SendData(HANDLE m_hcomm, char* data, int len); | |||
bool Recv_date(HANDLE *handle_com, UINT8 *Requst_Message, DWORD *read_len); | |||
#endif |
@@ -549,3 +549,27 @@ | |||
2020-9-15 18:2:46 Recv:00 01 00 00 00 06 01 0F 08 00 00 01 | |||
2020-9-15 18:3:6 Send:00 02 00 00 00 09 01 10 00 00 00 01 02 00 55 | |||
2020-9-15 18:3:15 Recv:00 02 00 00 00 06 01 10 00 00 00 02 | |||
2020-9-16 13:29:24 Send:00 00 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:30:39 Send:00 00 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:30:46 Send:00 01 00 00 00 06 01 03 00 00 00 01 | |||
2020-9-16 13:31:8 Send:00 02 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:31:33 Send:00 03 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:37:20 Send:00 00 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:38:13 Send:00 00 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:38:16 Recv:11 11 11 01 01 01 01 01 01 | |||
2020-9-16 13:38:24 Send:00 01 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:38:42 Recv:00 01 00 00 00 04 01 01 01 01 | |||
2020-9-16 13:40:12 Send:00 02 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:40:37 Send:00 03 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:41:2 Send:00 04 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:41:5 Recv:00 01 00 00 00 04 01 01 01 01 | |||
2020-9-16 13:41:18 Send:00 05 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:42:27 Send:00 00 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:44:1 Send:00 00 00 00 00 06 01 01 00 01 00 01 | |||
2020-9-16 13:44:8 Send:00 01 00 00 00 06 01 01 00 00 00 02 | |||
2020-9-16 13:44:36 Send:00 02 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-16 13:44:54 Send:00 03 00 00 00 09 01 10 00 00 00 01 02 00 00 | |||
2020-9-17 10:6:54 Send:00 00 00 00 00 09 01 10 00 00 00 01 02 11 11 | |||
2020-9-17 10:6:56 Recv: | |||
2020-9-17 10:10:56 Send:00 01 00 00 00 06 01 01 00 00 00 01 | |||
2020-9-17 10:10:56 Recv: |
@@ -1,116 +1,5 @@ | |||
#include "TCP_client.h" | |||
/********************************************************************************************* | |||
* 功能 : socket版本 | |||
* 描述 : 启动socket服务 | |||
* 输入 : 无 | |||
* 输出 : true 启动成功 | |||
* false 启动失败 | |||
*********************************************************************************************/ | |||
bool InitSocket_Version(void) | |||
{ | |||
WORD sockVersion = MAKEWORD(2, 2);//使用winsocket2.2版本 | |||
WSADATA wsaData; | |||
if (WSAStartup(sockVersion, &wsaData) != 0) | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : IP地址有效性检测 | |||
* 描述 : 检测输入的IP地址是否合法 | |||
* 输入 : IP 输入的IP地址 | |||
* 输出 : true IP地址合法 | |||
* false IP地址非法 | |||
*********************************************************************************************/ | |||
bool Check_IP(string IP) | |||
{ | |||
int s[4]; | |||
string ip = IP; | |||
if (ip.length() < 7 || ip.length() > 15) //长度判定 | |||
return false; | |||
if (sscanf_s(IP.c_str(), "%d.%d.%d.%d", &s[0], &s[1], &s[2], &s[3]) != 4) //IPV4格式正确 | |||
{ | |||
return false; | |||
} | |||
string newip = to_string(s[0]) + "." + to_string(s[1]) + "." + to_string(s[2]) + "." + to_string(s[3]); | |||
if (ip != newip) //前导0 | |||
return false; | |||
if ((s[0] & 0xffffff00) || (s[1] & 0xffffff00) || (s[2] & 0xffffff00) || (s[3] & 0xffffff00)) //判断每一段大小是否符合要求 | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 获取从站IP地址和端口号 | |||
* 描述 : 终端输入从站IP地址和端口号 | |||
* 输入 : IP 地址 (IPV4) | |||
* *Port_number 端口号(1-65535) | |||
* 输出 : 无 | |||
*********************************************************************************************/ | |||
void Input_IP(string& IP, unsigned int *Port_number) | |||
{ | |||
int i = 1; | |||
do | |||
{ | |||
if (i == 1) | |||
{ | |||
cout << "请输入从站IP:"; | |||
i = 0; | |||
} | |||
else | |||
cout << "IP地址格式不正确,请重新输入从站IP:"; | |||
cin >> IP; | |||
} while (!Check_IP(IP)); | |||
i = 1; | |||
cout << "IP地址输格式入正确,请输入从站端口号:"; | |||
do | |||
{ | |||
if (i != 1) | |||
cout << "请重新输入从站端口号:"; | |||
cin >> *Port_number; | |||
i = 0; | |||
} while (*Port_number == 0 || *Port_number > 65535); //端口不能为0 ,端口号范围1---65535 | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 初始化客户端 | |||
* 描述 : 根据终端输入从站IP地址和端口号连接对应的服务器,设置超时时间 | |||
* 输入 : IP 地址 (IPV4) | |||
* Port_number 端口号(1-65535) | |||
* 输出 : ClientSocket 连接成功的套接字 | |||
*********************************************************************************************/ | |||
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); | |||
sockaddr_in Serversock_in; | |||
Serversock_in.sin_addr.S_un.S_addr = inet_addr(IP.c_str()); | |||
Serversock_in.sin_family = AF_INET; | |||
Serversock_in.sin_port = htons(Port_number); | |||
if(SOCKET_ERROR == connect(ClientSocket, (SOCKADDR*)&Serversock_in, sizeof(SOCKADDR))) | |||
{ | |||
cout << "尝试连接TCP从站失败" << endl; | |||
return INVALID_SOCKET; | |||
} | |||
cout << "连接TCP从站成功" << endl; | |||
TIMEVAL timeout; | |||
timeout.tv_sec = 60000; //ms | |||
timeout.tv_usec = 0; //us | |||
setsockopt(ClientSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));//设置接收超时时间 | |||
return ClientSocket; | |||
} | |||
UINT16 Transmission_Indicator = 0x00; //事务号 | |||
/********************************************************************************************* | |||
* 功能 : 打印读取从站的线圈状态 | |||
@@ -122,14 +11,14 @@ void Printf_Coil_date(UINT8 *Response_Message, UINT8 *Request_Message) | |||
{ | |||
printf("从站设备ID %02X 功能码为 %02X\n", Response_Message[6], Response_Message[7]); | |||
unsigned int temp1 = ((Request_Message[8] << 8) | Request_Message[9]); | |||
unsigned int Number = ((Request_Message[10] << 8) | Request_Message[11]); | |||
unsigned int number = ((Request_Message[10] << 8) | Request_Message[11]); | |||
printf("线圈起始地址为%d \n",temp1); | |||
unsigned int temp = temp1; | |||
for (int i = 0; i < Response_Message[8]; i++) | |||
{ | |||
unsigned int temp2 = temp + 7; | |||
if (temp2 > temp1 + Number - 1) | |||
temp2 = temp1 + Number - 1; | |||
if (temp2 > temp1 + number - 1) | |||
temp2 = temp1 + number - 1; | |||
printf("线圈%d --- %d的状态为:%02X \n", temp2, temp, Response_Message[9+i]); | |||
temp = temp + 8; | |||
} | |||
@@ -145,7 +34,6 @@ void Printf_Register_date(UINT8 *Response_Message, UINT8 *Request_Message) | |||
{ | |||
printf("从站设备ID %02X 功能码为 %02X\n", Response_Message[6], Response_Message[7]); | |||
unsigned int temp1 = ((Request_Message[8] << 8) | Request_Message[9]); | |||
unsigned int Number = ((Request_Message[10] << 8) | Request_Message[11]); | |||
printf("寄存器起始地址为%d \n", temp1); | |||
for (int i = 0; i < Response_Message[8]; i = i + 2) | |||
{ | |||
@@ -161,53 +49,64 @@ void Printf_Register_date(UINT8 *Response_Message, UINT8 *Request_Message) | |||
*********************************************************************************************/ | |||
void Printf_Anomaly_date(UINT8 *Response_Message) | |||
{ | |||
UINT8 a = Response_Message[8]; | |||
UINT8 anomaly_code = Response_Message[8]; | |||
printf("从站设备ID %02X 功能码为 %02X\n", Response_Message[6], Response_Message[7]); | |||
switch (a) | |||
switch (anomaly_code) | |||
{ | |||
case 0x01: printf("%02X : 从站设备不支持此功能码\n",a); break; | |||
case 0x02: printf("%02X : 指定的数据地址在从站设备中不存在\n",a); break; | |||
case 0x03: printf("%02X : 指定的数据超过范围或者不允许使用\n",a); break; | |||
case 0x04: printf("%02X : 从站设备处理响应的过程中,出现未知错误等\n",a); break; | |||
case 0x01: printf("%02X : 从站设备不支持此功能码\n", anomaly_code); break; | |||
case 0x02: printf("%02X : 指定的数据地址在从站设备中不存在\n", anomaly_code); break; | |||
case 0x03: printf("%02X : 指定的数据超过范围或者不允许使用\n", anomaly_code); break; | |||
case 0x04: printf("%02X : 从站设备处理响应的过程中,出现未知错误等\n", anomaly_code); break; | |||
default: printf("Unkown Other Error!!!!!\n"); | |||
} | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 检测响应报文长度 | |||
* 描述 : 对响应报文中存放长度字节进行判断和请求报文对比 | |||
* 输入 : Response_Message 响应报文 Request_Message 请求报文 Response_Message_len 接收到的数据长度 | |||
* 输出 : true 长度正常 false 长度异常 | |||
*********************************************************************************************/ | |||
bool Check_Response_Message_len(UINT8 *Response_Message, UINT8 *Request_Message, int Response_Message_len) | |||
bool Check_Response_Message_len(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len) | |||
{ | |||
if ((Response_Message_len - 6) != Response_Message[5]) | |||
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); | |||
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) | |||
if (response_message_len != 12) | |||
return false; | |||
if (Request_Message[7] == 0x01 || Request_Message[7] == 0x03) | |||
{ | |||
if (Respone_Len + 9 != Response_Message_len) | |||
if (respone_Len + 9 != response_message_len) | |||
return false; | |||
if (Respone_Len != Response_Message[8]) | |||
if (respone_Len != Response_Message[8]) | |||
return false; | |||
} | |||
return true; | |||
} | |||
bool Printf_Analysis_Outcome(UINT8 *Response_Message, UINT8 *Request_Message) | |||
{ | |||
switch (Response_Message[7]) | |||
{ | |||
case 0x01:Printf_Coil_date(Response_Message, Request_Message); break; | |||
case 0x03:Printf_Register_date(Response_Message, Request_Message); break; | |||
case 0x0F:printf("成功写入从站线圈%d个\n", ((Request_Message[10] << 8) | Request_Message[11])); break; | |||
case 0x10:printf("成功写入从站寄存器%d个\n", ((Request_Message[10] << 8) | Request_Message[11])); break; | |||
default: return false; | |||
} | |||
return true; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 判断响应报文是否可以正常解析 | |||
* 描述 : 通过长度和异常码等判定该响应报文是否可以解析 | |||
* 输入 : Response_Message 响应报文 Request_Message请求报文 Response_Message_len 响应报文长度 | |||
* 输出 : true可以正常解析 false 无法解析 | |||
*********************************************************************************************/ | |||
bool Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, int Response_Message_len) | |||
bool Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len) | |||
{ | |||
if (Response_Message_len < 9) | |||
if (response_message_len < 9 || response_message_len > 260) | |||
return false; | |||
for (int i = 0; i < 7; i++) | |||
{ | |||
@@ -221,7 +120,7 @@ bool Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, | |||
if (Response_Message[7] == Request_Message[7] + 0x80)//先处理异常响应 | |||
{ | |||
if (Response_Message_len == 9) | |||
if (response_message_len == 9) | |||
{ | |||
Printf_Anomaly_date(Response_Message); | |||
return true; | |||
@@ -239,161 +138,165 @@ bool Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, | |||
return false; | |||
} | |||
} | |||
if (!Check_Response_Message_len(Response_Message, Request_Message, Response_Message_len)) | |||
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) | |||
Printf_Register_date(Response_Message, Request_Message); | |||
else if (Response_Message[7] == 0x0F) | |||
printf("成功写入从站线圈%d个\n", ((Request_Message[10] << 8) | Request_Message[11])); | |||
else if (Response_Message[7] == 0x10) | |||
printf("成功写入从站寄存器%d个\n", ((Request_Message[10] << 8) | Request_Message[11])); | |||
//打印解析结果 | |||
return Printf_Analysis_Outcome(Response_Message, Request_Message); | |||
} | |||
void Printf_Message(UINT8 *Message,int flage, int message_len) | |||
{ | |||
if (flage == 1) | |||
printf("主站请求 :"); | |||
else | |||
return false; | |||
return true; | |||
printf("从站响应 :"); | |||
for (int i = 0; i < message_len; i++) | |||
{ | |||
printf("%02x ", Message[i]); | |||
} | |||
printf("\n"); | |||
if (LOG_NOTE_SWITCH) | |||
Log_Note(Message, flage, message_len); | |||
} | |||
void Clear_buf(SOCKET ClientSocket) | |||
/********************************************************************************************* | |||
* 功能 : 生成MBAP报头 | |||
* 描述 : MBAP报文头的包括的内容: | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* | 域 | 长度 | 客户机 | 服务器 | 描述 | | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* |事务元标识符 | 2个字节 | 启动 | 复制 |请求/响应事务处理的识别码 | | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* |协议标识符 | 2个字节 | 启动 | 复制 |0=MODBUS 协议 | | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* | 长度 | 2个字节 | 启动 | 启动 |以下字节的数量 | | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* |单元标识符 | 1个字节 | 启动 | 复制 |连接的远程从站的识别码 | | |||
* 输入 : 无 | |||
* 输出 : MBAP报文头内容 | |||
*********************************************************************************************/ | |||
void Create_MBAP(UINT8 *Message, int function_code, unsigned int operations_number) | |||
{ | |||
unsigned long bytesToRecv; | |||
char temp[500]; | |||
do | |||
Message[0] = Transmission_Indicator >> 8;//事务号 | |||
Message[1] = (UINT8)Transmission_Indicator; | |||
Transmission_Indicator++; | |||
Message[2] = 0x00; //Modbus协议标识 | |||
Message[3] = 0x00; | |||
Message[4] = 0x00;//后续字节长度 | |||
Message[5] = Count_Write_date_number(function_code, operations_number) + 0x06; | |||
if (function_code == 0x0F || function_code == 0x10)//0f/10功能码后续字节数多1 | |||
{ | |||
Message[5] = Message[5] + 1; | |||
} | |||
Message[6] = DEVICE_ID; | |||
} | |||
ioctlsocket(ClientSocket, FIONREAD, &bytesToRecv); | |||
if (bytesToRecv != 0)//不等于0时进行清理操作 | |||
{ | |||
if (bytesToRecv > 500) | |||
{ | |||
recv(ClientSocket, temp, 500, 0); | |||
} | |||
else | |||
recv(ClientSocket, temp, bytesToRecv, 0); | |||
} | |||
} while (bytesToRecv != 0); | |||
/********************************************************************************************* | |||
* 功能 : 字符串转UINT8类型 | |||
* 描述 : 根据写入数量和功能码类型输入相应的数据 | |||
* 输入 : *Message 消息帧存放的数组 Write_date 要转换的字符串 | |||
* Message_len消息帧数组的起始位置 | |||
* 输出 : Message_len 消息帧的长度 | |||
*********************************************************************************************/ | |||
int HexStringtoByte(UINT8 *Message, string write_date, int message_len, int function_code, unsigned int operations_Number) | |||
{ | |||
if (write_date.length() == 0) | |||
return message_len; | |||
Message[message_len] = Count_Write_date_number(function_code, operations_Number); | |||
message_len++; | |||
const char *b = write_date.c_str(); | |||
int temp = 0; | |||
for (unsigned int i = 0; i + 3 < write_date.length(); i = i + 3) | |||
{ | |||
sscanf_s(b + i, "%02X", &temp); | |||
Message[message_len] = (UINT8)temp; | |||
message_len++; | |||
} | |||
sscanf_s(b + write_date.length() - 2, "%02X", &temp); | |||
Message[message_len] = (UINT8)temp; | |||
return ++message_len; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 生成TCP模式下的消息帧 | |||
* 描述 : 根据要写入的数据生成消息帧 | |||
* 输入 : *Message 消息帧存放的数组 Write_date 写入数据的字符串 | |||
* Function_code 功能码 Operations_Number 操作数量 Starting_address起始地址 | |||
* 输出 : 消息帧的总长度 | |||
*********************************************************************************************/ | |||
int Create_TCP_Message(UINT8 *Message, int function_code, unsigned int operations_Number, unsigned int starting_address, string write_date) | |||
{ | |||
Create_MBAP(Message, function_code, operations_Number); | |||
Message[7] = function_code;//功能码 | |||
Message[8] = starting_address >> 8;//起始地址H | |||
Message[9] = starting_address;//起始地址L | |||
Message[10] = operations_Number >> 8;//操作数量H | |||
Message[11] = operations_Number;//操作数量L | |||
return HexStringtoByte(Message, write_date, 12, function_code, operations_Number); | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 运行客户端 | |||
* 描述 : 根据终端输入从站IP地址和端口号连接对应的服务器并且生成发送请求等待响应 | |||
* 描述 : 初始化并且生成发送请求等待响应 | |||
* 输入 : 无 | |||
* 输出 : 无 | |||
*********************************************************************************************/ | |||
int Tcp_client() | |||
int Tcp_Client() | |||
{ | |||
SOCKET ClientSocket; | |||
do | |||
{ | |||
ClientSocket = Init_client(); | |||
} while (INVALID_SOCKET == ClientSocket); | |||
SOCKET clientSocket; | |||
UINT8 Request_Message[600]; | |||
memset(Request_Message, 0, 600); | |||
UINT8 Response_Message[600]; | |||
TIMEVAL timeout; | |||
timeout.tv_sec = 0; | |||
timeout.tv_usec = 0; | |||
fd_set reads; | |||
UINT16 Transmission_Indicator = 0x00; | |||
memset(Response_Message, 0, 600); | |||
do | |||
{ | |||
clientSocket = Init_Client(); | |||
} while (INVALID_SOCKET == clientSocket); | |||
while (true) | |||
{ | |||
int Function_code = Input_Function_code(); | |||
unsigned int Operations_Number = Input_Operations_Number(Function_code); | |||
unsigned int Starting_address = Input_Starting_address(); | |||
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] = (UINT8)Transmission_Indicator; | |||
printf("主站请求 :"); | |||
for (int i = 0; i < Request_Message_len; i++) | |||
{ | |||
printf("%02x ", Request_Message[i]); | |||
} | |||
printf("\n"); | |||
Log_Note(Request_Message, 1, Request_Message_len); | |||
Clear_buf(ClientSocket); //清理缓冲区 | |||
int test = send(ClientSocket, (char*)Request_Message, Request_Message_len, 0); | |||
if (Transmission_Indicator == 0xffff) | |||
{ | |||
Transmission_Indicator = 0x00; | |||
} | |||
Transmission_Indicator++; | |||
if (test == (-1)) | |||
int function_code = Input_Function_code();//交互 | |||
unsigned int operations_Number = Input_Operations_number(function_code); | |||
unsigned int starting_address = Input_Starting_address(); | |||
string write_date = Input_Write_date(function_code, operations_Number); | |||
int request_message_len = Create_TCP_Message(Request_Message, function_code, operations_Number, starting_address, write_date);//生成 | |||
if (!Send_date(clientSocket, Request_Message, request_message_len)) //发送 | |||
{ | |||
printf("连接异常,请检查连接状态。\n"); | |||
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) | |||
if (Abnormal_Connection(&clientSocket)) | |||
continue; | |||
else | |||
break; | |||
system("cls"); | |||
do | |||
{ | |||
ClientSocket = Init_client(); | |||
} while (INVALID_SOCKET == ClientSocket); | |||
system("cls"); | |||
continue; | |||
} | |||
memset(Response_Message, 0, 600); | |||
FD_ZERO(&reads); | |||
FD_SET(ClientSocket, &reads); | |||
int Response_Message_len = recv(ClientSocket, (char*)Response_Message, 600, 0); | |||
if (Response_Message_len > 0) | |||
int Response_Message_len = Recv_date(clientSocket, Response_Message);//接收 | |||
Printf_Message(Request_Message, 1, request_message_len); | |||
Printf_Message(Response_Message, 0, Response_Message_len); | |||
if (Response_Message_len) | |||
{ | |||
Log_Note(Response_Message, 0, Response_Message_len); | |||
printf("从站响应 :"); | |||
for (int i = 0; i < Response_Message_len; i++) | |||
{ | |||
printf("%02x ", Response_Message[i]); | |||
} | |||
printf("\n"); | |||
if (!Analysis_Response_Message(Response_Message, Request_Message, Response_Message_len)) | |||
printf("响应报文异常\n\n"); | |||
printf("响应报文数据异常\n"); | |||
} | |||
else if (select(0, &reads, 0, 0, &timeout)) | |||
else if(!Test_Connection_status(clientSocket)) | |||
{ | |||
printf("连接异常,请检查连接状态。\n"); | |||
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) | |||
if (Abnormal_Connection(&clientSocket)) | |||
continue; | |||
else | |||
break; | |||
system("cls"); | |||
do | |||
{ | |||
ClientSocket = Init_client(); | |||
} while (INVALID_SOCKET == ClientSocket); | |||
system("cls"); | |||
continue; | |||
} | |||
else | |||
cout << "响应超时" << endl; | |||
printf("响应超时\n"); | |||
printf("**************************** Press Enter To Contioun ****************************\n"); | |||
getchar(); | |||
system("cls"); | |||
} | |||
//关闭套接字 | |||
closesocket(ClientSocket); | |||
closesocket(clientSocket); | |||
//关闭服务 | |||
WSACleanup(); | |||
return 0; | |||
@@ -4,12 +4,7 @@ | |||
#include "common.h" | |||
bool InitSocket_Version(void); | |||
bool Check_IP(char* IP); | |||
void Input_IP(string& IP, unsigned int *Port_number); | |||
int Tcp_client(); | |||
bool Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, int Response_Message_len); | |||
int Tcp_Client(); | |||
#endif |
@@ -1,6 +1,66 @@ | |||
#include "common.h" | |||
/********************************************************************************************* | |||
* 功能 : IP地址有效性检测 | |||
* 描述 : 检测输入的IP地址是否合法 | |||
* 输入 : IP 输入的IP地址 | |||
* 输出 : true IP地址合法 | |||
* false IP地址非法 | |||
*********************************************************************************************/ | |||
bool Check_IP(string ip) | |||
{ | |||
int s[4]; | |||
if (ip.length() < 7 || ip.length() > 15) //长度判定 | |||
return false; | |||
if (sscanf_s(ip.c_str(), "%d.%d.%d.%d", &s[0], &s[1], &s[2], &s[3]) != 4) //IPV4格式正确 | |||
{ | |||
return false; | |||
} | |||
string newip = to_string(s[0]) + "." + to_string(s[1]) + "." + to_string(s[2]) + "." + to_string(s[3]); | |||
if (ip != newip) //前导0 | |||
return false; | |||
if ((s[0] & 0xffffff00) || (s[1] & 0xffffff00) || (s[2] & 0xffffff00) || (s[3] & 0xffffff00)) //判断每一段大小是否符合要求 | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 获取从站IP地址和端口号 | |||
* 描述 : 终端输入从站IP地址和端口号 | |||
* 输入 : IP 地址 (IPV4) | |||
* *Port_number 端口号(1-65535) | |||
* 输出 : 无 | |||
*********************************************************************************************/ | |||
void Input_IP(string& ip, unsigned int *port_number) | |||
{ | |||
int i = 1; | |||
do | |||
{ | |||
if (i == 1) | |||
{ | |||
cout << "请输入从站IP:"; | |||
i = 0; | |||
} | |||
else | |||
cout << "IP地址格式不正确,请重新输入从站IP:"; | |||
cin >> ip; | |||
} while (!Check_IP(ip)); | |||
i = 1; | |||
cout << "IP地址输格式入正确,请输入从站端口号:"; | |||
do | |||
{ | |||
if (i != 1) | |||
cout << "请重新输入从站端口号:"; | |||
cin >> *port_number; | |||
i = 0; | |||
} while (*port_number == 0 || *port_number > 65535); //端口不能为0 ,端口号范围1---65535 | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 选择功能码 | |||
* 描述 : 在功能码 0x01 0x03 0x0F 0x10中选择一个功能码 | |||
@@ -9,7 +69,7 @@ | |||
*********************************************************************************************/ | |||
int Input_Function_code(void) | |||
{ | |||
int Function_code; | |||
int function_code; | |||
cin >> hex; | |||
int i = 1; | |||
printf("功能码 : 0x01 0x03 0x0F 0x10 \n"); | |||
@@ -23,22 +83,22 @@ int Input_Function_code(void) | |||
} | |||
else | |||
cout << "输入功能码错误,请重新选择的功能码"; | |||
cin >> Function_code; | |||
cin >> function_code; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (Function_code != 0x01 && Function_code != 0x03 && Function_code != 0x0F && Function_code != 0x10); | |||
return Function_code; | |||
} while (function_code != 0x01 && function_code != 0x03 && function_code != 0x0F && function_code != 0x10); | |||
return function_code; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 输入操作起始地址码 | |||
* 描述 : 起始地址码,最大值65535 | |||
* 输入 : 无 | |||
* 输出 : Starting_address 操作起始地址码 | |||
* 输出 : starting_address 操作起始地址码 | |||
*********************************************************************************************/ | |||
unsigned int Input_Starting_address(void) | |||
{ | |||
unsigned int Starting_address; | |||
unsigned int starting_address; | |||
int i = 1; | |||
cin >> dec; | |||
do | |||
@@ -50,22 +110,22 @@ unsigned int Input_Starting_address(void) | |||
} | |||
else | |||
cout << "请重新输入操作(十进制)起始地址"; | |||
cin >> Starting_address; | |||
cin >> starting_address; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (Starting_address > 65535 || Starting_address < 0); | |||
return Starting_address; | |||
} while (starting_address > 65535 || starting_address < 0); | |||
return starting_address; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 输入操作数量 | |||
* 描述 : 操作数量,0x01 1-200 0x03 1-125 0x0xF 1-1968 0x10 1-123 | |||
* 输入 : Function_code 选择的功能码类型 | |||
* 输出 : Operations_Number 对应功能码类型的操作数量 | |||
* 输入 : function_code 选择的功能码类型 | |||
* 输出 : operations_Number 对应功能码类型的操作数量 | |||
*********************************************************************************************/ | |||
unsigned int Input_Operations_Number(int Function_code) | |||
unsigned int Input_Operations_number(int function_code) | |||
{ | |||
unsigned int Operations_Number; | |||
unsigned int operations_Number; | |||
int i = 1; | |||
bool flage = true; | |||
printf(" 功能码 0x01 0x03 0x0F 0x10\n"); | |||
@@ -80,83 +140,82 @@ unsigned int Input_Operations_Number(int Function_code) | |||
} | |||
else | |||
cout << "请重新输入操作(十进制)数量"; | |||
cin >> Operations_Number; | |||
cin >> operations_Number; | |||
cin.clear(); | |||
cin.sync(); | |||
if (Function_code == 0x01 && Operations_Number >= 1 && Operations_Number <= 65535) | |||
if (function_code == 0x01 && operations_Number >= 1 && operations_Number <= 65535) | |||
flage = false; | |||
if (Function_code == 0x03 && Operations_Number >= 1 && Operations_Number <= 65535) | |||
if (function_code == 0x03 && operations_Number >= 1 && operations_Number <= 65535) | |||
flage = false; | |||
if (Function_code == 0x0F && Operations_Number >= 1 && Operations_Number <= 65535) | |||
if (function_code == 0x0F && operations_Number >= 1 && operations_Number <= 65535) | |||
flage = false; | |||
if (Function_code == 0x10 && Operations_Number >= 1 && Operations_Number <= 65535) | |||
if (function_code == 0x10 && operations_Number >= 1 && operations_Number <= 65535) | |||
flage = false; | |||
} while (flage); | |||
return Operations_Number; | |||
return operations_Number; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 检测写入数据 | |||
* 描述 : 检测写入数据格式是否正确 | |||
* 输入 : Write_date 写入的数据 Write_date_number写入数据的组数 | |||
* 输入 : write_date 写入的数据 write_date_number写入数据的组数 | |||
* 输出 : true 写入数据格式正确 | |||
* false 写入数据格式错误 | |||
*********************************************************************************************/ | |||
bool Check_Write_date(string Write_date, int Write_date_number) | |||
bool Check_Write_date(string write_date, int write_date_number) | |||
{ | |||
int Write_date_len = 2 * Write_date_number + Write_date_number - 1; | |||
if (Write_date.length() != Write_date_len) | |||
int write_date_len = 2 * write_date_number + write_date_number - 1; | |||
if (write_date.length() != write_date_len) | |||
return false; | |||
int Space_number = 0; | |||
int j = -1; | |||
for (unsigned int i = 0; i < Write_date.length(); i++) | |||
int space_number = 0; | |||
int temp = -1; | |||
for (unsigned int i = 0; i < write_date.length(); i++) | |||
{ | |||
if (Write_date[i] == 0x20)//空格位置判定 | |||
if (write_date[i] == 0x20)//空格位置判定 | |||
{ | |||
if (i - j == 3) | |||
if (i - temp == 3) | |||
{ | |||
Space_number++; | |||
j = i; | |||
space_number++; | |||
temp = i; | |||
continue; | |||
} | |||
else | |||
return false; | |||
} | |||
if ((Write_date[i] >= 0x30 && Write_date[i] <= 0x39)) // 1-9 | |||
if ((write_date[i] >= 0x30 && write_date[i] <= 0x39)) // 1-9 | |||
continue; | |||
else if ((Write_date[i] >= 0x41 && Write_date[i] <= 0x5A)) //A-Z | |||
else if ((write_date[i] >= 0x41 && write_date[i] <= 0x5A)) //A-Z | |||
continue; | |||
else if ((Write_date[i] >= 0x61 && Write_date[i] <= 0x7A)) //a-z | |||
else if ((write_date[i] >= 0x61 && write_date[i] <= 0x7A)) //a-z | |||
continue; | |||
else | |||
return false; | |||
} | |||
if (Space_number != Write_date_number - 1) | |||
if (space_number != write_date_number - 1) | |||
return false; | |||
return true; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 计算写入数据的字节数 | |||
* 描述 : 通过对应的功能码和操作数量计算对应的数据字节数 | |||
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量 | |||
* 输入 : function_code 选择的功能码类型 operations_Number对应功能码类型的操作数量 | |||
* 输出 : Write_date_number 写入数据的字节数 | |||
*********************************************************************************************/ | |||
unsigned int Count_Write_date_number(int Function_code, unsigned int Operations_Number) | |||
unsigned int Count_Write_date_number(int function_code, unsigned int operations_number) | |||
{ | |||
unsigned int Write_date_number = 0; | |||
if (Function_code == 0x01 || Function_code == 0x03) | |||
return Write_date_number; | |||
if (Function_code == 0x0F) //读线圈 | |||
unsigned int write_date_number = 0; | |||
if (function_code == 0x01 || function_code == 0x03) | |||
return write_date_number; | |||
if (function_code == 0x0F) //读线圈 | |||
{ | |||
Write_date_number = Operations_Number / 8; | |||
if (Operations_Number % 8) | |||
Write_date_number++; | |||
write_date_number = function_code / 8; | |||
if (operations_number % 8) | |||
write_date_number++; | |||
} | |||
if (Function_code == 0x10) | |||
Write_date_number = Operations_Number * 2; | |||
return Write_date_number; | |||
if (function_code == 0x10) | |||
write_date_number = operations_number * 2; | |||
return write_date_number; | |||
} | |||
/********************************************************************************************* | |||
@@ -165,20 +224,20 @@ unsigned int Count_Write_date_number(int Function_code, unsigned int Operations_ | |||
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量 | |||
* 输出 : Respone_len 预期响应的数据字节数 | |||
*********************************************************************************************/ | |||
unsigned int Count_Respone_Len(int Function_code, unsigned int Operations_Number) | |||
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) //读线圈 | |||
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++; | |||
respone_len = operations_number / 8; | |||
if (operations_number % 8) | |||
respone_len++; | |||
} | |||
if (Function_code == 0x03) | |||
Respone_len = Operations_Number * 2; | |||
return Respone_len; | |||
if (function_code == 0x03) | |||
respone_len = operations_number * 2; | |||
return respone_len; | |||
} | |||
/********************************************************************************************* | |||
@@ -187,13 +246,13 @@ unsigned int Count_Respone_Len(int Function_code, unsigned int Operations_Number | |||
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量 | |||
* 输出 : Write_date 写入的数据 | |||
*********************************************************************************************/ | |||
string Input_Write_date(int Function_code, unsigned int Operations_Number) | |||
string Input_Write_date(int function_code, unsigned int operations_Number) | |||
{ | |||
int i = 1; | |||
string Write_date; | |||
unsigned int Write_date_number = Count_Write_date_number(Function_code, Operations_Number); | |||
if (Function_code == 0x01 || Function_code == 0x03) | |||
return Write_date;//读线圈/寄存器不需要输入写入数据 | |||
string write_date; | |||
unsigned int write_date_number = Count_Write_date_number(function_code, operations_Number); | |||
if (function_code == 0x01 || function_code == 0x03) | |||
return write_date;//读线圈/寄存器不需要输入写入数据 | |||
printf("请输入N组写入数据(2位16进制为一组,空格间隔)例如:00 00 01 00 20 05\n"); | |||
do | |||
@@ -201,91 +260,16 @@ string Input_Write_date(int Function_code, unsigned int Operations_Number) | |||
if (i == 1) | |||
{ | |||
i = 0; | |||
printf("请输入%d组写入数据 :", Write_date_number); | |||
printf("请输入%d组写入数据 :", write_date_number); | |||
} | |||
else | |||
printf("请重新输入%d组写入数据 :", Write_date_number); | |||
getline(cin, Write_date); | |||
printf("请重新输入%d组写入数据 :", write_date_number); | |||
getline(cin, write_date); | |||
cin.clear(); | |||
cin.sync(); | |||
} while (!Check_Write_date(Write_date, Write_date_number)); | |||
} while (!Check_Write_date(write_date, write_date_number)); | |||
return Write_date; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 生成MBAP报头 | |||
* 描述 : MBAP报文头的包括的内容: | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* | 域 | 长度 | 客户机 | 服务器 | 描述 | | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* |事务元标识符 | 2个字节 | 启动 | 复制 |请求/响应事务处理的识别码 | | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* |协议标识符 | 2个字节 | 启动 | 复制 |0=MODBUS 协议 | | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* | 长度 | 2个字节 | 启动 | 启动 |以下字节的数量 | | |||
* +-------------+---------+--------+--------+------------------------------+ | |||
* |单元标识符 | 1个字节 | 启动 | 复制 |连接的远程从站的识别码 | | |||
* 输入 : 无 | |||
* 输出 : MBAP报文头内容 | |||
*********************************************************************************************/ | |||
void Crate_MBAP(UINT8 *Message, int Function_code, unsigned int Operations_Number) | |||
{ | |||
Message[0] = 0x00; | |||
Message[1] = 0x00; | |||
Message[2] = 0x00; | |||
Message[3] = 0x00; | |||
Message[4] = 0x00; | |||
Message[5] = Count_Write_date_number(Function_code, Operations_Number) + 0x06; | |||
if (Function_code == 0x0F || Function_code == 0x10) | |||
{ | |||
Message[5] = Message[5] + 1; | |||
} | |||
Message[6] = DEVICE_ID; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 字符串转UINT8类型 | |||
* 描述 : 根据写入数量和功能码类型输入相应的数据 | |||
* 输入 : *Message 消息帧存放的数组 Write_date 要转换的字符串 | |||
* Message_len消息帧数组的起始位置 | |||
* 输出 : Message_len 消息帧的长度 | |||
*********************************************************************************************/ | |||
int HexStringtoByte(UINT8 *Message, string Write_date, int Message_len, int Function_code, unsigned int Operations_Number) | |||
{ | |||
if (Write_date.length() == 0) | |||
return Message_len; | |||
Message[Message_len] = Count_Write_date_number(Function_code, Operations_Number); | |||
Message_len++; | |||
const char *b = Write_date.c_str(); | |||
for (unsigned int i = 0; i + 3 < Write_date.length(); i = i + 3) | |||
{ | |||
sscanf_s(b + i, "%02X", (int *)(Message + Message_len)); | |||
Message_len++; | |||
} | |||
sscanf_s(b + Write_date.length() - 2, "%02X", (int *)(Message + Message_len)); | |||
return ++Message_len; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 生成TCP模式下的消息帧 | |||
* 描述 : 根据要写入的数据生成消息帧 | |||
* 输入 : *Message 消息帧存放的数组 Write_date 写入数据的字符串 | |||
* Function_code 功能码 Operations_Number 操作数量 Starting_address起始地址 | |||
* 输出 : 消息帧的总长度 | |||
*********************************************************************************************/ | |||
int Crate_TCP_Message(UINT8 *Message, int Function_code, unsigned int Operations_Number, unsigned int Starting_address, string Write_date) | |||
{ | |||
Crate_MBAP(Message, Function_code, Operations_Number); | |||
Message[7] = Function_code;//功能码 | |||
Message[8] = Starting_address >> 8;//起始地址H | |||
Message[9] = Starting_address;//起始地址L | |||
Message[10] = Operations_Number >> 8;//操作数量H | |||
Message[11] = Operations_Number;//操作数量L | |||
return HexStringtoByte(Message, Write_date, 12, Function_code, Operations_Number); | |||
return write_date; | |||
} | |||
/********************************************************************************************* | |||
@@ -295,17 +279,16 @@ int Crate_TCP_Message(UINT8 *Message, int Function_code, unsigned int Operations | |||
* Message_len 报文数据长度 | |||
* 输出 : 无 | |||
*********************************************************************************************/ | |||
void Log_Note(UINT8 *Message, int flage, int Message_len) | |||
void Log_Note(UINT8 *Message, int flage, int message_len) | |||
{ | |||
FILE *fp = NULL; | |||
time_t timep; | |||
struct tm *p; | |||
time(&timep); | |||
p = gmtime(&timep); | |||
string Recv_str = to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday) | |||
string recv_str = to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday) | |||
+ " " + to_string(8 + p->tm_hour) + ":" + to_string(p->tm_min) + ":" + to_string(p->tm_sec) + " Recv:"; | |||
string Send_str= to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday) | |||
string send_str= to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday) | |||
+ " " + to_string(8 + p->tm_hour) + ":" + to_string(p->tm_min) + ":" + to_string(p->tm_sec) + " Send:"; | |||
/* 打开文件用于读写 */ | |||
@@ -314,11 +297,10 @@ void Log_Note(UINT8 *Message, int flage, int Message_len) | |||
printf("打开文件失败"); | |||
return ; | |||
} | |||
if (flage == 1) | |||
{ | |||
fwrite(Send_str.c_str(), Send_str.length(), 1, fp); | |||
for (int i = 0; i < Message_len; i++) | |||
fwrite(send_str.c_str(), send_str.length(), 1, fp); | |||
for (int i = 0; i < message_len; i++) | |||
{ | |||
fprintf(fp, "%02X ", Message[i]); | |||
} | |||
@@ -326,8 +308,8 @@ void Log_Note(UINT8 *Message, int flage, int Message_len) | |||
} | |||
else | |||
{ | |||
fwrite(Recv_str.c_str(), Recv_str.length(), 1, fp); | |||
for (int i = 0; i < Message_len; i++) | |||
fwrite(recv_str.c_str(), recv_str.length(), 1, fp); | |||
for (int i = 0; i < message_len; i++) | |||
{ | |||
fprintf(fp, "%02X ", Message[i]); | |||
} | |||
@@ -336,3 +318,137 @@ void Log_Note(UINT8 *Message, int flage, int Message_len) | |||
fclose(fp); | |||
fp = NULL; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : socket版本 | |||
* 描述 : 启动socket服务 | |||
* 输入 : 无 | |||
* 输出 : true 启动成功 | |||
* false 启动失败 | |||
*********************************************************************************************/ | |||
bool InitSocket_Version(void) | |||
{ | |||
WORD sockVersion = MAKEWORD(2, 2);//使用winsocket2.2版本 | |||
WSADATA wsaData; | |||
if (WSAStartup(sockVersion, &wsaData) != 0) | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
/********************************************************************************************* | |||
* 功能 : 初始化客户端 | |||
* 描述 : 根据终端输入从站IP地址和端口号连接对应的服务器,设置超时时间 | |||
* 输入 : 无 | |||
* 输出 : ClientSocket 连接成功的套接字 | |||
*********************************************************************************************/ | |||
SOCKET Init_Client(void) | |||
{ | |||
if (InitSocket_Version() == 0) | |||
{ | |||
printf("启动Socket服务失败,请检查Socket版本"); | |||
return INVALID_SOCKET; | |||
} | |||
string ip_address; | |||
unsigned int port_number; | |||
Input_IP(ip_address, &port_number); | |||
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0); | |||
sockaddr_in serversock_in; | |||
serversock_in.sin_addr.S_un.S_addr = inet_addr(ip_address.c_str()); | |||
serversock_in.sin_family = AF_INET; | |||
serversock_in.sin_port = htons(port_number); | |||
if (SOCKET_ERROR == connect(clientSocket, (SOCKADDR*)&serversock_in, sizeof(SOCKADDR))) | |||
{ | |||
cout << "尝试连接TCP从站失败" << endl; | |||
return INVALID_SOCKET; | |||
} | |||
cout << "连接TCP从站成功" << endl; | |||
TIMEVAL timeout; | |||
timeout.tv_sec = 200; //ms | |||
timeout.tv_usec = 0; //us | |||
setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));//设置接收超时时间 | |||
return clientSocket; | |||
} | |||
void Clear_buf(SOCKET clientSocket) | |||
{ | |||
unsigned long bytesToRecv; | |||
char temp[500]; | |||
do | |||
{ | |||
ioctlsocket(clientSocket, FIONREAD, &bytesToRecv); | |||
if (bytesToRecv != 0)//不等于0时进行清理操作 | |||
{ | |||
if (bytesToRecv > 500) | |||
{ | |||
recv(clientSocket, temp, 500, 0); | |||
} | |||
else | |||
recv(clientSocket, temp, bytesToRecv, 0); | |||
} | |||
} while (bytesToRecv != 0); | |||
} | |||
bool Send_date(SOCKET clientSocket, UINT8 *Request_Message, int request_message_len) | |||
{ | |||
Clear_buf(clientSocket); //清理缓冲区 | |||
int status = send(clientSocket, (char*)Request_Message, request_message_len, 0); | |||
if (status == (-1)) | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
bool Abnormal_Connection(SOCKET *clientSocket) | |||
{ | |||
printf("连接异常,请检查连接状态。\n"); | |||
printf("**************************** Press Enter To Contioun ****************************\n"); | |||
getchar(); | |||
system("cls"); | |||
closesocket(*clientSocket); | |||
WSACleanup(); | |||
printf("是否重新连接服务器: 1 重新连接 0 关闭本软件\n"); | |||
int flage = 0; | |||
do | |||
{ | |||
cin >> flage; | |||
cin.clear(); | |||
cin.sync(); | |||
} while (!(flage == 0 || flage == 1)); | |||
if (flage == 0) | |||
return false; | |||
system("cls"); | |||
do | |||
{ | |||
*clientSocket = Init_Client(); | |||
} while (INVALID_SOCKET == *clientSocket); | |||
system("cls"); | |||
return true; | |||
} | |||
int Recv_date(SOCKET clientSocket, UINT8 *Response_Message) | |||
{ | |||
int Response_Message_len = recv(clientSocket, (char*)Response_Message, 600, 0); | |||
if (Response_Message_len > 0) | |||
{ | |||
return Response_Message_len; | |||
} | |||
return 0; | |||
} | |||
bool Test_Connection_status(SOCKET clientSocket) | |||
{ | |||
TIMEVAL timeout; | |||
timeout.tv_sec = 0; | |||
timeout.tv_usec = 0; | |||
fd_set reads; | |||
FD_ZERO(&reads); | |||
FD_SET(clientSocket, &reads); | |||
if (select(0, &reads, 0, 0, &timeout)) | |||
return false; | |||
else | |||
return true; | |||
} |
@@ -12,20 +12,23 @@ | |||
using namespace std; | |||
#define DEVICE_ID 0x01 //É豸ID | |||
#define LOG_NOTE_SWITCH 1 //ÈÕÖ¾¼Ç¼¿ØÖÆÎ» | |||
int Input_Function_code(void); | |||
unsigned int Input_Starting_address(void); | |||
unsigned int Input_Operations_Number(int Function_code); | |||
bool Check_Write_date(string Write_date, int Write_date_number); | |||
unsigned int Count_Write_date_number(int Function_code, unsigned int Operations_Number); | |||
string Input_Write_date(int Function_code, unsigned int Operations_Number); | |||
void Crate_MBAP(UINT8 *Message, int Function_code, unsigned int Operations_Number); | |||
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); | |||
unsigned int Input_Operations_number(int function_code); | |||
unsigned int Count_Write_date_number(int function_code, unsigned int operations_Number); | |||
string Input_Write_date(int function_code, unsigned int operations_Number); | |||
void Log_Note(UINT8 *Message, int flage, int message_len); | |||
unsigned int Count_Respone_Len(int function_code, unsigned int operations_number); | |||
SOCKET Init_Client(void); | |||
bool Send_date(SOCKET clientSocket, UINT8 *Request_Message, int request_message_len); | |||
bool Abnormal_Connection(SOCKET *clientSocket); | |||
int Recv_date(SOCKET clientSocket, UINT8 *Response_Message); | |||
bool Test_Connection_status(SOCKET clientSocket); | |||
#endif |
@@ -2,7 +2,7 @@ | |||
int main() | |||
{ | |||
Tcp_client(); | |||
Tcp_Client(); | |||
getchar(); | |||
return 0; | |||
} |