⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mainunit.pas

📁 序采用网上介绍的方法实现最基本的P2P方式通讯.模拟实现即时消息互发. 2.P2P通讯说明: 1).网关类型是在理想状态下.即非对称型NAT. 2).同在一个内网的两个CLIENT端通讯时,
💻 PAS
字号:
unit MainUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdBaseComponent, IdSocketHandle,IdComponent,
  IdUDPBase, IdUDPServer,testQQCommon;
type
  TServer = class(TForm)
    UDPServer: TIdUDPServer;
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure UDPServerUDPRead(Sender: TObject; AData: TStream;ABinding: TIdSocketHandle);
    procedure StartUp;
  private
    { Private declarations }
  public
    { Public declarations }
    OnlineUsers:TStringList; //在线用户列表
    function ProcRecvLogonData(ThisBinding:TIdSocketHandle;LogonData:TLogonData):boolean;
    function ProcRecvLogoutData(ThisBinding:TIdSocketHandle;LogoutData:TLogoutData):boolean;
    function ProcRecvP2PData(ThisBinding:TIdSocketHandle;HandData:THandData):boolean;
  end;

var
  Server: TServer;

implementation

{$R *.dfm}

procedure TServer.Button1Click(Sender: TObject);
begin
   Server.Close ;
end;

procedure TServer.FormCreate(Sender: TObject);
begin
   StartUp;
   Hide;
end;

//启动服务程序
procedure TServer.StartUp;
var   bind:TIdSocketHandle;
begin
try
   OnlineUsers:=TStringList.create;
   UDPServer.DefaultPort :=SERVER_Port;
   udpserver.Active :=true;
   Memo1.Lines.Add('服务已经在 ['+IntToStr(SERVER_Port)+'] 端口启动!');
 except on E:Exception do
    Memo1.lines.add(e.Message );
 end;
end;

procedure TServer.UDPServerUDPRead(Sender: TObject; AData: TStream;ABinding: TIdSocketHandle);
var _UDPHead:TTQQUDPHead;
    _LogonData:TLogonData;
    _LogoutData:TLogoutData;
    _HandData:THandData;
    RecvSize,MsgType:integer;
begin
try
   MsgType:=-1;
   RecvSize:=adata.Read (_UDPHead,sizeof(_UDPHead) );  //接收数据头
   MsgType:=StrToInt(_UDPHead.MsgType);
   if Msgtype=-1 then exit;
//   UDPSERVER.Binding.Assign(ABinding); //2005-02-17 Updated!
   case  MsgType of
     LogonSign:
     begin
       //登录
       Adata.Read(_LogonData,sizeof(TLogonData));
       ProcRecvLogonData(Abinding,_LogonData);
     end;
     LogoutSign:
     begin
       //注销
       Adata.Read(_LogoutData,sizeof(TLogoutData));
       ProcRecvLogoutData(Abinding,_LogoutData);
     end;
     HandSign:
     begin
       //处理P2P请求
       Adata.Read(_HandData,sizeof(THandData));
       ProcRecvP2PData(Abinding,_HandData);
     end;
   end;
  except on E:Exception do
     Memo1.lines.add(E.Message);
  end;
end;
//登录处理
function Tserver.ProcRecvLogonData(ThisBinding:TIdSocketHandle;LogonData:TLogonData):boolean;
var _LogonDataPackage:TLogonDataPackage;
    _HandDataPackage:THandDataPackage;
    _FriendDataPackage:TFriendDataPackage;
    _tempUserBasicInfo:TServerUserBasicInfo;
    _Account,_PeerIP,_tempIP,_NeedReBack:string;
    i,_PeerPORT,_tempPORT:integer;
begin
   _Account:=LogonData.Account;
   _PeerIP:=thisbinding.PeerIP ;
   _PeerPORT:=thisbinding.PeerPort ;
   with  _LogonDataPackage do
   begin
     Head.MsgType:=IntToStr(LogonSign);
     StrPCopy(Body.Account,_Account);
     StrPCopy(Body.MyPublicIP,_PeerIP);
     StrPCopy(Body.MyPublicPORT,IntToStr(_PeerPORT));
     StrPCopy(Body.lResult,IsTrue);
   end;
   //返回自己的登录信息
   UdpServer.SendBuffer(_PeerIP,_PeerPort ,_LogonDataPackage,sizeof(_LogonDataPackage));
   sleep(1);
   for i:=0 to OnlineUsers.Count-1 do
   begin
     _tempUserBasicInfo:=TServerUserBasicInfo(Onlineusers.Objects[i]);
     _tempIP:=_tempUserBasicInfo.UserData.IP;
     _tempPORT:=StrToInt(_tempUserBasicInfo.UserData.PORT);
     with _HandDataPackage do
     begin
        Head.MsgType:=IntToStr(HandSign);
          StrPCopy(Body.Account,_Account);
          StrPCopy(Body.Mark,IsTrue);
          StrPCopy(Body.DesIP,_PeerIP);
          StrPCopy(Body.DesPORT,IntToStr(_PeerPort));
          StrPCopy(Body.NeedReBack,IsTrue);
        //Head.DataSize:=SizeOf(_HandDataPackage);
     end;
     //向好友发送上线信息
     UdpServer.SendBuffer(_tempIP,_tempPORT,_HandDataPackage,SizeOf(_HandDataPackage));
     sleep(1);
     //取回此好友信息
     with _FriendDataPackage do
     begin
       Head.MsgType:=IntToStr(FriendDataSign);
         StrPCopy(Body.Account,_tempUserBasicInfo.UserData.Account);
         if i=0 then
         begin
            StrPCopy(Body.IsFirstOne,IsTrue);
         end;
         StrPCopy(Body.IP,_tempUserBasicInfo.UserData.IP);
         StrPCopy(Body.PORT,_tempUserBasicInfo.UserData.PORT);
      //Head.DataSize:=SizeOf( _FriendDataPackage);
      UdpServer.SendBuffer(_PeerIP,_PeerPORT,_FriendDataPackage,SizeOf(_FriendDataPackage));
      Sleep(1);
     end;
   end;
   //注册自己的信息
   _tempUserBasicInfo:=TServerUserBasicInfo.Create ;
   StrPCopy(_tempUserBasicInfo.UserData.Account,_Account);
   StrPCopy(_tempUserBasicInfo.UserData.IP,_PeerIP);
   StrPCopy(_tempUserBasicInfo.UserData.PORT,IntToStr(_PeerPORT));
   Onlineusers.AddObject(_Account,_tempUserBasicInfo);
   Memo1.Lines.Add('用户:'+_Account+'['+_PeerIP+':'+IntToStr(_PeerPORT)+'登录上线!');
end;
//用户注销处理
function TServer.ProcRecvLogoutData(ThisBinding:TIdSocketHandle;LogoutData:TLogoutData):boolean;
var _Account,_tempIP,_PeerIP:string;
    i,TheTag,_tempPort,_PeerPORT:Integer;
    _tempUserBasicInfo:TServerUserBasicInfo;
    LogoutDataPackage:TLogoutDataPackage;
begin
  _Account:=LogoutData.Account;
  _PeerIP:=thisbinding.PeerIP ;
  _PeerPORT:=thisbinding.PeerPort;
  TheTag:=OnlineUsers.IndexOf(_Account);
  if TheTag>=0 then
  begin
     //删除用户在线信息
     OnlineUsers.Delete(TheTag);
     Memo1.Lines.Add('用户:'+_Account+'['+_PeerIP+':'+IntToStr(_PeerPORT)+'注销下线!');
     with LogoutDataPackage do
     begin
        Head.MsgType:=IntToStr(LogoutSign);
          StrPCopy(Body.Account,_Account);
          StrPCopy(Body.lResult,IsTrue);
        //
     end;
     UdpServer.SendBuffer(_PeerIP,_PeerPORT,LogoutDataPackage,SizeOf(LogoutDataPackage));
     {//向好友发送下线信号
     for i:=0 to OnlineUsers.Count-1 do
     begin
        _tempUserBasicInfo:=TServerUserBasicInfo(Onlineusers.Objects[i]);
        _tempIP:=_tempUserBasicInfo.UserData.IP;
        _tempPORT:=StrToInt(_tempUserBasicInfo.UserData.PORT);
        with LogoutDataPackage do
        begin
            Head.MsgType:=IntToStr(LogoutSign);
              StrPCopy(Body.Account,_Account);
            //
        end;
        UdpServer.SendBuffer(_tempIP,_tempPORT,LogoutDataPackage,SizeOf(LogoutDataPackage));
     end;
     }
  end;
end;
//转发处理P2P请求
function TServer.ProcRecvP2PData(ThisBinding:TIdSocketHandle;HandData:THandData):boolean;
var toIP,toPort:string;
    HandDataPackage:THandDataPackage;
begin
    toIP:=HandData.DesIP;
    toPort:=HandData.DesPORT;
    with HandDataPackage do
    begin
         Head.MsgType:=IntToStr(HandSign);
           Body.Account:=HandData.Account;
           Body.DesIP:=HandData.DesIP;
           Body.DesPORT:=HandData.DesPORT;
           Body.NeedReBack:=HandData.NeedReBack;
         //Head.DataSize:=SizeOf(HandDataPackage);
    end;
    UdpServer.SendBuffer(toIP,StrToInt(toPort),HandDataPackage,SizeOf(HandDataPackage));
    Sleep(1);
end;
end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -