• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1109
  • Last Modified:

Console App Help...

Hello,
 I have this code but I need some help with it

Program Project2;

{$APPTYPE CONSOLE}

Uses
  SysUtils, ScktComp;

Type
  TMyApp = Class(TObject)
    Public
      Procedure Connect(Sender: TObject; Socket: TCustomWinSocket);
      Procedure Disconnect(Sender: TObject; Socket: TCustomWinSocket);
      Procedure Receive(Sender: TObject; Socket: TCustomWinSocket);
  End;

Var
  MyApp: TMyApp; Server: TServerSocket;

Procedure TMyApp.Connect(Sender: TObject; Socket: TCustomWinSocket); Begin WriteLn('Connected.') End;
Procedure TMyApp.Disconnect(Sender: TObject; Socket: TCustomWinSocket); Begin WriteLn('Disconnected.') End;
Procedure TMyApp.Receive(Sender: TObject; Socket: TCustomWinSocket); Begin WriteLn(Socket.ReceiveText) End;

Begin
  MyApp := TMyApp.Create;
  Server := TServerSocket.Create(nil);
  Server.OnClientConnect := MyApp.Connect;
  Server.OnClientDisconnect := MyApp.Disconnect;
  Server.OnClientRead := MyApp.Receive;
  Server.Port := 6000;
  Server.Active := True;
  While True Do ReadLn;
End.

But I think the
   While True Do ReadLn;

Is blocking the ServerSocket, how can I fix this?
I will give more points but this is all I have at the mo.

Thx Karamja
0
-Karamja-
Asked:
-Karamja-
  • 11
  • 7
1 Solution
 
shaneholmesCommented:
you might want to try adding a timer

set it interval property for say 3000 //every 3 seconds

Begin
 timer1:= TTimer.Create;
 timer1.enabled:= false;
 timer1.OnTImer:= MyTImer;
  MyApp := TMyApp.Create;
  Server := TServerSocket.Create(nil);
  Server.OnClientConnect := MyApp.Connect;
  Server.OnClientDisconnect := MyApp.Disconnect;
  Server.OnClientRead := MyApp.Receive;
  Server.Port := 6000;
  Server.Active := True;
  Timer1.Enabled:= True;
End.


procedure MyTimer(Sender: TObject);
var
 tmp: String;
begin
tmp:=  Server.Readln;
if tmp <> '' then
// DoSomething with tmp
end;


don't forget to free your timer & server on forms close


Shane
0
 
shaneholmesCommented:
procedure MyTimer(Sender: TObject);
var
 tmp: String;
begin
tmp:=  Readln;
if tmp <> '' then
// DoSomething with tmp
end;


this will continue until you call timer1.enabled:= false;

Shane
0
 
shaneholmesCommented:
sorry

timer1:= TTimer.Create(nil);

Shane
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
shaneholmesCommented:
Program Project2;

{$APPTYPE CONSOLE}

Uses
  SysUtils, ScktComp, ExtCtrls;

Type
  TMyApp = Class(TObject)
    Public
      Procedure Connect(Sender: TObject; Socket: TCustomWinSocket);
      Procedure Disconnect(Sender: TObject; Socket: TCustomWinSocket);
      Procedure Receive(Sender: TObject; Socket: TCustomWinSocket);
      Procedure MyTimer(Sender: TObject);
  End;

Var
  MyApp: TMyApp; Server: TServerSocket;
  Timer1: TTimer;

Procedure TMyApp.Connect(Sender: TObject; Socket: TCustomWinSocket); Begin WriteLn('Connected.') End;
Procedure TMyApp.Disconnect(Sender: TObject; Socket: TCustomWinSocket); Begin WriteLn('Disconnected.') End;
Procedure TMyApp.Receive(Sender: TObject; Socket: TCustomWinSocket); Begin WriteLn(Socket.ReceiveText) End;

procedure MyTimer(Sender: TObject);
var
 tmp: String;
begin
tmp:=  Readln;
if tmp <> '' then
begin
 //do something here
end;
end;
 

Begin
 Timer1:= TTimer.Create(nil);
 Timer1.Enabled:= false;
 Timer1.OnTimer:= MyTimer
  MyApp := TMyApp.Create;
  Server := TServerSocket.Create(nil);
  Server.OnClientConnect := MyApp.Connect;
  Server.OnClientDisconnect := MyApp.Disconnect;
  Server.OnClientRead := MyApp.Receive;
  Server.Port := 6000;
  Server.Active := True;
  Timer1.Enabled:= True
End.


you also need to figure out how you are going to free up your objects when program terminates

Timer1.Free
 Server.Free;


You might want to do it in the MyTimer event.

You check for some logic then free them

Shane
0
 
-Karamja-Author Commented:
[Error] Project1.dpr(29): Incompatible types: 'String' and 'procedure, untyped pointer or untyped parameter'
[Error] Project1.dpr(41): Incompatible types: 'method pointer and regular procedure'
[Error] Project1.dpr(14): Unsatisfied forward or external declaration: 'TMyApp.MyTimer'

??????????
0
 
-Karamja-Author Commented:
At this line btw
tmp:= Readln;
0
 
shaneholmesCommented:
Building you an example right now


Shane
0
 
shaneholmesCommented:
program Project1;

uses
  Forms,
  Unit2 in 'Unit2.pas';

{$R *.res}

begin
 Server.Active := True;
 Timer.Enabled:= True;
end.





unit Unit2;

interface

uses
 SysUtils, ScktComp, ExtCtrls, Dialogs;

Type
  TMyApp = Class(TObject)
    Public
      Procedure Connect(Sender: TObject; Socket: TCustomWinSocket);
      Procedure Disconnect(Sender: TObject; Socket: TCustomWinSocket);
      Procedure Receive(Sender: TObject; Socket: TCustomWinSocket);
      Procedure MyTimer(Sender: TObject);
  End;

var
 MyApp: TMyApp;
 Server: TServerSocket;
 Timer: TTimer;
 ReceivedText: String;

implementation

Procedure TMyApp.Connect(Sender: TObject; Socket: TCustomWinSocket); Begin WriteLn('Connected.') End;
Procedure TMyApp.Disconnect(Sender: TObject; Socket: TCustomWinSocket); Begin WriteLn('Disconnected.') End;
Procedure TMyApp.Receive(Sender: TObject; Socket: TCustomWinSocket); Begin WriteLn(Socket.ReceiveText) End;

procedure TMyApp.MyTimer(Sender: TObject);
begin
 //
end;


initialization
begin
 Timer:= TTimer.Create(nil);
 Timer.Enabled:= false;
 Timer.OnTimer:= MyApp.MyTimer;
 MyApp := TMyApp.Create;
 Server := TServerSocket.Create(nil);
 Server.OnClientConnect := MyApp.Connect;
 Server.OnClientDisconnect := MyApp.Disconnect;
 Server.OnClientRead := MyApp.Receive;
 Server.Port := 6000;
end;

finalization
begin
 Timer.Free;
 Server.Free;
end;
end.
0
 
-Karamja-Author Commented:
Ok, thx for your quick reply but I think you messed up a bit.

I am making a console app but you have done this a a normal project with units

{$APPTYPE CONSOLE}
0
 
shaneholmesCommented:
program Project1;
No, i no your doing a Console app. I just figured out the timer wont work.

Although, I added the second unit, so you could free the Objects

Try This,

Shane



{$APPTYPE CONSOLE}
uses
  Forms,
  Unit2 in 'Unit2.pas';


{$R *.res}

begin
 Server.Active := True;
 System.Readln;
end.


unit Unit2;

interface

uses
 SysUtils, ScktComp, ExtCtrls;

Type
  TMyApp = Class(TObject)
    Public
      Procedure Connect(Sender: TObject; Socket: TCustomWinSocket);
      Procedure Disconnect(Sender: TObject; Socket: TCustomWinSocket);
      Procedure Receive(Sender: TObject; Socket: TCustomWinSocket);
  End;

var
 MyApp: TMyApp;
 Server: TServerSocket;

implementation

Procedure TMyApp.Connect(Sender: TObject; Socket: TCustomWinSocket);
Begin
 WriteLn('Connected.')
End;

Procedure TMyApp.Disconnect(Sender: TObject; Socket: TCustomWinSocket);
Begin
 WriteLn('Disconnected.')
End;

Procedure TMyApp.Receive(Sender: TObject; Socket: TCustomWinSocket);
Begin
 WriteLn(Socket.ReceiveText)
End;


initialization
begin
 MyApp := TMyApp.Create;
 Server := TServerSocket.Create(nil);
 Server.OnClientConnect := MyApp.Connect;
 Server.OnClientDisconnect := MyApp.Disconnect;
 Server.OnClientRead := MyApp.Receive;
 Server.Port := 6000;
end;

finalization
begin
 MyApp.Free;
 Server.Free;
end;
end.
0
 
-Karamja-Author Commented:
Right even tho this code works we are back to step one,
Somethink is blocking it again
0
 
shaneholmesCommented:
Something is blocking what?

The socket from receiving data?

SHane
0
 
-Karamja-Author Commented:
That or showing it
0
 
shaneholmesCommented:
did you try doing any type of break points, or write statements at certain points to test ...


example, the OnReceive event

Shane
0
 
shaneholmesCommented:
I can't test it, cause i don't have anything coming across that port

Shane
0
 
-Karamja-Author Commented:
1) You could change port to test
2) http://127.0.0.1:6000 Should call the on connect event
0
 
shaneholmesCommented:
What i believe you want to do is in fact hard to accommplish in a console app
rather than in a GUI app.
A GUI app typically sits idly waiting in the message loop for messages to come it to
process. Sockets create background threads that need to Synchronize to the
main threads for the socket events, and the synchronization is done using
messages. So, no message loop, no synchronization. And a console app typically
does not have a message loop, it sits waiting for console input events if it
is not a linear processing code flow anyway.

So i would make a little VCl app, using a main form with a memo as output
window instead of a console.

It is surely possible to get this to work with a console as well, but it
requires a whole lot more work.

Would you consider a invisible form?

A Borderless form?

SOmething other than a Console app?

Shane
0
 
Melih SARICACommented:
Here is a running example

How to test:
 open internet explorer and type this address

   http://127.0.0.1:5555


 

program Project1;

{$APPTYPE CONSOLE}

uses
  sockets,windows;

type
  TmySocket = class(TObject)
    mServer : TTcpServer;
    public
      procedure Create;
      Procedure Destroy;
      property TCPServer : TTcpServer read mserver write mserver;
    protected
      Procedure mOnAccept (Sender: TObject; ClientSocket: TCustomIpClient);
  end;
var
  mysock : TmySocket;
  msg : tagMSG;
{ TmySocket }

procedure TmySocket.Create;
begin
  mServer:=TTcpServer.Create(nil);
end;

procedure TmySocket.Destroy;
begin
 mServer.Free;
end;

procedure TmySocket.mOnAccept(Sender: TObject;ClientSocket: TCustomIpClient);
var
   mbuf : pchar;
   dlen : integer;
   mstr : string ;
begin
   writeln(clientSocket.remotehost);
   mstr :=clientSocket.remotehost+ ' ->Just To see if that is send';
   ClientSocket.Sendln(mstr);
   ClientSocket.ReceiveBuf(mbuf,dlen,0);
end;

begin
  mysock.Create;
  mysock.TCPServer.LocalPort:='5555';
  mysock.TCPServer.OnAccept:=mysock.mOnAccept;
  mysock.TCPServer.Active:=true;
  while GetMessage(Msg, 0, 0, 0) <> BOOL(FALSE) do begin
   TranslateMessage(Msg);
   DispatchMessage(Msg);
  end;
  mysock.TCPServer.Active:=false;
  mysock.Destroy;

end.
0
 
-Karamja-Author Commented:
Thx, your code worked fine.
Also thx for your quick replys
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 11
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now