1

맞춤형 전함 게임에 대한 중매 서버를 만들고 있습니다. 나는 네트워크 코딩의 초보자이기 때문에, 바보 같은 질문에 대해서는 미리 유감스럽게 생각한다. : PDelphi 10. TCustomWinSocket 배열 사용시 액세스 위반

이제 주제에 더 가깝습니다. 나는 기본 델파이 서버/클라이언트 소켓 구성 요소를 사용합니다. 공공 구역 (clients: array of TCustomWinSocket;)에서 선언 한 배열을 가지고, 메인 프레임 시동시 길이를 0으로 설정합니다 (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; 

는 기본적으로, 이러한 배열을 사용할 때마다 그것이 액세스 위반을 제공

여기 예외를 발생 부호 예이다. 나는 그것을 얻을 수 없다, 나는 배열 길이에 머물도록 코드를 제한하지만, 그렇지 않다. 아니면 어쩌면 평소와 같이 어리 석음이 원인일까요?

어쨌든, 나는 정말로 도움이 될 수 있습니다.

미리 감사드립니다. :)

+0

안녕하세요, @KenWhite ! 대답 해줘서 고마워요! 문제가 발생하지 않고 0 요소가 존재하기 전에 프로그램을 테스트 할 때 액세스 위반을 일으키기 시작한 후 0 인덱스를 다시 사용하지 않으려 고 시도했습니다. 과거에이를 사용했기 때문에 이제 해결책을 찾았습니다. 다시 작동합니다. 나는 너무 혼란 스럽다 ...하지만 도움에 다시 한번 감사드립니다! –

+0

내 대답보기; 게시 한 코드에 다른 문제가 있습니다. –

답변

4

이 루프에서 배열의 끝을 벗어났습니다. Length(clients)은 동적 배열의 인덱스가 0에서 시작하기 때문에 마지막 인덱스보다 하나 더 높습니다. 루프 종료 자로 Length(clients) - 1 또는 High(clients) 중 하나를 사용해야합니다. 그 무효이기 때문에,

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에 할당하려고 :

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; 

당신은뿐만 아니라 당신의 두 번째 코드 블록에서 유사한 오류, 플러스 꽤 분명 다른 하나가 색인. 배열 길이가 0이면 배열이 비어 있기 때문에 요소 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; 
+0

다시 한번 감사드립니다! 멋진 n '의 모든 것이 빛나는! :) –