Delphi 10.使用时TCustomWinSocket访问冲突的数组

时间:2016-09-03 16:34:21

标签: arrays delphi server network-programming delphi-10-seattle

我正在为我的定制战舰游戏制作一个Matchmaking服务器。我是网络编码的初学者,所以我很抱歉提前愚蠢的问题。 :P

现在更接近主题了。我使用默认的Delphi Server / Client Socket组件。我在公共部分(clients: array of TCustomWinSocket;)声明了我的数组,然后在主帧启动时我将长度设置为零(setLength(clients, 0);)。现在令我困惑的部分是:每当我尝试访问数组程序的任何元素时,都会引发访问冲突异常。我已经以任何已知的方式检查过,程序永远不会超过数组的长度。

以下是抛出异常的代码示例:

procedure Tmain.Button1Click(Sender: TObject);
var
i: integer;
begin
  for i := 0 to length(clients) do begin
    if assigned(clients[i]) then begin
      showmessage(IntToStr(i));
      showmessage(IntToStr(i) + ': ' + clients[i].RemoteAddress);
    end;
  end;
end;

另一个例子:

procedure Tmain.serverClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  addLog('(' + Socket.RemoteAddress + ':' + IntToStr(Socket.RemotePort) + ') Клиент подключился');
  if length(clients) <> 0 then begin
    showmessage(IntToStr(length(clients)));
    setLength(clients, length(clients) + 1);
    showmessage(IntToStr(length(clients)));
    clients[length(clients)] := Socket;
  end
  else if length(clients) = 0 then begin
    showmessage(IntToStr(length(clients)));
    clients[0] := Socket;
  end;

end;

基本上,每次我使用这个数组时都会产生访问冲突。我无法得到它,我限制代码保持在数组长度,但它没有。或者,也许是我的愚蠢常常导致它?

任何方式,我都可以使用一些帮助。

提前致谢! :)

1 个答案:

答案 0 :(得分:4)

你在这个循环中跑掉了数组的末尾。 Length(clients)比最后一个索引高一个,因为动态数组的索引从零开始。您必须使用Length(clients) - 1High(clients)作为循环的终止符。

procedure Tmain.Button1Click(Sender: TObject);
var
i: integer;
begin
  for i := 0 to High(clients) do begin // or Length(clients) - 1
    if assigned(clients[i]) then begin
      showmessage(IntToStr(i));
      showmessage(IntToStr(i) + ': ' + clients[i].RemoteAddress);
    end;
  end;
end;

您的第二个代码块中也有类似的错误,另外还有一个非常清楚的错误:

procedure Tmain.serverClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  addLog('(' + Socket.RemoteAddress + ':' + IntToStr(Socket.RemotePort) + ') Клиент подключился');
  if length(clients) <> 0 then begin
    showmessage(IntToStr(length(clients)));      // Need - 1 or High() here
    setLength(clients, length(clients) + 1);
    showmessage(IntToStr(length(clients)));      // Need - 1 or High() here
    clients[length(clients)] := Socket;
  end
  else if length(clients) = 0 then begin       // Second problem starts here
    showmessage(IntToStr(length(clients)));    // See text below
    clients[0] := Socket;                      
  end;                                         
end;

第二个错误是在clients[0]时尝试分配给Length(clients) = 0,因为它是无效索引。如果数组长度为零,则没有元素0,因为数组是空的 - 其中没有元素 - 不是单个元素;您不能为其中包含零元素的数组赋值。

整个块的正确代码是这样的 - 你不需要两个测试,测试长度= 0,或者跳过所有的箍:

procedure Tmain.ServerClientConnect(Sender: TObject; Socket; TCustomSocket);
begin
  AddLog('Whatever you want to log.');
  SetLength(clients, Length(clients) + 1);
  Clients[High(Clients)] := Socket;
end;