delphi中的套接字出错

时间:2014-09-08 20:59:57

标签: delphi

您好我的以下代码有问题:

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;

问题在于

code: = ClientSocket.Socket.Read();

给我以下错误

[DCC错误] irc.dpr(35):E2035实际参数不足

尝试将nil作为参数,但我收到了这个新错误

[DCC错误] irc.dpr(35):E2010不兼容的类型:' NativeInt'和指针'

我做错了吗?

1 个答案:

答案 0 :(得分:3)

内部使用

Read()来触发OnRead事件。您应该从不直接调用它。

默认情况下,TClientSocket.ClientType属性设置为ctNonBlocking。这意味着套接字以异步方式运行,使用内部窗口接收套接字活动的通知。因此,您必须使用OnConnect事件来检测成功连接,使用OnError事件来检测连接失败,以及OnRead事件来接收传入数据。您需要一个消息循环,以便可以触发这些事件。例如:

// 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.

要编写您尝试的循环类型,您必须将TClientSocket.ClientType设置为ctBlocking,然后使用TWinSocketStream进行读写。例如:

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.