Ir al contenido



Foto

Simulador de impresora TCP/IP


  • Por favor identifícate para responder
7 respuestas en este tema

#1 seoane

seoane

    Advanced Member

  • Administrador
  • 1.219 mensajes
  • LocationEspaña

Escrito 08 mayo 2014 - 09:12

El siguiente programa sirve para simular una impresora TCP/IP, es decir, al ejecutarlo se pone a la "escucha" en el puerto 9100 esperando a que alguien le mande un trabajo de impresión y cuando lo recibe lo envía a la impresora que le indiquemos. Ahora mismo estaréis pensando que es una manera muy rebuscada de imprimir un documento a través de la red, teniendo alternativas como las impresoras compartidas de windows, pero ¿y si queremos imprimir desde nuestro móvil con andoid en una impresora conectada a nuestro ordenador?

Este es precisamente la duda que me plantearon hace unos días. Se trataba de una aplicación en Android que estaba preparada para imprimir en una impresora de tickets con conexión ethernet  pero solo se disponía de una impresora USB conectada a un PC con Windows. La solucion es este programa que nos permite compartir la impresora en red como si se tratara de un servidor de impresión TCP/IP

Al código:


delphi
  1. program PrintSrv;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses
  6.   Windows,
  7.   SysUtils,
  8.   Winsock,
  9.   WinSpool;
  10.  
  11. const
  12.   BUFFERSIZE = 4*1024;
  13.  
  14. var
  15.   Terminated: Boolean;
  16.  
  17. // Esta rutina maneja la señal "Ctrl+C"
  18. function HandlerRoutine(dwCtrlType: DWORD): BOOL; stdcall;
  19. begin
  20.   Result:= TRUE;
  21.   case dwCtrlType of
  22.     CTRL_C_EVENT:
  23.       Terminated:= TRUE;
  24.     CTRL_CLOSE_EVENT:
  25.       Terminated:= TRUE;
  26.     CTRL_LOGOFF_EVENT:
  27.       Terminated:= TRUE;
  28.     CTRL_SHUTDOWN_EVENT:
  29.       Terminated:= TRUE;
  30.     else
  31.       Result:= FALSE;
  32.   end;
  33. end;
  34.  
  35. function Min(i,j: Integer): Integer;
  36. begin
  37.   if i < j then
  38.     Result:= i
  39.   else
  40.     Result:= j;
  41. end;
  42.  
  43. // Muestra el mensage en hexadecimal y como texto
  44. procedure WriteHex(Buffer: PAnsiChar;  Count: Integer);
  45. var
  46.   i,j: Integer;
  47. begin
  48.   j:= 0;
  49.   while Count > 0 do
  50.   begin
  51.     Write(IntToHex(j,8) + ':' + #32#32);
  52.     for i:= 0 to Min(Count,8) - 1 do
  53.       Write(IntToHex(Byte(Buffer[i]),2) + #32);
  54.     Write(#32);
  55.     for i:= 8 to Min(Count,16) - 1 do
  56.       Write(IntToHex(Byte(Buffer[i]),2) + #32);
  57.     for i:= Min(Count,16) to 15 do
  58.       Write(#32#32#32);
  59.     Write(#32 + '|');
  60.     for i:= 0 to Min(Count,16) - 1 do
  61.     if Char(Buffer[i]) in ['A'..'Z','a'..'z','0'..'9'] then
  62.       Write(Buffer[i])
  63.     else
  64.       Write('.');
  65.     Writeln('|');
  66.     Dec(Count,16);
  67.     inc(Buffer,16);
  68.     inc(j,16);
  69.   end;
  70. end;
  71.  
  72. function CheckAddress(Address: TSockAddr): Boolean;
  73. begin
  74.   Writeln('Recibiendo documento desde: ' +
  75.     AnsiString(PAnsiChar(inet_ntoa(Address.sin_addr))));
  76.   Writeln;
  77.   Result:= TRUE;
  78. end;
  79.  
  80. procedure Procesar(S: TSocket);
  81. var
  82.   Prnt: THandle;
  83.   DocInfo: TDocInfo1;
  84.   Res: DWORD;
  85.   Buffer: PAnsiChar;
  86.   Len: Integer;
  87. begin
  88.   try
  89.     GetMem(Buffer,BUFFERSIZE);
  90.     try
  91.       if OpenPrinter(PAnsiChar(ParamStr(1)), Prnt, nil) then
  92.       try
  93.         FillChar(DocInfo,Sizeof(DocInfo),#0);
  94.         with DocInfo do
  95.         begin
  96.           pDocName:= PChar('PrintSrv');
  97.           pOutputFile:= nil;
  98.           pDataType:= 'RAW';
  99.         end;
  100.         if StartDocPrinter(Prnt, 1, @DocInfo) <> 0 then
  101.         try
  102.           if StartPagePrinter(Prnt) then
  103.           try
  104.             Len:= Recv(S, Buffer^, BUFFERSIZE, 0);
  105.             while Len > 0 do
  106.             begin
  107.               WritePrinter(Prnt, Buffer, Len, Res);
  108.               WriteHex(Buffer,Len);
  109.               Len:= Recv(S, Buffer^, BUFFERSIZE, 0);
  110.             end;
  111.           finally
  112.             EndPagePrinter(Prnt);
  113.           end;
  114.         finally
  115.           EndDocPrinter(Prnt);
  116.         end;
  117.       finally
  118.         ClosePrinter(Prnt);
  119.       end;
  120.     finally
  121.       FreeMem(Buffer);
  122.     end;
  123.   finally
  124.     CloseSocket(S);
  125.   end;
  126. end;
  127.  
  128. var
  129.   WSAData: TWSAData;
  130.   SSocket, CSocket: TSocket;
  131.   SAddr, CAddr: TSockAddr;
  132.   Size: Integer;
  133.   FDSet: TFDSet;
  134.   TimeVal: TTimeVal;
  135. begin
  136.   if ParamCount < 1 then
  137.   begin
  138.     Writeln('Ejemplo de uso:');
  139.     Writeln('PrintSrv "Nombre de la impresora"');
  140.     Writeln;
  141.     Exit;
  142.   end;
  143.  
  144.   Terminated:= FALSE;
  145.   SetConsoleCtrlHandler(@HandlerRoutine,TRUE);
  146.  
  147.   if WSAStartup(MAKEWORD(1, 1), WSADATA) = 0 then
  148.   try
  149.     // Creamos un socket
  150.     SSocket:= Socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  151.     if SSocket = INVALID_SOCKET then
  152.     begin
  153.       Writeln('Error en Socket()!');
  154.       Exit;
  155.     end;
  156.     // Configuramos la ip y el puerto del servidor
  157.     with SAddr do
  158.     begin
  159.       sin_family:= AF_INET;
  160.       sin_port:= htons(9100);
  161.       sin_addr.s_addr:= Inet_Addr(PAnsiChar('0.0.0.0'));
  162.     end;
  163.     if Bind(SSocket, SAddr, SizeOf(SAddr)) = SOCKET_ERROR then
  164.     begin
  165.       CloseSocket(SSocket);
  166.       Writeln('Error en Bind!');
  167.       Exit;
  168.     end;
  169.     // Ponemos el puerto a la escucha
  170.     if Listen(SSocket, SOMAXCONN) = SOCKET_ERROR then
  171.     begin
  172.       CloseSocket(SSocket);
  173.       Writeln('Error en Listen!');
  174.       Exit;
  175.     end;
  176.     Writeln('La impresora seleccionada es: ' + ParamStr(1));
  177.     Writeln('Escuchando en el puerto 9100, formato RAW');
  178.     Writeln('Pulsa Ctrl+C para salir ...');
  179.     Writeln;
  180.     // Bucle del servidor
  181.     while not Terminated do
  182.     begin
  183.       // Procesamos los mensajes
  184.       TimeVal.tv_sec:= 0;
  185.       TimeVal.tv_usec:= 500;
  186.       FD_ZERO(FDSet);
  187.       FD_SET(SSocket, FDSet);
  188.       // Comprobamos si hay algun cliente esperando
  189.       if Select(0, @FDSet, nil, nil, @TimeVal) > 0 then
  190.       begin
  191.         Size:= SizeOf(CAddr);
  192.         // Aceptamos la conexion
  193.         CSocket:= Accept(SSocket, @CAddr, @Size);
  194.         // Si la conexion es correcta
  195.         if CSocket <> INVALID_SOCKET then
  196.         begin
  197.           // Comprobamos la direccón del cliente
  198.           if CheckAddress(CAddr) then
  199.           begin
  200.             // Aqui procesamos el envio
  201.             try
  202.               Procesar(CSocket);
  203.             except
  204.               On E: Exception do
  205.               begin
  206.                 // Si no podemos crearlo cerramos el socket
  207.                 CloseSocket(CSocket);
  208.                 // Informamos del error
  209.                 Writeln(E.Message);
  210.               end;
  211.             end;
  212.           end else
  213.             // Si la direccion no es valida cerramos el socket
  214.             CloseSocket(CSocket);
  215.         end;
  216.       end;
  217.     end;
  218.     // Cerramos el Socket del servidor
  219.     CloseSocket(SSocket);
  220.   finally
  221.     // Limpiamos todo
  222.     WSACleanup;
  223.   end else
  224.     Writeln('Error en WSAStartup!');
  225. end.



Solamente hay que ejecutar la aplicación indicando el nombre de la impresora, y en la App de Android indicarle la IP del PC y el puerto 9100.

PD: Por aquí dejo el binario por si alguien no puede compilar el código (por ejemplo la persona que me lo pidió, que no tiene Delphi)


Archivos adjuntos


  • 0

#2 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 08 mayo 2014 - 10:05

Gracias por compartir tan intreresante aplicación amigo.

Saludos.
  • 0

#3 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.689 mensajes
  • LocationMadrid - España

Escrito 08 mayo 2014 - 01:30

Muy buena solución, seoane.  :ap: :ap:
  • 0

#4 ELKurgan

ELKurgan

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 502 mensajes
  • LocationEspaña

Escrito 08 mayo 2014 - 11:19

Magnífico, como siempre...

Muchas gracias por el aporte, maestro

(y)
  • 0

#5 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 509 mensajes
  • LocationCali, Colombia

Escrito 09 mayo 2014 - 07:26

Excelente, muchas gracias por estos aportes.
  • 0

#6 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.133 mensajes

Escrito 09 mayo 2014 - 07:44

De lujo, muchas gracias. (y)
  • 0

#7 fherworld2017

fherworld2017

    Newbie

  • Miembros
  • Pip
  • 1 mensajes

Escrito 16 julio 2017 - 06:10

Hola muchas gracias por el aporte, pero trate de probarlo y al ejecutarlo trata de abrir y se cierra, por que sera? nececita algun complemento? muchas gracias.


  • 0

#8 seoane

seoane

    Advanced Member

  • Administrador
  • 1.219 mensajes
  • LocationEspaña

Escrito 16 julio 2017 - 04:24

Hola muchas gracias por el aporte, pero trate de probarlo y al ejecutarlo trata de abrir y se cierra, por que sera? nececita algun complemento? muchas gracias.

¿Lo abriste desde una consola de comandos o simplemente haciendo doble clic sobre el?

 

El programa es una aplicacion de consola, y lo errores se muestran directamente en la consola. Prueba a ejecutarlo desde la consola y ver que error aparece

 

Por otro lado si ya tienes algun programa ocupando el puerto 9100, el programa fallara, comprueba eso tambien


  • 0