Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Indy y Threads (https://www.clubdelphi.com/foros/showthread.php?t=20730)

PeLuCa 23-04-2005 20:33:23

Indy y Threads
 
Hola a todos, se me presenta la siguiente situacion, tengo un servidor de impresion para impresoras fiscales de TPV, y varios clientes en una red conectados a este servidor a traves de socket, el envio de mesajes es con string usando los CommandHandler del TcpServer.
El tema es que cuando el servidor recibe el string con el cual se inicia el Command de la impresion, inicia todo bien pero al invocar un metodo propio de la impresora el cliente se desconecta y el comando no se ejecuta o se da la inverso, es decir el comando no se ejecuta por lo que le cliente se desconecta a pesar de que la propiedad disconnect del CommandHandler = False, revise los metodos de impresion y son los correctos, si a alguien le sucedio algo parecido aceptare cualquier sugerencia, Gracias.

johncook 24-04-2005 03:54:03

No entiendo bien la pregunta, pero podría sugerirte que crees un hilo cada vez que tengas que imprimir algo...
Es decir cuando ejecute el comando, creas un hilo y dejas que el cliente siga a la escucha de nuevos eventos..

PeLuCa 24-04-2005 16:26:04

Redefiniendo pregunta
 
Primero que nada gracias por responder, segundo, probrando de nuevo logre darme cuenta cual es problema, mi aplicacion servidor crea hilos por cada cliente que se conecta a el, cuando desde un cliente llega la peticion de impresion salta la excepcion EAccessViolation, si tu sabes a raiz de que se lanza esta excepcion te agradeceria, probe en los clientes eliminar la sincronizacion pero sigue igual, ahora estoy viendo TCriticalSection haber si con esto lo logro. Cualquier sugerencia sera bienvenida.Saludos.

johncook 25-04-2005 00:29:40

Podrías Incluir parte del código, para poder analizarlo?
Saludos.
John Cook.

PeLuCa 26-04-2005 18:14:56

Redefiniendo el problema
 
El tema ahora es el siguiente:
Ejemplificando, tengo un TIdTCPServer con un objeto publico impresora que hace referencia a un objeto fisico de impresion, cuando hago uso de este objeto desde la misma aplicacion, es decir, desde el mismo formulario , a traves de un boton, por ejempli funciona todo correctamente, pero he aqui, que cuando algun cliente TIdTCPClient envia un comando al servidor y en el metodo que se ejecuta quiero hacer uso de ese objeto salta la excepcion de AccessViolation, estoy bastante desconcertado, sera por los hilos que crea el servidor para atender a los clientes, no podran acceder a este objeto, no se.
Probando y probando, inspecciondo el objeto, los valores que adquiere, este toma valores validos pero no lo puedo utilizar de esta manera.
Espero haber sido claro en la explicacion sino avisame. Saludos.

johncook 27-04-2005 01:33:08

Peluca: Insisto de que incluyas al menos unas líneas de código......
Creo que con el código del comando bastaría... Por el tipo de error que mencionas, me imagino que puede ser a causa de que estas referenciando objetos sin haberlos creado previamente. Es por eso que me gustaría ver el código que incluyes cuando se ejecuta el comando...
Espero tu respuesta....
Saludos.
John Cook.

PeLuCa 27-04-2005 04:10:21

Aqui va - un poco largo
 
Este es un extracto del codigo

type
TFServidor = class(TForm)
impresora : TImpresoraFiscal;
procedure serverConnect(AThread: TIdPeerThread);
procedure serverExecute(AThread: TIdPeerThread);
procedure serverDisconnect(AThread: TIdPeerThread);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure serverComandoImpresionCommand(ASender: TIdCommand);
procedure serverNoCommandHandler(ASender: TIdTCPServer;
const AData: String; AThread: TIdPeerThread);
procedure serverComandoCierreXCommand(ASender: TIdCommand);
private
{ Private declarations }
ipCount : integer;
ipLocal : string;
puerto : integer;
cantart : integer;
function verificarCantArticulos(param : TStringList) : boolean;
function verificarIndicadores(param : TStringList) : boolean;
public
{ Public declarations }
Clients : TThreadList;
secCrit : TCriticalSection;
vec : TObjectList;
function verficarEstadoConexionesImpFiscales() : boolean ;
function inicilizarInterfaceGrafica() : boolean ;
function cargarConfiguraciones() : boolean ;
function inicializarConexionesClientes() : boolean ;
function verificarParametros(param : TStringList) : boolean;

end;

var
FServidor: TFServidor;


implementation

{$R *.dfm}


function TFServidor.verficarEstadoConexionesImpFiscales() : boolean ;
var
res : boolean;
begin
res:=false;
try
impresora:= TEpsonTM2000AF.Create;
memo1.Lines.Add('Iniciado objeto EPSON');
res:=true;
except
on E: Exception do MessageDlg(E.Message, mtInformation,[mbOk], E.HelpContext);
end;
result := res;
end;

function TFServidor.inicilizarInterfaceGrafica() : boolean ;
var
res : boolean;
begin
res:=false;
try
trayicon1.Show;
result := True;
except
on E: Exception do MessageDlg(E.Message, mtInformation,[mbOk], E.HelpContext);
end;
result := res;
end;

function TFServidor.cargarConfiguraciones() : boolean ;
begin
try
ipLocal := getIPs.Strings[0];
puerto := 5000;
EIP.Text := ipLocal;
EPuerto.Text := IntToStr(puerto);
except
on E: Exception do MessageDlg(E.Message, mtInformation,[mbOk], E.HelpContext);
end;
end;

function TFServidor.inicializarConexionesClientes() : boolean ;
begin
Clients := TThreadList.Create;

Server.Active := true;
secCrit := TCriticalSection.Create;
end;


procedure TFServidor.FormCreate(Sender: TObject);
begin
// verficar estado de la conexion con las Impresoras Fiscales.
verficarEstadoConexionesImpFiscales();
// cargo archivos de configuracion
cargarConfiguraciones();
// Inicializamos los socket con todos los clientes
inicializarConexionesClientes();
// inicializar IGU
inicilizarInterfaceGrafica();

end;

procedure TFServidor.serverConnect(AThread: TIdPeerThread);
var
NewClient: PClient;
begin
GetMem(NewClient, SizeOf(TClient));

NewClient.DNS := AThread.Connection.LocalName;
NewClient.Connected := Now;
NewClient.LastAction := NewClient.Connected;
NewClient.Thread := AThread;

with grillaConexiones do
begin
addRow(1);
cell[0,0].AsString := AThread.Connection.Socket.Binding.PeerIP;
cell[1,0].AsString := IPAddrToName(AThread.Connection.Socket.Binding.PeerIP);
end;
AThread.Data:=TObject(NewClient);
memo1.Lines.Add('Conectado');
try
Clients.LockList.Add(NewClient);
finally
Clients.UnlockList;
end;

end;


procedure TFServidor.serverExecute(AThread: TIdPeerThread);
var
ActClient, RecClient: PClient;
CommBlock, NewCommBlock: String;
RecThread: TIdPeerThread;
i: Integer;
j: byte;

begin
if not AThread.Terminated and AThread.Connection.Connected then
begin
CommBlock:=AThread.Connection.ReadLn;
ActClient := PClient(AThread.Data);
ActClient.LastAction := Now;

with Clients.LockList do
try
for i := 0 to Count-1 do
begin
RecClient:=Items[i];
// if RecClient.DNS=CommBlock.Text then
// begin
RecThread:=RecClient.Thread;
RecThread.Connection.WriteLn(NewCommBlock);
memo1.Lines.Add('Recibido : '+CommBlock+' - Renviando');
// impresora.cierreX;
end;
finally
Clients.UnlockList;
end;
end;
end;



procedure TFServidor.serverDisconnect(AThread: TIdPeerThread);
var
ActClient: PClient;

begin
ActClient := PClient(AThread.Data);
try
Clients.LockList.Remove(ActClient);
memo1.Lines.Add('Desconectado');
grillaConexiones.SearchNext(1,AThread.Connection.LocalName);
grillaConexiones.DeleteRow(grillaConexiones.SelectedRow);

finally
Clients.UnlockList;
end;
FreeMem(ActClient);
AThread.Data := nil;
end;

procedure TFServidor.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Server.Active := False;
Clients.Free;
impresora.Destroy;
end;

procedure TFServidor.serverComandoImpresionCommand(ASender: TIdCommand);
var
resp,th: TStringList;
i : integer;

begin
// Comando que va dar inicio a la impresion
memo1.Lines.Add('recibiendo impresion');
resp := TStringList.Create;
resp.Sorted := False;
for i:=0 to ASender.Params.Count-1 do
begin
resp.add(ASender.Params.Strings[i]);

end;
if verificarParametros(resp) then
begin
memo1.Lines.Add('seteado parametros');
if impresora.setearParametros(resp) then
begin
memo1.Lines.Add('mandando a imprimir');
th := TStringList.Create;
th.Add(impresora.imprimir());
ASender.SetResponse(th);
end;
end
else
memo1.Lines.Add('error en el seteo de parametros');

end;


function TFServidor.verificarParametros(param : TStringList) : boolean;
var
res : boolean;
begin
res:=false;
if param.Strings[1]='FISCAL' then
begin
if verificarCantArticulos(param) then
begin
if verificarIndicadores(param) then
res:=true;
end
end
else
begin
if param.Strings[1]='NO FISCAL' then
res:=true;
end;
result:=res;
end;

function TFServidor.verificarCantArticulos(param : TStringList) : boolean;
var
i :integer;
res : boolean;
begin
//verificamos cantidad de parametros
// por defecto tiene 15 + ( 7 * Cantidad de Items de Articulos)
res:=false;
cantArt := 0;
for i := 0 to param.Count-1 do
begin

if param.Strings[i]='ITEM' then
cantArt:=cantArt+1;
end;

// Verificamos que la Cantidad de articulos OK
if param.Count = (15 + ( 7 * cantArt)) then
res:=true;


result:=res;

end;

function TFServidor.verificarIndicadores(param : TStringList) : boolean;
var
res : boolean;
index,i : integer;
ParamSort : TStringList;
begin
res:=false;
ParamSort := TStringList.Create();
for i := 0 to param.Count-1 do
begin
ParamSort.Add(param.Strings[i]);
end;
ParamSort.Sort;
if ParamSort.Find('TIPO',index) then
if ParamSort.Find('PUERTO',index) then
if ParamSort.Find('CABEZERA',index) then
if ParamSort.Find('ITEM',index) then
if ParamSort.Find('CIERRE',index) then
res:=true;
result:=res;
end;


procedure TFServidor.serverComandoCierreXCommand(ASender: TIdCommand);
var
resp : TStringList;
begin
resp := TStringList.Create;
try
secCrit.Enter;
if impresora.cierreX then <------------ aca da la Excepcion
begin
resp.Add('Cierre X');
ASender.SetResponse(resp);
end;
finally
secCrit.Leave;
end;

end;

*******************************************************************+
unit EpsonFiscal;

interface

uses
EPSON_Impresora_Fiscal_TLB, comobj, ImpresoraFiscal, classes,utiles,SysUtils,Math;

type
TItem = record
descripcion,cantidad,prUnitario,tasaIva,noGravado,descExtra : widestring;
end;

type
TEpsonTM2000AF = class(TImpresoraFiscal) <--esta clase es base se implementan los metodos
private

port : integer;
baud : widestring;


items : array of TItem;
itemsNF : TStringList;

cantArt : integer;

public
PrnFisc : _PrinterFiscalDisp;
constructor Create();
procedure setPuerto( puerto : integer );override;
function getPuerto() : integer;override;
procedure setBaudRate( baudRate : widestring );override;
function getBaudRate() : widestring;override;

function abrirTicketFiscal( letraDoc, ivaEmisor, ivaComprador, nombreCliente, docCliente,
nroDocCliente, domicilio1, domicilio2 : widestring ) : boolean; overload;override;

function abrirTicketFiscal() : boolean;overload;override;

function enviarItemFiscal( descripcion, cantidad, prUnitario, tasaIVA, impNoGravado,
desc1 : Widestring) : boolean; overload;override;

function enviarItemFiscal() : boolean; overload;override;

function cerrarTicketFiscal( letraDoc, saludo: widestring) : boolean;overload;override;

function cerrarTicketFiscal() : boolean;overload;override;

function abrirTicketN0Fiscal() : boolean; override;
function enviarItemNoFiscal(item : widestring) : boolean;overload;override;
function enviarItemNoFiscal() : boolean;overload;override;
function cerrarTicketNoFiscal() : boolean;override;
function verificarParamentros(param : TStringList) : boolean;override;
function setearParametros(param : TStringList) : boolean;override;
function imprimir() : string;override;

function cierreX() : boolean;override;


end;



implementation

uses Servidor;

constructor TEpsonTM2000AF.Create;
begin
inherited;
setMarca('Epson');
setModelo('TM2000AF');
PrnFisc := CreateComObject(CLASS_PrinterFiscal) as _PrinterFiscalDisp;
prnfisc.PortNumber:=1;
prnfisc.BaudRate:='9600';


itemsNF := TStringList.Create();
itemsNF.Sorted:=False;
end;


function TEpsonTM2000AF.cierreX() : boolean;
var Aux1,Aux2:WideString;
resp: boolean;
begin
Aux1:='X';
Aux2:='P';
resp:=prnFisc.CloseJournal(Aux1,Aux2);
ActualizarMemo('CIERRE X');
result :=resp;
end;



function TEpsonTM2000AF.imprimir() : string;
var
resp : string;
i : integer;
aux : widestring;
begin
resp:='';
fservidor.memo1.Lines.Add('comenzando impresion');
if tipo_impresion = 'FISCAL' then
begin
if abrirTicketFiscal() then
begin
if enviarItemFiscal() then
begin
if cerrarTicketFiscal() then
resp:=PrnFisc.AnswerField_3;
end;
end ;
end
else
begin
if tipo_impresion = 'NO FISCAL' then
begin
resp:='Imp NF ';
if abrirTicketN0Fiscal() then
begin
resp:=resp+'Abrir NF ';
if enviarItemNoFiscal() then
begin
resp:=resp+'Item NF ';
if cerrarTicketNoFiscal() then
begin
resp:=resp+'Cerrar NF'
end;
end;
end;
end;

end;


result:=resp;
end;

johncook 27-04-2005 16:05:32

Peluca:
Estuve pegando una mirada, muy por arriba a tu código y me parece que el problema se podría solucionar poniendo
impresora : TImpresoraFiscal; en la parte pública de la clase..
En estos momentos no tengo el delphi, pero cuando llegue a mi casa lo verifico.
De paso te comento que me gustaría si podés que me pases la clase para el acceso a la impresora fiscal.. Me gustaría saber acerca de su manejo...
Mas tarde posteo de nuevo...
Saludos

johncook 27-04-2005 16:10:11

Otra sugerencia que te podría hacer, es que crees el objeto impresora cada vez que un cliente necesite imprimir.
A grandes rasgos sería algo asi:

Cuando recibes el mensaje imprimir, Creas un hilo, dentro de ese hilo creas un objeto impresión, utilizas sus métodos para realizar la impresión propiamente dicha, liberas el objeto, finalizas el hilo.

PeLuCa 27-04-2005 18:57:25

Ya lo he probado
 
johncook :
Ya habia probado de ponerlo en la parte publica y da el mismo error, visitando los newsgroup de Borland, el de winsock, encontre algo parecido y como respuesta mencionaban el ambito de las variables, pero vuelvo a lo mismo la variable impresora es publica a toda la aplicacion no se si para los hilos cuenta esto, la verdad escapa a mi entendimiento.????:confused::confused:

jachguate 27-04-2005 22:45:45

El objeto printer es público... pero no creo que soporte de alguna manera concurrencia multihilos, por lo que eso, te toca a vos proveerlo.

Una forma muy simple es con algún tipo de semáforo controlar cuando la impresora está en uso por algún hilo... y quizas usar el método Synchronize del hilo para garantizar que todo corra sin problemas.

Hasta luego.

;)

Enan0 28-04-2005 15:42:01

Una Cosa peluca, TE cuento que yo estube trabajando un tiempo con impresores fiscales de HASSAR, y estos si la impresora estaba imprimiendo, y les mandabas otro evento de imprimir se rebentaba el OCX entregado por ellos, desconosco el tema de EPSON, pero ahora...
Te imprime aunque sea la primera peticion=??? o absolutamente nada?

PeLuCa 28-04-2005 17:47:01

Enan0, directamente salta la excepcion cuando trata de acceder al objeto de de impresion, ahora inspeccione el objeto y no se esta creando, estoy llegando a la conclusion de jachguate.
El tema seria, creo yo, que deberia funcionar, deberia crearse el objeto al menos, y despues lanzarme la excepcion, o directamente por "precaucion" no me deja acceder a este??,:confused:.
Ideas, que me recomiendan, el objeto de impresion es el que debe implementar multihilos y sincronizar estos, o como le sugiere hacerlo.

Enan0 28-04-2005 18:19:44

Si mal no interprete tenes un BOTON el Con el Cual podes Imprimir Datos Duros Verdad??? y si dentro del Hilo haces la llamada al BOTON?!!!
Digo como Prueba Tonta!!! pero aveces anda.
y de esta manera vas limpiando posibilidades.

PeLuCa 29-04-2005 01:37:33

No, tambien lo habia probado, y no funciona, ya me canse de hacer pruebas y todas terminan mal. Sigo buscando..........

JCarlosas 14-03-2007 05:26:38

Hola.
Se que ya hace como 2 años que postearon este tema, pero me gustaria conocer en que termino el cuento, sobre todo si termino con un final feliz pues estoy usando tambien al componente
TIdTCPServer
y me esta ocurriendo algo similar.
La diferencia es que yo solamente estoy escribiendo para un objeto visual que es un mapa donde voy representando objetos. Y si inteno de hacer algo con el mapa. Resize, paneo etc, mientras se estan recibiendo datos por el socket me salta ese mismo error.
Saludos a todos y gracias de antemano.

jlrbotella 16-03-2007 20:00:38

Actualmente tengo una aplicación muy parecida a la tuya, que lanza comandos y programas. Ese error me ocurrío y lo solucione añadiendo un componente de la paleta indy llamado TClientDataThread, que gestiona en un thread las entradas de la conexión cliente. Además hay limitaciones:

- Si inicias un servicio, y quieres que un cliente lanza una operación que sea un objeto VCL te dará una excepción. Nunca supe el porque. Pero lo solucione creando otra aplicacion y realizando un shellexecute.

Ej:

Un cliente conectado a tu servidor lanza un comando que abre un form de tu aplicación. Da un exception. ¿?.

Ten 2 aplicaciones, 1 : Controlador de red, 2 :Gui o operacionales y te funcionará.

Aunque la mejor opción es crear un servicio en windows, con delphi hay ejemplos y le marcas que interactue con el escritorio y va todo en uno.

Saludos y buen fin de semana.

JCarlosas 18-03-2007 16:20:29

OK. Muchas gracias.
Al final dividi la aplicacion en 2. Una tira los datos para la BD y la otra los muestra desde la BD y Todo OK.
Ahora lo que voy es a convertir en un servicio de windows la aplicacion que tira para la BD pero ya esa sera otra historia.
Bueno muchas gracias.
JCarlos

jlrbotella 20-03-2007 10:33:38

Enhorabuena me alegra que te funcione.

Saludos,
JL

genyus00 07-01-2011 16:10:00

TIdPeerThread
 
Hola buenas, tengo un problema con la clase TIdPeerThread, alguien podria por favor decirme en que libreria de delphi se encuentra, aunque he mirado que segun deberia estar incluido con los indy,... pero en que version de indy esta, tenia la version 9 y la cambie por la 10.0.76 y nada, no me aparece. espero alguien pueda ayudarme y si alguien tiene un link donde encontrar el paquete que los contiene. se lo agradeceria mucho.


La franja horaria es GMT +2. Ahora son las 16:56:58.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi