Reputation: 39
Hi I have a problem with the following code:
host := 'localhost';
nickname := 'tester';
canal := '#tester';
code := '';
ClientSocket := TClientSocket.Create(nil);
ClientSocket.host := host;
ClientSocket.Port := 6667;
ClientSocket.Open;
if ClientSocket.Socket.Connected = True then
begin
Writeln('Connected!');
while (1 = 1) do
begin
code := ClientSocket.Socket.Read();
if not(code = '') then
begin
Writeln(code);
end;
end;
end
else
begin
Writeln('Error');
end;
the problem is with the line
code: = ClientSocket.Socket.Read();
gives me the following error
[DCC Error] irc.dpr (35): E2035 Not enough actual parameters
try putting nil as parameter but I get this new error
[DCC Error] irc.dpr (35): E2010 Incompatible types: 'NativeInt' and 'Pointer'
I'm doing wrong?
Upvotes: 0
Views: 2659
Reputation: 596266
Read()
is used internally to trigger the OnRead
event. You should never call it directly.
The TClientSocket.ClientType
property is set to ctNonBlocking
by default. That means the socket runs asynchronously, using an internal window to receive notifications of socket activity. So you have to use the OnConnect
event to detect a successful connection, the OnError
event to detect a failed connect, and the OnRead
events to receive incoming data. And you need a message loop so those events can be triggered. For example:
// since you are using a Console app, you can use
// a little hack to assign event handlers...
procedure ClientConnected(Self: Pointer; Sender: TObject; Socket: TCustomWinSocket);
begin
Writeln('Connected!');
end;
procedure ClientDisconnected(Self: Pointer; Sender: TObject; Socket: TCustomWinSocket);
begin
Writeln('Disconnected!');
PostQuitMessage(0);
end;
procedure ClientError(Self: Pointer; Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
Writeln('Socket Error! ', ErrorCode);
if ErrorEvent = eeConnect then
PostQuitMessage(0);
end;
procedure ClientRead(Self: Pointer; Sender: TObject; Socket: TCustomWinSocket);
var
len: Integer;
Buf: PByte;
begin
len := Socket.ReceiveLength;
if len <= 0 then Exit;
GetMem(Buf, len);
try
len := Socket.ReceiveBuf(Buf^, len);
if len <= 0 then Exit;
// use data as needed...
finally
FreeMem(Buf);
end;
end;
var
ClientSocket: TClientSocket;
M: TMethod;
Msg: TMsg;
begin
try
ClientSocket := TClientSocket.Create(nil);
try
ClientSocket.Host := 'localhost';
ClientSocket.Port := 6667;
M.Code := @ClientConnected;
M.Data := ClientSocket;
ClientSocket.OnConnect := TSocketNotifyEvent(M);
M.Code := @ClientDisconnected;
M.Data := ClientSocket;
ClientSocket.OnDisconnect := TSocketNotifyEvent(M);
M.Code := @ClientRead;
M.Data := ClientSocket;
ClientSocket.OnRead := TSocketNotifyEvent(M);
M.Code := @ClientError;
M.Data := ClientSocket;
ClientSocket.OnError := TSocketErrorEvent(M);
ClientSocket.Open;
while GetMessage(msg, 0, 0, 0) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
finally
ClientSocket.Free;
end;
except
Writeln('Error');
end;
end.
To write the kind of loop you attempted, you would have to set the TClientSocket.ClientType
to ctBlocking
instead, and then use a TWinSocketStream
for reading and writing. For example:
var
ClientSocket: TClientSocket;
Strm: TWinSocketStream;
len: Integer;
Buf: array[0..1023] of Byte;
begin
try
ClientSocket := TClientSocket.Create(nil);
try
ClientSocket.ClientType := ctBlocking;
ClientSocket.Host := 'localhost';
ClientSocket.Port := 6667;
ClientSocket.Open;
Writeln('Connected!');
Strm := TWinSocketStream.Create(ClientSocket.Socket, 5000);
try
repeat
len := Strm.Read(Buf[0], SizeOf(Buf));
if len <= 0 then Break;
// use data as needed...
until False;
finally
Strm.Free;
end;
finally
ClientSocket.Free;
end;
except
Writeln('Error');
end;
end.
Upvotes: 3