delphi Udp 통신

unit MainUnit;
interface
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer, IdSystatUDPServer, IdGlobal, IdSocketHandle, Vcl.StdCtrls, IdUDPClient, Vcl.ComCtrls,StrUtils,System.Types, Vcl.ExtCtrls, Data.DB, Data.Win.ADODB,MsListObject,DateUtils;
type TfrmUDPServer = class(TForm) udpserver: TIdUDPServer; mmoData: TMemo; btnClear: TButton; lv1: TListView; tmrheart: TTimer; qry1: TADOQuery; btnFree: TButton; procedure FormCreate(Sender: TObject); procedure udpserverUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); procedure FormDestroy(Sender: TObject); procedure btnClearClick(Sender: TObject); procedure tmrheartTimer(Sender: TObject); procedure btnFreeClick(Sender: TObject);
private { Private declarations } public { Public declarations } procedure AddListView(AName,AIp,APort:string);
end; type TUDPList = Class(TObject)//클라이언트 객체 저장 fIp: String;//ip fPort : Integer;//port fTime : TDateTime;//시간 fName: String;//사용자 이름 fPwd: String;//암호private
public procedure UpdateTime;//클라이언트의 연결 시간 업데이트 {심장 박동 시간 초과 여부 판단} function IsLink Time Out: Boolean;End; var frmUDPServer : TfrmUDPServer; UdpList : TMsObjectList;//이 클래스는 개인이 다시 쓰는 Tstringlist 클래스입니다.
심박수.로그인메시지를 전달하다.{$R *.dfm} uses IniFiles,DMUnit; //대기열 개체procedure TfrmUDPServer를 해제합니다.btnFreeClick(Sender: TObject); begin UDpList.Destroy; lv1.Items.Clear; mmoData.Clear; UdpList := TMsObjectList.Create; end; //mmo의 데이터(mmo에 로그인 데이터를 저장)procedure TfrmUDPServer를 비웁니다.btnClearClick(Sender: TObject); begin mmoData.Clear; end;
procedure TfrmUDPServer.FormCreate(Sender: TObject); begin try//바인딩 포트 udpServer.DefaultPort := 86; //udpServer를 활성화합니다.Active := true; //대기열 UdpList 만들기: = TMsObjectList.Create; except on e: exception do WriteLog('귀속 포트 오류'+ e.Message),
end; end; //스레드 보안을 위해 사용자가 로그인한 작업(여러 사용자가 로그인할 때 문제가 발생하지 않음)function CheckLogin(const UserName, Password: string):Boolean;begin Result := dbFindTabelValue( ‘SELECT count(1) as c from tb_user where username =”’+UserName+”’ and password = ”’+Password+”’ ‘, False, ‘c’ ); end; //클라이언트가 보낸 정보를 수신하는 데 이 방법이 가장 중요한//Athread는 라인 대상이고 주로 여러 개의 클라이언트가 보낸 데이터를 처리한다. Adata는 클라이언트가 보낸 데이터//AbindIng이Socket 대상이다. 그 안에 클라이언트의 로그인 Ip와 포트procedure TfrmUdpserver가 포함되어 있다.udpserverUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); var Ip,Port : String;//IP ,Port Udp,RUdp : TUDPList;//사용자 SendUdp 생성: TUDPList;//음성 보낸 사람 i: Integer;index : Integer; Data : TIdBytes; UserData : String; ArrayData : TArray; Name : String; Pwd : string; begin Ip := ABinding.PeerIP; Port := IntToStr(ABinding.PeerPort); OutputDebugString ('데이터 길이' + Length (Adata).ToString)); writeLog('데이터 길이 수신 시작'+ IntTOStr(Length(Adata))));//데이터 헤더를 받아서 어떤 조작인지 판단해야 합니다. 이것은 클라이언트와 좋은 프로토콜**//이 헤더가 0이면 로그인을 표시하고 그 다음에 사용자 이름과 사용자 비밀번호를 표시합니다//1은 음성 메시지를 보내는 것을 의미합니다. 2는 심장 박동을 표시하며 클라이언트가 아직 존재하는지 확인하는 데 사용됩니다*** case BytesToInt32(Adata) of 0:begin//AppendBytes(Data, Adata, 4, Length(Adata) -4)에 로그인합니다.//사용자 로그인 정보 UserData: = BytesToString(Data, IndyTextEncoding UTF8);ArrayData := UserData.Split([‘|’]);
  if Length(ArrayData)>1 then begin
    Name        := ArrayData[0];
    Pwd         := ArrayData[1];
    {        }
    if CheckLogin(Name,Pwd) then begin

      Udp         := UdpList.IndexOfObject(Ip+Port);
      if Assigned(Udp) and (Udp.fName = Name) then begin
         //        
        Data := ToBytes(Integer(0));
        udpServer.SendBuffer(Udp.fIp,Udp.fPort,TIdIPVersion.Id_IPv4,Data);
        WriteLog('          0    ');
        Udp.UpdateTime;
        Exit;
      end;

      mmoData.Lines.Add('      '+UserData);
      Udp         := TUDpList.Create;
      Udp.fIp     := Ip;
      Udp.fPort   := Port.ToInteger;
      Udp.UpdateTime;
      UDP.fName   := Name;
      UDP.fPwd    := Pwd;
      UdpList.AddObject(Ip+Port,Udp);
      AddListView(Name,Ip,Port);
      try
        //        
        Data := ToBytes(Integer(0));
        udpServer.SendBuffer(Udp.fIp,Udp.fPort,TIdIPVersion.Id_IPv4,Data);
        WriteLog('    '+'IP:'+Udp.fIp +'  :'+IntTOstr(Udp.fPort));

      except
         on e:exception do
          WriteLog('    '+e.Message);
      end;

    end else begin
      Data := ToBytes(Integer(-1));
      udpServer.SendBuffer(Ip,Port.ToInteger,TIdIPVersion.Id_IPv4,Data);
      writeLog('         '+'   ='+Name+'  ='+Pwd);
      mmoData.Lines.Add('         ='+'   ='+Name +'  =' + Pwd);
    end;

  end;

end;
1: begin  //    
  SendUdp :=UdpList.IndexOfObject(IP+Port);
  if Assigned(SendUdp) = False then begin
    udpServer.SendBuffer(Ip,Port.ToInteger,TIdIPVersion.Id_IPv4,ToBytes(Integer(-1)));
    writeLog('    !'+IP+Port);
    exit;
  end;
  SendUdp.UpdateTime;
  AppendBytes(Data,AData,4,Length(AData)-4);
  for I := 0 to UdpList.Count-1 do begin

    RUdp := UdpList.Objects[i];
    if Assigned(RUdp) then begin

       if (RUdp.fName<>SendUDp.fName) then begin

         udpServer.SendBuffer(RUdp.fIp,RUdp.fPort,TIdIPVersion.Id_IPv4,Data);
         writeLog('      '+ IntTOStr( Length(Data)));
         WriteLog('    --'+'  IP:'+RUdp.fIp+'    :'+IntToStr(RUdp.fPort));
       end else
         WriteLog('    --'+'  IP:'+RUdp.fIp+'    :'+IntToStr(RUdp.fPort));

    end;
  end;
end;

2: begin  //    
  SendUdp :=UdpList.IndexOfObject(IP+Port);
  if Assigned(SendUdp) = False then exit;
  SendUdp.UpdateTime;
  Data := ToBytes(Integer(2));
  udpServer.SendBuffer(Ip,Port.ToInteger,TIdIPVersion.Id_IPv4,Data);
  WriteLog('      '+'IP:'+Ip +'  :'+Port);
end;

end;
end;
procedure TfrmUDPServer.FormDestroy(Sender: TObject); begin udpServer.Active := false; UdpList.Destroy; end; //타이머가 대기열에서 클라이언트 대상 procedure TfrmUDPServer를 삭제합니다.tmrheartTimer(Sender: TObject); var I : integer; begin UdpList.Lock; try for I := UdpList.Count -1 downto 0 do if UdpList.Objects[I].IsLinkTimeOut then begin UdpList.FreeAndNilObject(I); end; finally UdpList.UnLock; end;
end;
//TlistView 목록에 사용자 로그인 데이터를 추가procedure TfrmUDPServer.AddListView(AName,AIp,APort:string); var item : TListItem; begin item := lv1.Items.Add; item.Caption := AName; item.SubItems.Add(AIP); item.SubItems.Add(APort); item.SubItems.Add(FormatDateTime(‘c’,Now)) end;
{TUDPList}//이 방법은 심장 박동 데이터가 10분 이상 수신되지 않았음을 판단하는 데 사용되며, 이 때 사용자function TUDPList를 삭제합니다.IsLinkTimeOut: Boolean; begin Result := MinutesBetween(Now,fTime) > 10; end; //사용자가 데이터를 보낼 때마다 최신 시간procedure TUDPList를 업데이트합니다.UpdateTime; begin fTime := Now; end;
end.

좋은 웹페이지 즐겨찾기