现在想使用 TServerSocket stThreadBlocking模式做一个服务器,然后用 TClientSocket做一个客户端,
要求客户端发送一个数据包,内容为:AskFile 服务器接收到后组织数据包,内容为:SendFile, 后面加文件信息及文件,传送给客户端,请高手指教,初次写网络文面的,还望高手帮忙.

解决方案 »

  1.   

    请哪位高手写个简单的Demo给我,以数据包的形式发送,数据包要包含传送信息,文件信息,文件,如sendFile(传送信息)test.doc(文件名)24(文件大小)(具体文件)
      

  2.   

    最好能把代码贴出来,让有需要的朋友也学学,也可以发给我邮箱,[email protected] 谢谢
      

  3.   

    unit ThreadGetData;interfaceuses
      Classes, Windows, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
      IdGlobal, SysUtils, StrUtils;type
      ThreadGetFile = class(TThread)
      procedure IdTcpClientGetWork(ASender: TObject; AWorkMode: TWorkMode;
          AWorkCount: Integer);
      private
        { Private declarations }
        FSaveDir, FFileName : string;
        FIpVer : TIdIPVersion;
        IdTcpClientGet : TIdTCPClient;
        FStreamSize : Int64;
        FItemIndex : Integer;
      protected
        procedure Execute; override;
      public
        constructor Create(FileName , SaveDir : string; aIpVer : TIdIPVersion);
      end;implementation
    uses
      Main;
    { ThreadGetFile }function GetPort(aStr : string) : Integer; stdcall;
      begin
          Result := StrToInt(Copy(aStr,Pos(':',aStr) + 1,Pos(')',aStr) - Pos(':',aStr) - 1));
      end;
    function GetHost(aStr : string) : string; stdcall;
      begin
        Result := Copy(aStr,Pos('(',aStr) + 1,Pos(':',aStr) - Pos('(',aStr) - 1);
      end;
    function GetDisplayName(aStr : string) : string; stdcall;
      begin
        Result := LeftBStr(aStr,Pos('(',aStr) - 1);
      end;constructor ThreadGetFile.Create(FileName , SaveDir : string; aIpVer : TIdIPVersion);
    begin  
      FFileName := FileName;
      FItemIndex := -1;
      IdTcpClientGet := TIdTCPClient.Create(nil);
      IdTcpClientGet.OnWork := IdTcpClientGetWork;
      FIpVer := aIpVer;
      FSaveDir := SaveDir;
      inherited Create(True);
    end;procedure ThreadGetFile.IdTcpClientGetWork(ASender: TObject;
      AWorkMode: TWorkMode; AWorkCount: Integer);
    begin
      //
      if FItemIndex <> -1 then
        FrmMain.Lst1.Items[FItemIndex] := '开始接收数据...' + FormatFloat('0',AWorkCount/FStreamSize*100) + '%';
    end;procedure ThreadGetFile.Execute;
    var
      Size : Int64;
      CurInfo, S : string;
      FileStream : TFileStream;  function ProDir (aDir : string) : string;
        begin
          if RightBStr(aDir,1) = '\' then
            Result := aDir
          else
            Result := aDir + '\';
        end;
    begin
    while CurItem < ComLst.Count do
    begin
      EnterCriticalSection(Lock); //进入临界区
      CurInfo := ComLst[CurItem];
      Inc(CurItem);
      LeaveCriticalSection(Lock); //退出临界区
      with IdTcpClientGet do
        begin
          try
            Host := GetHost(CurInfo);
            Port := GetPort(CurInfo);
            IPVersion := FIpVer;
            ReadTimeout := 10000;    
            ConnectTimeout := 10000;
            OnWork := IdTcpClientGetWork;       
            Connect;
            IOHandler.WriteLn('file');
            s := IOHandler.ReadLn;
            if s = '-filename' then
              begin
                IOHandler.WriteLn(FFileName);
                s := IOHandler.ReadLn;
                if s = 'file not found' then
                  begin
                    //文件不存在  
                    FrmMain.Lst1.Items.Add(CurInfo + ' 文件不存在! ' + FFileName);
                  end
                else
                  begin
                    s := RightBStr(s,Length(s) - Pos(':',s));
    //                s := GetDisplayName(FInfo) + s;
                    FileStream := TFileStream.Create(ProDir(FSaveDir) + GetDisplayName(CurInfo) + s,
                      fmCreate);
                    IOHandler.WriteLn('-size');
                    s := IOHandler.ReadLn;
                    Size := StrToInt64Def(s,-1);
                    if Size > -1 then
                      begin
                        FrmMain.Lst1.Items.Add(CurInfo + ' 获取文件大小: ' + IntToStr(Size) + ' Byte');
                        FStreamSize := Size;
                        IOHandler.WriteLn('-ready');
                        IOHandler.LargeStream := True;
                        FItemIndex := FrmMain.Lst1.Items.Add(CurInfo + ' 开始接收数据... ');
                        IOHandler.ReadStream(FileStream,Size);
                        FItemIndex := -1;
                        FileStream.Free;
                        IOHandler.WriteLn('-ok');
                        FrmMain.Lst1.Items.Add(CurInfo + ' 文件传输完成! ' + FFileName);
                      end;
                  end;
              end;
            Disconnect;
          except
            FrmMain.Lst1.Items.Add(CurInfo + ' 连接失败!');
          end;
        end;
    end;
    Dec(ThCount);
    if ThCount = 0 then
      begin
        IdTcpClientGet.Free;
        FrmMain.Lst1.Items.Add('------------任务完成!------------');
        FrmMain.Lst1.Items.Add('');
      end;
    end;
      

  4.   

    procedure TLXServer.IdTCPServerExecute(AContext: TIdContext);
    var
      SPort,sIP: string;
      s: string;
      FileName, SaveFileName: string;
      FileStream: TFileStream;
    begin
      if AContext.Connection.Connected then 
        begin
          sIP := AContext.Binding.PeerIP;
          SPort := IntToStr(AContext.Binding.PeerPort);
          s := AContext.Connection.IOHandler.ReadLn;
          if SameText(s,'test connect') then
            begin
              //测试连接
              AContext.Connection.IOHandler.WriteLn('ok');
              AddLog(FormatDateTime('yyyy-MM-dd HH:mm:ss',Now) + ' Connect Test '
                + AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.PeerPort));
            end;
          if SameText(S, 'file') then
            begin
              AContext.Connection.IOHandler.WriteLn('-filename');
              S := AContext.Connection.IOHandler.ReadLn;
              s := ReplaceStr(s,'%Cur%',ExtractFilePath(ParamStr(0))); //替换程序当前路径
    //          AddLog('test:'+s);
              if FileExists(s) then
                begin
                  //文件存在,发送文件名
    //              AddLog('True');
                  FileName := s;
                  SaveFileName := ExtractFileName(s);
                  AContext.Connection.IOHandler.WriteLn('filename:' + SaveFileName);
                  S := AContext.Connection.IOHandler.ReadLn;
                  if s = '-size' then
                    begin
    //                  if ExtractFileName(FileName) = 'Run.log' then
    //                    begin
    //                      EnterCriticalSection(FUI);
    //                      FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    //                      LeaveCriticalSection(FUI);
    //                    end
    //                  else
                        FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
                      AContext.Connection.IOHandler.WriteLn(IntToStr(FileStream.Size));
                      S := AContext.Connection.IOHandler.ReadLn;
                      if s='-ready' then
                        begin
                          AContext.Connection.IOHandler.LargeStream := True;
                          AContext.Connection.IOHandler.Write(FileStream, FileStream.Size);
                          S := AContext.Connection.IOHandler.ReadLn;
                          if s='-ok' then
                            AddLog(FormatDateTime('yyyy-MM-dd HH:mm:ss',Now) + ' Send File: ' + FileName + ' Ok! '
                              + AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.PeerPort))
                          else
                            AddLog(FormatDateTime('yyyy-MM-dd HH:mm:ss',Now) + ' Send File: ' + FileName + ' Error! '
                              + AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.PeerPort));
                        end;
                      FileStream.Free;
                    end;
                end
                else
                begin
                  //文件不存在
    //              AddLog('false');
                  AContext.Connection.IOHandler.Writeln('file not found');
                  AddLog(FormatDateTime('yyyy-MM-dd HH:mm:ss',Now) + ' File: '+s+' not found!  '
                    + AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.PeerPort));
                end;
            end;
        end;
    end;
      

  5.   

    楼上的,不好意思,我是想用TServerSocket和TClientSocket两个组件.并且是阴塞模式的
      

  6.   

    我自己写的,谁帮我看下哪里的问题,帮我修改一下,谢谢unit Unit1;//客户端interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ComCtrls, StdCtrls, ScktComp;type
      TDataInfo=record
        DataName:String[255];
        FileName:String[255];
        FileSize:Int64;
      end;
      
      TForm1 = class(TForm)
        btnAsk: TButton;
        cs: TClientSocket;
        procedure btnAskClick(Sender: TObject);
        procedure csRead(Sender: TObject; Socket: TCustomWinSocket);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      
    implementation{$R *.dfm}procedure TForm1.btnAskClick(Sender: TObject);
    var
      A: TDataInfo;
      B: TMemoryStream;
      i: Integer;
    begin
      try
        B := TMemoryStream.Create;
        try
          cs.Address := '10.137.199.232';
          cs.Port := 8750;
          cs.Open;
          A.DataName := 'AskFile';
          A.FileName := 'aa';
          A.FileSize := 0;
          B.WriteBuffer(A,SizeOf(A));
          cs.Socket.SendStream(B);
        except
          on E: Exception do
            ShowMessage(E.Message);
        end;
      finally
        FreeAndNil(B);
      end;
    end;procedure TForm1.csRead(Sender: TObject; Socket: TCustomWinSocket);
    var
      A: TMemoryStream;
      B: TDataInfo;
      C: PChar;
      D: Integer;
    begin
      try
        A := TMemoryStream.Create;
        Socket.ReceiveBuf(B,SizeOf(B));
        if B.DataName = 'SendFile' then
        begin
          GetMem(C, 4096);
          repeat
            Socket.ReceiveBuf(C, 4096);
            A.WriteBuffer(C, 4096);
          until A.Size >= B.FileSize;      A.SaveToFile('File\'+B.FileName);
        end;
      finally
        FreeAndNil(A);
      end;
    end;end.
    //客户端结束unit Unit1;//服务器端interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ScktComp;type
      TDataInfo=record
        DataName:String[255];
        FileName:String[255];
        FileSize:Int64;
      end;
      
      TForm1 = class(TForm)
        ss: TServerSocket;
        procedure FormCreate(Sender: TObject);
        procedure ssGetThread(Sender: TObject;
          ClientSocket: TServerClientWinSocket;
          var SocketThread: TServerClientThread);
      private
        { Private declarations }
      public
        { Public declarations }
      end;  TMyThread = class(TServerClientThread)
      private
        FStream: TWinSocketStream;
      public
        procedure ClientExecute; override;
      end;
      
    var
      Form1: TForm1;implementation{$R *.dfm}{ TMyThread }procedure TMyThread.ClientExecute;
    var
      A, B: TDataInfo;
      C: TFileStream;
    begin
      inherited FreeOnTerminate := true;
      try
        FStream := TWinSocketStream.Create(ClientSocket, 10000);
        C := TFileStream.Create('File\Test.doc', fmOpenRead or fmShareDenyNone);
        while(not Terminated) and (ClientSocket.Connected) do
        begin
          try
            FStream.ReadBuffer(A,SizeOf(A));
            if A.DataName = 'AskFile' then
            begin
              B.DataName := 'SendFile';
              B.FileName := 'Test.doc';
              B.FileSize := C.Size;
              FStream.WriteBuffer(B, SizeOf(B));
              FStream.CopyFrom(C,B.FileSize);
            end;
          except
            on E:exception do
            begin
              ClientSocket.Close;
              Terminate;
            end;
          end;
        end;
      finally
        FreeAndNil(FStream);
        FreeAndNil(C);
      end;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      ss.Open;
    end;procedure TForm1.ssGetThread(Sender: TObject;
      ClientSocket: TServerClientWinSocket;
      var SocketThread: TServerClientThread);
    begin
      SocketThread := TMyThread.Create(False, ClientSocket); 
    end;end.
    //服务器端结束
      

  7.   

    你可以考虑使用indy控件来写,应该简单不少