A prática do Wireshark captura pacotes de dados de rede e usa programação C para concluir o protocolo modbus e ler dados de temperatura e umidade do servidor em nuvem.


prefácio

Tarefa:
1.

Pratique wireshark para capturar pacotes de rede. Execute o programa "Crazy Chat Room" em dois computadores (laptop win10 host e máquina virtual ubuntu. Selecione o modo bridge para a placa de rede para obter dois endereços IPv4 de sub-rede) e capture pacotes através do wireshark: 1) Analise a conexão de rede deste programa
usando Qual protocolo (TCP, UDP) e qual é o número da porta?
2) Tente encontrar as informações do bate-papo roubado no pacote de captura (caracteres ingleses e caracteres chineses podem ter sofrido algum tipo de conversão de codificação e o pacote de dados não está em texto simples) 3) Se a conexão de rede usar TCP, analise quando
estabelecer uma conexão handshake de 3 vias, handshake de 4 vias quando desconectado; se for UDP, explique por que o programa pode transmitir dados de bate-papo entre vários computadores (somente o mesmo número de sala de bate-papo) ao mesmo tempo?

dois,

Use a programação C para concluir o protocolo modbus e ler os dados de temperatura e umidade do servidor em nuvem:

Software:
Crazy Chat Room :
Link: Crazy Chat Room Código
de extração : 1234
wireshark:
Link: wireshark
Código de extração: 1234
RedPandaDE:
Link: RedPandaDE
Código de extração: 1234


1. Sala de bate-papo maluca

Ao conduzir este experimento, precisamos de dois computadores na mesma rede local.

1. Configure a rede

Painel de Controle---->Rede e Internet---->Central de Rede e Compartilhamento---->Alterar Configurações do Adaptador:
Desative outros gateways, deixando apenas a rede onde os dois computadores estão conectados:

insira a descrição da imagem aqui

2. Crie uma sala

Ambos os computadores precisam baixar o Crazy Chat Room:

Clique em crazychat.exe para criar uma sala:
insira a descrição da imagem aqui
Crie a sala número 8888 e nomeie-a:
insira a descrição da imagem aqui

3. Envie mensagens uns aos outros

insira a descrição da imagem aqui

2. Wireshark captura pacotes de rede

A instalação do wireshark é a próxima e de acordo.

1. Encontre o pacote correspondente

Sempre que enviarmos uma mensagem na sala de bate-papo maluca, o wireshark encontrará imediatamente o pacote cujo endereço IP é o endereço de broadcast 255.255.255.255.
insira a descrição da imagem aqui

A partir da análise de pacotes capturada na figura acima, sabemos que
este programa de bate-papo usa o protocolo UDP e o número de porta 255.255.255.255.

2. Analise as informações no pacote capturado

Clique duas vezes no pacote capturado para visualizar informações específicas:

Números:
insira a descrição da imagem aqui
Inglês:
insira a descrição da imagem aqui
Chinês:

insira a descrição da imagem aqui
insira a descrição da imagem aqui

A partir da análise da figura acima, sabemos que os caracteres e números em inglês podem ser visualizados em texto simples normalmente, mas os caracteres chineses não podem ser visualizados em texto simples depois de codificados. Depois de enviar três códigos hexadecimais chineses idênticos, descobrimos que três bytes codificam um caractere chinês e adivinhe a codificação. O formato é UTF-8.

3. Visão geral do protocolo Modbus

1. O protocolo Modbus é um protocolo de comunicação serial publicado pela Modicon (agora Schneider Electric) em 1979 para o uso da comunicação do controlador lógico programável (PLC). O protocolo Modbus é um protocolo de camada de aplicação, que se tornou o padrão da indústria para protocolos de comunicação no campo industrial e é um método de conexão comumente usado entre dispositivos eletrônicos industriais.
2. Modbus é um protocolo de arquitetura mestre/escravo.Um nó é o nó mestre e outros nós que usam o protocolo Modbus para participar da comunicação são nós escravos.Cada dispositivo escravo tem um endereço exclusivo. Somente o nó designado como nó mestre pode iniciar um comando. Todos os quadros de dados Modbus contêm um código de verificação para garantir a exatidão da transmissão. Os comandos ModBus básicos podem instruir um dispositivo escravo a alterar um valor em um de seus registros, controlar ou ler uma porta de E/S e direcionar o dispositivo a enviar dados de volta em um ou mais de seus registros.

1. Princípio do protocolo Modbus mestre/escravo

O protocolo de link serial Modbus é um protocolo mestre-escravo. Ao mesmo tempo, apenas uma estação mestra pode ser conectada ao barramento e uma ou mais estações escravas (número máximo 247) podem ser conectadas ao mesmo barramento serial. A comunicação Modbus é sempre iniciada pela estação mestre, quando a estação escrava não receber uma solicitação da estação mestre, ela não enviará dados. A estação mestre só pode iniciar uma transação Modbus ao mesmo tempo e as estações escravas não podem se comunicar entre si.

insira a descrição da imagem aqui

2. Estrutura geral do quadro Modbus - unidade de dados de protocolo (PDU)

O protocolo Modbus define uma unidade de dados de protocolo simples (PDU) independente da camada de comunicação subjacente. O mapeamento do protocolo Modbus em um barramento ou rede específica pode introduzir alguns campos adicionais na unidade de dados de aplicação (ADU).

insira a descrição da imagem aqui

3. Dois modos de transmissão serial Modbus

Modo RTU : Cada byte de 8 bits contém dois caracteres hexadecimais de 4 bits.A vantagem é que na mesma taxa de transmissão, mais dados podem ser transmitidos do que ASCII, mas cada mensagem deve estar em fluxo contínuo de dados.

insira a descrição da imagem aqui

Modo ASCII : são necessários 2 caracteres ASCII para cada byte de 8 bits na informação, o que tem a vantagem de permitir que o intervalo de transmissão de caracteres chegue a 1s sem erro;

insira a descrição da imagem aqui

4. Estrutura de comunicação ModbusTCP

Dispositivos de comunicação para Modbus TCP/IP: Dispositivos cliente e servidor Modbus TCP/IP conectados a uma rede TCP/IP.
Dispositivos de interconexão, como pontes, roteadores ou gateways que interconectam redes TCP/IP e sub-redes de link serial.

insira a descrição da imagem aqui

4. A programação C completa o protocolo modbus e lê os dados de temperatura e umidade do servidor em nuvem.

Abra o RedPandaDE e crie um novo projeto:
insira a descrição da imagem aqui

1. Código de configuração

1. Inicialize a dll do soquete e conecte-se à porta correspondente do servidor através do IP:

WORD winsock_version = MAKEWORD(2,2);
	WSADATA wsa_data;
	if (WSAStartup(winsock_version, &wsa_data) != 0) {
    
    
		printf("Failed to init socket!\n");
		return 1;
	}
	
	SOCKET client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (client_socket == INVALID_SOCKET) {
    
    
		printf("Failed to create server socket!\n");
		return 2;
	}
	
	struct sockaddr_in server_addr;
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);
	if (connect(client_socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
    
    
		printf("Failed to connect server: %ld !\n", GetLastError());
		return 3;
	}

2. Gere o código de verificação:

uint16_t CRC_16(uint8_t *temp)
{
    
    
	uint8_t i,j;
	uint16_t CRC_1 = 0xFFFF;          //声明CRC寄存区,也就是步骤1
	for(i = 0;i < 6;i++)       //这里的for循环说的是步骤6中的重复步骤 2 到步骤 5
	{
    
    
		CRC_1 ^= temp[i]; //这里就是步骤2,进行异或运算
		for(j = 0;j < 8;j++)         //用来将异或后的低八位全部移出的for循环
		{
    
    
			if(CRC_1 & 0x01)         //判断低八位的最后一位是否为1,为1时执行下列语句,也就是步骤3说的移位判断与步骤5说的右移8次
			{
    
    
				/*一定要先移位,再异或*/
				CRC_1 >>=1;          //移位后再异或,就是步骤4
				CRC_1 ^= 0xA001;     //0xA001为0x8005的逆序
			}
			else                    //若不为1,则直接移位。
			{
    
    
				CRC_1 >>=1;
			}
		}
	}
	
	//	CRC_1 = (((CRC_1 & 0xFF)<<8) + (CRC_1>>8));
	//	printf("%04x\r\n",CRC_1);     //用于打印检测CRC校验码
	return(CRC_1);
}

3. Obtenha os dados de temperatura e umidade:

int ret = recv(client_socket, recv_data, BUFFER_SIZE, 0);
		if (ret < 0) {
    
    
			printf("Failed to receive data!\n");
			break;
		}
		recv_data[ret]=0; // correctly ends received string
		char yb[4],wd[4];
		for(int i=0;i<4;i++){
    
    
			//TODO
			yb[i] = recv_data[4+i];
			wd[i] = recv_data[8+i];
			
		}
		float mic = hexToDec(yb)/100.0;
		float strain_temp = hexToDec(wd)/100.0;
		printf("应变:%f\r\n",mic);
		printf("温度:%f\r\n",strain_temp);

4. Código completo

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <winsock2.h>  
#include <math.h>
#include "stdint.h"
#define length_8 8    //定义一个宏,为传入8位16进制数的个数
#define PORT 8002
#define SERVER_IP "123.56.90.74"
#define BUFFER_SIZE 4196

const char* kExitFlag = "exit";


/* 返回ch字符在sign数组中的序号 */
int getIndexOfSigns(char ch)
{
    
    
	if(ch >= '0' && ch <= '9')
	{
    
    
		return ch - '0';
	}
	if(ch >= 'A' && ch <='F') 
	{
    
    
		return ch - 'A' + 10;
	}
	if(ch >= 'a' && ch <= 'f')
	{
    
    
		return ch - 'a' + 10;
	}
	return -1;
}
/* 十六进制数转换为十进制数 */
int hexToDec(char *source)
{
    
    
	int sum = 0;
	int t = 1;
	int i, len=4;
	char low,high;
	for(int i=0,j=7;i<4;i++){
    
    
		//TODO
		high = (source[i] & 0xf0)>>4;
		low = source[i] & 0x0f;
		sum += high*pow(16,j--)+low*pow(16,j--); 
	}
	return sum;
}



const unsigned char *fromhex(const char *str)
{
    
    
	static unsigned char buf[512];
	size_t len = strlen(str) / 2;
	if (len > 512) len = 512;
	for (size_t i = 0; i < len; i++) {
    
    
		unsigned char c = 0;
		if (str[i * 2] >= '0' && str[i*2] <= '9') 
			c += (str[i * 2] - '0') << 4;
		if ((str[i * 2] & ~0x20) >= 'A' && (str[i*2] & ~0x20) <= 'F') 
			c += (10 + (str[i * 2] & ~0x20) - 'A') << 4;
		if (str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9') 
			c += (str[i * 2 + 1] - '0');
		if ((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F')
			c += (10 + (str[i * 2 + 1] & ~0x20) - 'A');
		buf[i] = c;
	}
	return buf;
}

uint16_t CRC_16(uint8_t *temp)
{
    
    
	uint8_t i,j;
	uint16_t CRC_1 = 0xFFFF;          //声明CRC寄存区,也就是步骤1
	for(i = 0;i < 6;i++)       //这里的for循环说的是步骤6中的重复步骤 2 到步骤 5
	{
    
    
		CRC_1 ^= temp[i]; //这里就是步骤2,进行异或运算
		for(j = 0;j < 8;j++)         //用来将异或后的低八位全部移出的for循环
		{
    
    
			if(CRC_1 & 0x01)         //判断低八位的最后一位是否为1,为1时执行下列语句,也就是步骤3说的移位判断与步骤5说的右移8次
			{
    
    
				/*一定要先移位,再异或*/
				CRC_1 >>=1;          //移位后再异或,就是步骤4
				CRC_1 ^= 0xA001;     //0xA001为0x8005的逆序
			}
			else                    //若不为1,则直接移位。
			{
    
    
				CRC_1 >>=1;
			}
		}
	}
	
	//	CRC_1 = (((CRC_1 & 0xFF)<<8) + (CRC_1>>8));
	//	printf("%04x\r\n",CRC_1);     //用于打印检测CRC校验码
	return(CRC_1);
}

int main() {
    
    
	// 初始化socket dll。
	WORD winsock_version = MAKEWORD(2,2);
	WSADATA wsa_data;
	if (WSAStartup(winsock_version, &wsa_data) != 0) {
    
    
		printf("Failed to init socket!\n");
		return 1;
	}
	
	SOCKET client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (client_socket == INVALID_SOCKET) {
    
    
		printf("Failed to create server socket!\n");
		return 2;
	}
	
	struct sockaddr_in server_addr;
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);
	if (connect(client_socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
    
    
		printf("Failed to connect server: %ld !\n", GetLastError());
		return 3;
	}
	
	char recv_data[BUFFER_SIZE+1];
	while (true) {
    
    
		uint8_t data[length_8];
		printf("0+传感器编号(1,2,3,4,5)0300010002\r\n");
		scanf("%s",data);
		uint16_t crc;
		unsigned char * cmd;
		char crc1[8];
		cmd = fromhex(data);
		crc = CRC_16(cmd);
		uint8_t a = 0xFF;
		for(int i=0;i<6;i++){
    
    
			//TODO
			crc1[i] = cmd[i];
		}
		crc1[6] = a & crc;
		crc1[7] = (crc >> 8) & a;
		
		if (send(client_socket, crc1, 8, 0) < 0) {
    
    
			printf("Failed to send data!\n");
			break;
		}
		
		int ret = recv(client_socket, recv_data, BUFFER_SIZE, 0);
		if (ret < 0) {
    
    
			printf("Failed to receive data!\n");
			break;
		}
		recv_data[ret]=0; // correctly ends received string
		char yb[4],wd[4];
		for(int i=0;i<4;i++){
    
    
			//TODO
			yb[i] = recv_data[4+i];
			wd[i] = recv_data[8+i];
			
		}
		float mic = hexToDec(yb)/100.0;
		float strain_temp = hexToDec(wd)/100.0;
		printf("应变:%f\r\n",mic);
		printf("温度:%f\r\n",strain_temp);
		
		
		//		printf("Receive data from server: \"%x\"\n",recv_data);
		if (strcmp(data,kExitFlag)==0) {
    
    
			printf("Exit!\n");
			break;
		}
	}
	
	closesocket(client_socket);
	WSACleanup();
	
	return 0;
}

2. Efeito

insira a descrição da imagem aqui


V. Resumo

Como o endereço de broadcast de 255.255.255.255 é usado ao enviar a mensagem, várias partes podem receber a mensagem. Entenda os princípios básicos do protocolo de comunicação Modbus e do protocolo e estrutura de comunicação ModbusTCP.

6. Referências

Use wireshark para capturar informações de bate-papo (comunicação udp na rede local),
use linguagem c para concluir o protocolo modbus e leia as informações de temperatura e umidade do servidor em nuvem

Acho que você gosta

Origin blog.csdn.net/qq_52215423/article/details/128444683
Recomendado
Clasificación