O objetivo deste artigo é apresentar uma visão geral sobre este protocolo.
Histórico
Criado em 1987 a ISO8583 descreve o intercâmbio entre requisições bancárias.
Funcionamento
Sem entrar muito no detalhe do funcionamento.
Basicamente a imagem abaixo, ilustra o funcionamento do protocolo em linhas gerais.
Visão geral do protocolo
De forma geral, o PDV ou POS solicita a operadora uma dada solicitação.
Por exemplo:
inicio de pagamento com cartão de crédito.
No corpo da solicitação, irão alguns dados identificadores da solicitação.
A operadora, pode conforme o tipo da solicitação, perguntar algumas coisas, como senha, tipo de cartão entre outras coisas.
Ou mesmo solicitar a visualização de outras.
A esta solicitação (chamamos de ação), que deve ser respondida pelo PDV ou POS.
A operadora pode realizar quantas perguntas forem necessárias para atendimento de suas necessidades.
Ao fim a operadora envia a resposta final, dando por encerrado a operação.
Em linhas bem gerais é assim que funciona o protocolo ISO 8583.
Estaremos entrando em detalhes, mais adiante.
Porem para entendimento geral, é um protocolo mestre/escravo, onde após a solicitação inicial, a operadora passa a solicitar informações, que devem ser respondidas.
Identificadores de tipo de mensagens
O identificador de tipo de mensagem é um campo numérico de 4 dígitos que especifica o tipo da mensagem que deve ser processado.
Formatação do cabeçalho da solicitação
V: número de versão da ISO 8583 (0 indica que é ISO 8583:1987; 1 indica ISO 8583:1992).
n: Classe da Mensagem conforme a tabela abaixo: | 0 Reserved for ISO use | 1 Authorization | 2 Financial | | 3 File action | 4 Reversal/Chargeback | 5 Reconciliation | | 6 Administration | 7 Fee collection | 8 Network management | | 9 Reserved for ISO use | | |
X: Função da Mensagem conforme tabela: | 0 Request | 1 Request response | 2 Advice | | 3 Advice response | 4 Notification | 5 – 9 Reserved for ISO use |
Y: Origem da Transação | 0 Acquirer | 1 Acquirer repeat | 2 Card issuer | | 3 Card issuer repeat | 4 Other | 5 Other repeat | | 6 –9 Reserved for ISO use | | |
Simulando PDV e Simulando Autorizadora
Eu vasculhando a internet achei o site da neapay, conforme referência.
Baixei um download simulator_ISSUER_ISO8583_host_auth_PRO.
A aplicação trabalha com JAVA, e é uma boa pedida quem deseja testar e aprender mais sobre o protocolo.
Temos também a variável executada, que será utilizada na marcação dos itens executados.
Sessão Crítica
O controle da sessão crítica é feita nas funções IniciaSessaoCritica e TerminaSessaoCritica, conforme fonte abaixo:
int IniciaSessaoCritica()
{
int rc;
int cont = 0;
while ( (rc = pthread_mutex_lock(&mutex))!=0)
{
usleep(100); /*Aguarda um pouco*/
cont++;
printf("Sessao critica não conseguida\n");
if (cont>3) break;
}
return rc;
}
int TerminaSessaoCritica()
{
int rc;
int cont = 0;
while ( (rc = pthread_mutex_unlock(&mutex))!=0)
{
usleep(100); /*Aguarda um pouco*/
cont++;
printf("Sessao critica não liberada\n");
if (cont>3) break;
}
return rc;
}
Ambas as funções controlam a sessão criada mutex, declarada, conforme fonte abaixo:
Para cada sessão critica, deve-se criar uma variável de controle. Como usaremos apenas a fila, como variável de troca de dados, utilizaremos uma única sessão critica.
Criando a thread da recepção
Agora iremos dar inicio a criação da thread da recepção, na qual incluiremos o inicio da thread.
Neste segmento do código, podemos acompanhar que criamos a thread com pthread_create, passando o ponteiro da função que será criada a thread threadRecepcao. Desta forma a função threadRecepcao, não mais seguirá na thread pai. O ultimo parâmetro é utilizado para passagens de argumentos, no nosso caso, não será usado.
Por fim a função da thread
/*thread function definition*/
void* threadRecepcao(void* args)
{
for(int cont = 0;cont<=MAXITEMS;cont++)
{
printf("Criando pacote nro %d\n",cont);
if(IniciaSessaoCritica()==0)
{
int Valor = (rand()% 100);
fila[cont] = Valor; /*Grava Valor na fila*/
printf("Registrou na fila[%d] = %d\n",cont,Valor);
TerminaSessaoCritica();
usleep(1000);
} else {
printf("Falha na Recepcao nro:\n",cont);
}
}
printf("Recepcao terminou atendimento\n");
}
Podemos observar que a threadRecepção requisita a sessão crítica para movimentar a fila, apenas depois alocando valor para ela. Também podemos perceber que após seu uso, o mesmo é descartado.
Criando o Controlador
O controlador, é executado, em seguida, ordenando as informações.
void ordenacao()
{
int i, x;
bool flgordenado = false;
while((!flgordenado)&&(!flgTerminou))
{
//flgordenado = true;
for (i=0; i<=MAXITEMS-1; i++)
{
if ((fila[i]!=0)&&(fila[i+1]!=0))
{
if(fila[i]>fila[i+1])
{
x = fila[i];
fila[i] = fila[i+1];
fila[i+1] = x;
flgordenado = false;
//printf("Ordenando os pacote nro %d\n",i);
}
} else {
//printf("Posicao vazia %d\n",i);
flgordenado = false;
}
}
}
}
/*thread function definition*/
void* threadControlador(void* args)
{
int oldValue, newValue;
int flgOrdenado = false;
printf("Iniciou o controlador\n");
while(!flgTerminou) /*Faz enquanto nao terminar e nao ordenao*/
{
if(IniciaSessaoCritica()==0)
{
ordenacao();
TerminaSessaoCritica();
//usleep(200);
}
}
printf("Terminou ordenação de todos os itens\n");
}
Neste bloco temos duas funções:
A thread em si é a threadControlador, que chama a função de ordenação ordenacao.
A ordenação só para quando for atendida duas condições:
Tiver terminado as demais threads, indicado pelo flag flgTerminou e quando tiver sido totalmente ordenado flgordenado.
Executor
A thread do Executor, pode ser vista conforme apresentado a seguir:
/*thread function definition*/
void* threadExecutor(void* args)
{
int oldValue, newValue;
bool flgExecutado = false;
printf("Iniciou o controlador\n");
int posicao = 0;
//while(!flgExecutado)
while((!flgExecutado)&&(!flgTerminou))
{
//printf("Pesquisando Posicao %d\n",posicao);
//printf("Entrou na sessao critica\n");
if (fila[posicao]==0) /*Fila nao foi preenchida*/
{
printf("posicao vazia %d\n",posicao);
posicao = posicao;
} else
{
executada[posicao] = fila[posicao];
printf("Executou[%d] = %d\n",posicao,fila[posicao]);
if(posicao==MAXITEMS-1)
{
printf("Chegou ao fim\n ");
flgExecutado= true; /*Finaliza executor*/
} else
{
posicao ++;
}
}
//printf("terminou while\n");
}
flgTerminouExecucao = true;
printf("Terminou ordenação de todos os itens\n");
}
Ela irá rodar até que duas condições sejam satisfeitas:
flgExecutado – Controla a execução de todas as tarefas da lista
flgTerminou – Controla o fim de todas as demais threads do sistema
Testando programa
Compilando programa
A compilação em um Raspberry PI ocorreu com sucesso.
Executando o programa
root@raspberrypi:/home/mmm/projetos/Threads-para-Raiz/c# ./threads
Bem vindo ao programa das threads
Este programa faz parte do artigo:
http://maurinsoft.com.br/index.php/2022/07/02/threads-para-raiz-parte-1/
Inicializando vetor
Iniciando Recepcao
Iniciando Controlador
Registrou na fila[0] = 80
Registrou na fila[1] = 11
Registrou na fila[2] = 76
Registrou na fila[3] = 71
Registrou na fila[4] = 27
Registrou na fila[5] = 23
Registrou na fila[6] = 33
Registrou na fila[7] = 68
Registrou na fila[8] = 32
Registrou na fila[9] = 92
Recepcao terminou atendimento
Iniciou o controlador
Iniciando Executor
Status:Iniciou o controlador
Executou[0] = 11
Executou[1] = 23
Executou[2] = 27
Executou[3] = 32
Executou[4] = 33
Executou[5] = 68
Executou[6] = 71
Executou[7] = 76
Executou[8] = 80
Executou[9] = 92
Chegou ao fim
Terminou ordenação de todos os itens
Status:Terminou ordenação de todos os itens
Fila ordenada:11 23 27 32 33 68 71 76 80 92
Fila executada:11 23 27 32 33 68 71 76 80 92
Como a execução ficou um pouco longa, resolvi jogar como código.
Foto da execução
Conclusão
Podemos perceber que a execução de threads pode ser facilitada com uso de flags externos, que facilitam a comunicação entre os processos. Pudemos ver tambem, que a programação em threads é de fato, um estado de arte da programação C, pois envolve alem de um algoritmo bem desenvolvido, a elaboração de estratégias pensando em que uma thread não sabe exatamente quando a outra irá cumprir suas atividades.
Desta forma cada thread tem que ser pensada em aguardar e esperar as informações das threads que colaboraram com esta.
Desta forma o controle interno das informações é bem mais complicado.
Pudemos ver por ultimo o uso dos sinalizadores, que visão identificar o uso de uma sessão crítica do sistema. Que nada mais é que um recurso compartilhado.
Espero que tenham gostado do artigo.
Em caso de dúvidas ou sugestões, fico a disposição como sempre.
Neste primeiro artigo, iremos estabelecer um projeto, que iremos desenvolver nos demais artigos.
Objetivo
A intenção deste projeto é apresentar solução em diversos linguagens de controle de threads com compartilhamento de informações entre elas.
Proposta de projeto
Imagine que temos 3 funcionários em um departamento público.
Recepção de Protocolo – Ele recebe os protocolos de serviço dos clientes.
Controlador de Serviço – Ele recebe os protocolos da recepção, colocando em ordem numérica em uma fila de execução. Por controlar e ordenar, sua atividade demora tempo mediano.
Executor de Serviço – Ele pega o serviço, por executar o serviço é o mais demorado de todos.
Fluxo de execução
Tempo de execução
Ao analisarmos o departamento, fizemos a seguinte constatação:
A recepção de protocolo, é o departamento mais rápido.
O Controlador de Serviço tem um tempo médio que é o dobro da recepção.
Executor de Serviço – Demora o dobro do tempo do controlador de serviço.
Agora que temos o projeto, podemos no próximo artigo começar sua implementação.
Estarei neste tópico apresentando como integrar linux com JAVA, de forma que possamos utilizar recursos do sistema operacional de forma que possamos ganhar maior agilidade.
Porque usar o SO
É interessante criar rotinas integráveis para o sistema operacional para ganhar agilidade e performace.
Como utilizar?
Podemos chamar aplicações:
shell script– Quando queremos agregar operações em lote, exemplo copiar uma pasta.
aplicação terceira – Quando queremos aproveitar features especificas da linguagem, exemplo uso de python para IA.
Quando não utilizar o SO
Existem muitos motivos para usar, e outros motivos que rejeitam o uso.
O mais importante motivo que rejeita seu uso, é quando queremos criar aplicações que não dependem do SO, podendo ser desacoplada de qualquer plataforma.
Aplicações
Aplicações de infra, necessárias para criação de serviços ou recursos, associados a um dado SO.
Podemos utilizar um serviço por exemplo para criar ambientes automatizados, criando ambientes de forma rápida e automática, replicando o que um operador faria em processos manuais.
O modelo deste script, permite capturar pela shell script os parâmetros recebidos do JAVA, realizando tarefas via scripts, permitindo aproveitar o que o JAVA teria maior dificuldade em realizar.
De fato a automação de cópia, não se enquadra em tarefa difícil, porem em um processo didático exemplifica sua prática.
Outro Exemplo seria copia de banco de dados:
#!/bin/bash
#exemplo de teste
#sh -x ./clonabanco.sh bancoorigem bancodest
PATH=/home/mmm/projetos/meuproj/scripts
echo "Script de replicação de banco"
databaserep=$1
database=$2
output="output.sql"
echo "Log de execucao da operacao de clonagem de banco" >> $PATH/logbkp.log
echo "Origem:$databaserep" >> $PATH/logbkp.log
echo "Destino:$database" >> $PATH/logbkp.log
echo "Data:`/usr/bin/date`" >> $PATH/logbkp.log
echo "Iniciando criacao de backup " >> $PATH/logbkp.log
echo `/usr/bin/mysqldump -uroot -pSENHA $databaserep -r $PATH/output.sql` >> $PATH/logbkp.log
echo "Escrevendo script de copia" >> $PATH/logbkp.log
echo "CREATE DATABASE $database;"> $PATH/copy.sql
echo "use $database" >> $PATH/copy.sql
echo "SOURCE $PATH/output.sql" >> $PATH/copy.sql
echo "Criando a base destino" >> $PATH/logbkp.log
echo `/usr/bin/mysql -uroot -pSENHA < $PATH/copy.sql` >> $PATH/logbkp.log
echo "Fim de execução " >> $PATH/logbkp.log
Podemos ver neste script, o uso de técnica de clonagem do banco de dados, permitindo a integração simples com JAVA.
Com este ultimo artigo, encerramos a série de artigos Java sem Nutela no Ubuntu, espero que tenham gostado.
Neste segundo artigo iremos incluir um arquivo de biblioteca JAR alem de explicar o conceito do JAR.
O JAR na verdade é um pacote contendo vários arquivos java, alem de outras informações referentes a criação de um pacote.
Usando um JAR
Primeiro irei explicar como usar o JAR.
O Arquivo JAR deve estar localizado em uma pasta onde os .JAR sejam encontrados, de forma geral, o linux ou qualquer outro sistema operacional, precisa visualizar a variável CLASSPATH
Para isso, iremos alterar o Makefile, incluindo o caminho da nossa lib