Boa noite a todos.
Atualmente na minha empresa trabalhamos com um sistema legado desenvolvido em IBM S400.
Gostaria de saber se é possível se conectar com esse sistema via TELNET.
Poderia me tirar essa dúvida?
Boa noite a todos.
Atualmente na minha empresa trabalhamos com um sistema legado desenvolvido em IBM S400.
Gostaria de saber se é possível se conectar com esse sistema via TELNET.
Poderia me tirar essa dúvida?
Olá @Framos
Essa comunicação é bem difícil de implementar, pois não é possível manter uma conexão aberta de TELNET entre as requisições do Formulário (request / response / request …)
Você teria que implementar a toda a lógica de comunicação de forma atômica, ou seja, quando ocorrer um evento do Formulário, você precisa abrir a conexão Telnet, fazer tudo que precisa e fechar a conexão depois.
Este processo pode envolver vários comandos e respostas. Por exemplo, se o servidor exige autenticação, poderia ser algo assim:
Conecta no servidor.
Aguarda o servidor pedir “username”
Informa o nome de usuário
Aguarda o servidor pedir “password”
Informa a senha
Aguarda o servidor pedir um comando (prompt)
Envia um comando
Lê a resposta
Além disso, é preciso levar em consideração que cada servidor poderá ter uma codificação de texto diferente (UTF8, ASCII…) e formas diferentes de solicitar os comandos (poder ser qualquer caractere ou palavra chave definida pelo servidor).
Eu implementei um exemplo com o servidor Telehack, para testar a comunicação. O exemplo pode ser conferido neste link.
Neste servidor, o prompt para comandos é um “.” (ponto) e a codificação é ASCII.
OBS.: Eu recomendo que você teste o seu código em um projeto Console do Visual Studio antes de colocá-lo em uso no LATROMI. Assim você pode depurar e testar com mais facilidade.
Para implementar este exemplo basta criar um Formulário com os campos txtCommand e txtResult do tipo TextBox, um botão. No evento Click do botão, executar o código C# a seguir:
using System.IO;
using System.Net.Sockets;
using System.Text;
var hostname = "telehack.com";
var port = 23;
var returnKey = "\r\n";
var command = (string)Fields["txtCommand"].Value;
StringBuilder output = new StringBuilder();
string readedLine;
// Faz a leitura da linha de retorno telnet.
Func<StreamReader, string> ReadTelnetLine = sr =>
{
int n;
StringBuilder line = null;
while ((n = sr.Read()) > 0)
{
if (line == null) line = new StringBuilder();
// Consome as quebras de linhas
if (System.Environment.NewLine[0] == (char)n)
{
if (System.Environment.NewLine.Length == 2)
{
if (System.Environment.NewLine[1] == sr.Peek())
sr.Read();
break;
}
else
{
break;
}
}
line.Append((char)n);
if (sr.Peek() == -1)
break;
}
return line?.ToString();
};
// Use o encoding correspondente ao servidor telnet
Encoding encoding = Encoding.ASCII;
using (var client = new TcpClient())
{
client.Connect(hostname, port);
using (NetworkStream networkStream = client.GetStream())
{
// IMPORTANTE: Sempre defina um Timetout para evitar que aplicação trave
networkStream.ReadTimeout = 5000;
bool quit = false;
using (var writer = new StreamWriter(networkStream, encoding) { AutoFlush = true })
using (var reader = new StreamReader(networkStream, encoding, true))
{
while ((readedLine = ReadTelnetLine(reader)) != null)
{
// Detecta linha de prompt
if (readedLine.StartsWith(((char)27).ToString()) && readedLine.EndsWith("."))
{
readedLine = ".";
}
output.AppendLine(readedLine);
switch (readedLine.Trim())
{
// Prompt
case ".":
if (string.IsNullOrEmpty(command))
quit = true;
else
{
writer.Write(command + returnKey);
System.Threading.Thread.Sleep(500);
command = "";
}
break;
default:
break;
}
if (quit)
{
writer.Write("quit" + returnKey);
break;
}
}
}
}
}
Fields["txtResult"].Value = output.ToString();
Não deixe de definir o ReadTimeout
do NetworkStream
. Isso evita que o site fique travado caso ocorra algum erro. Informe um valor em milisegundos.
Se executar StreamReader.Read()
após chegar ao fim da resposta que o servidor tem para oferecer, ocorrera um erro do tipo System.IO.IOException
com a mensagem:
‘Não é possível ler os dados da conexão de transporte: Uma tentativa de conexão falhou porque o componente conectado não respondeu
corretamente após um período de tempo ou a conexão estabelecida falhou
porque o host conectado não respondeu.’
Por isso é importante interceptar no momento certo as “perguntas” que o servidor irá fazer, e não deixar que a leitura prossiga a partir deste ponto. Por exemplo, se o servidor pedir por um comando com um “.” (ponto) e depois disso ocorrer uma leitura de StreamReader.Read()
, vai ocorrer o erro, pois o servidor está esperando um comando (que deve ser enviado com StreamWriter.Write(...)
).
Este erro também irá ocorrer se o servidor exceder o limite de tempo estipulado do ReadTimeout
.
@daniel.giacomelli muito obrigado por responder, vou fazer o teste no visual Studio para ver se consigo.