user3692208
user3692208

Reputation: 39

Error with sockets in delphi

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

Answers (1)

Remy Lebeau
Remy Lebeau

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

Related Questions