TransmitFile函数怎么使用?求大侠给个接收和发送端端代码啊,我要它从服务器端发送小文件到客户端,我对网络通信不熟,谢谢啦

解决方案 »

  1.   

    如果没有网络通讯基础就先学好基础。TransmitFile跟异常的WSASend没有任何区别,只是读取文件的部分由系统帮你完成了。也可以看看MSDN当中的API介绍。
      

  2.   

    为什么非得要TransmitFile这个函数啊,这个函数我不懂。
    但可以给你提供一个网络发送和接收文件的小例子,供参考
    发送端:  public
        { Public declarations }
        StopTrans:boolean;//是否停止传送的开发
        InTrans:boolean;//是否正在传送文件
        procedure TransFile(filename:string);
      end;const Blocklen=1024*4 ; //每次发送的最大数据量var
      frmClient: TfrmClient;implementation{$R *.dfm}procedure TfrmClient.FormCreate(Sender: TObject);
    var
      aWSAData:TWSAData;
    begin
      if WSAStartup($0101,aWSAData)<>0 then
        raise Exception.Create('不能启动WinSock动态链接库!');
      messagebox(handle,aWSAData.szDescription,'WinSock动态链接库版本',Mb_OK);
    end;procedure TfrmClient.BitBtn4Click(Sender: TObject);
    begin
      close;
    end;procedure TfrmClient.FormClose(Sender: TObject; var Action: TCloseAction);
    var
      tim:Tdatetime;
    begin
      if intrans then
        if messagebox(handle,'正在传输文件,停止吗?','提示',mb_yesno)=idno then
          abort;
      if WSACleanup<>0 then
        messagebox(handle,'清除WinSock动态链接库错误!','提示',MB_OK)
      else
        messagebox(handle,'清除WinSock动态链接库成功!','提示',MB_OK);
      closesocket(Client);
    end;procedure TfrmClient.BitBtn1Click(Sender: TObject);
    var
      ca:Sockaddr_in;
      hostaddr:u_long;
    begin
      Client:=socket(PF_INET,SOCk_STREAM,IPPROTO_IP);
      if Client=INVALID_SOCKET then
      begin
        self.StatusBar1.SimpleText:='为连接远程服务器端创建Socket错误!';
        exit;
      end;
      ca.sin_family:=PF_INET;
      ca.sin_port:=htons(strtoint(trim(edit2.Text)));
      hostaddr:=inet_addr(Pchar(trim(edit1.Text)));
      if (hostaddr=-1) then
      begin
        self.StatusBar1.SimpleText:='主机IP地址:' +  trim(edit1.Text)+'错误!';
        exit;
      end
      else
        ca.sin_addr.S_addr:=hostaddr;
      if connect(Client,ca,sizeof(ca))<>0 then
      begin
        self.StatusBar1.SimpleText:='连接服务器Socket错误!';
        exit;
      end
      else
        self.StatusBar1.SimpleText:='连接远程Socket成功!';
    end;procedure  TfrmClient.TransFile(filename:string);
    var
      Ftrans:file of Byte;
      Flen:integer;
      BlockNum,RemainLen:integer;
      BlockBuf:array[0..BlockLen-1] of Byte;
      i:integer;
      SendLen:integer;
    begin
      AssignFile(Ftrans,filename);
      Reset(Ftrans);
      Flen:=FileSize(Ftrans);
      BlockNum:=Flen div BlockLen;
      StopTrans:=false;
      InTrans:=true;
      SendLen:=1;
      for i:=0 to BlockNum-1 do
      begin
        if (StopTrans) or (sendlen<0) then Break;
        Blockread(Ftrans,Blockbuf[0],Blocklen);
        self.ProgressBar1.Position:=i;
        application.ProcessMessages;
      end;
      if stopTrans  then
      begin
        closefile(ftrans);
        intrans:=false;
        self.StatusBar1.SimpleText:='';
        messagebox(handle,'停止传输','提示',mb_ok);
        self.ProgressBar1.Position:=0;
        exit;
      end;
      if (sendlen<=0) then
      begin
        closefile(ftrans);
        intrans:=false;
        self.StatusBar1.SimpleText:='';
        messagebox(handle,'传输异常终止!','提示',mb_ok);
        self.ProgressBar1.Position:=0;
        exit;
      end;
      if Remainlen>0 then
      begin
        BlockRead(Ftrans,Blockbuf[0],1,remainlen);
        sendlen:=send(Client,BlockBuf,remainlen,0);
        if (sendlen<=0) then
        begin
          closefile(ftrans);
          intrans:=false;
          self.StatusBar1.SimpleText:='';
          messagebox(handle,'传输异常终止!','提示',mb_ok);
          self.ProgressBar1.Position:=0;
          exit;
        end;
      end;
      self.ProgressBar1.Position:=self.ProgressBar1.Max;
      closefile(Ftrans);
      Intrans:=false;
      self.StatusBar1.SimpleText:='';
      messagebox(handle,'传输完成!','提示',mb_Ok);
      self.ProgressBar1.Position:=0;
    end;procedure TfrmClient.BitBtn2Click(Sender: TObject);
    begin
      if (self.OpenDialog1.Execute) and (fileExists(self.OpenDialog1.FileName)) then
        transfile(self.OpenDialog1.FileName);
    end;procedure TfrmClient.BitBtn3Click(Sender: TObject);
    begin
      stoptrans:=true;
    end;
      

  3.   

    服务器接收端:  public
        { Public declarations }
        StopTrans:boolean;
        InTrans:boolean;
        Server:TSocket;
        procedure RecvFile(filename:string);
      end;var
      frmServer: TfrmServer;const Blocklen=1024*4;implementation{$R *.dfm}procedure TfrmServer.FormCreate(Sender: TObject);
    var
      aWSAData:TWSAData;
    begin
      if WSAStartup($0101,aWSAData)<>0 then
        raise exception.Create('不能启动WinSock动态链接库!');
      messagebox(handle,aWSAData.szDescription,'WinSock动态链接库版本',MB_OK);
    end;procedure TfrmServer.BitBtn4Click(Sender: TObject);
    begin
      close;
    end;procedure TfrmServer.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      if InTrans then
        if messagebox(handle,'正在接收文件,停止吗?','提示',mb_yesno)=idno then
          abort;
      if Server<>INVALID_SOCKET then
        closesocket(Server);
      if WSACleanup<>0 then
        messagebox(handle,'清除WinSock动态链接库错误!','提示',mb_Ok)
      else
         messagebox(handle,'清除WinSock动态链接库成功!','提示',mb_Ok);
    end;procedure TfrmServer.BitBtn1Click(Sender: TObject);
    var
      ca:SOCKADDR_IN;
    begin
      Server:=Socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
      if Server=INVALID_SOCKET then
      begin
        self.StatusBar1.SimpleText:='创建接收Socket错误!';
        exit;
      end;
      ca.sin_family:=PF_INET;
      ca.sin_port:=htons(strtoint(trim(edit1.Text)));
      ca.sin_addr.S_addr:=INADDR_ANY;
      if bind(Server,ca,sizeof(ca))=SOCKET_ERROR then
      begin
        self.StatusBar1.SimpleText:='绑定接收端Socket错误!请更改接收端口!';
        closeSocket(Server);
        exit;
      end
      else
        self.StatusBar1.SimpleText:='绑定接收端Socket成功!';
      listen(Server,5);
      self.BitBtn1.Enabled:=false;
      self.BitBtn2.Enabled:=true;    
    end;procedure TfrmServer.BitBtn3Click(Sender: TObject);
    begin
      stoptrans:=true;
      if Server<>INVALID_SOCKET  then closesocket(server);
      Server:=INVALID_SOCKET;
      self.BitBtn3.Enabled:=false;
      self.BitBtn1.Enabled:=true;
    end;
      

  4.   

    好,谢谢,我 研究看,据说 TransmitFile 比较有效率,还有谁有例子?我想做个文件服务器,把文件同时下发到好多个客户端
      

  5.   

    TransmitFile是什么东西,没听过3楼的代码,还不错,学习一下.
      

  6.   

    要真正地用好TransmitFile,至少要对Overlapped I/O有一定的了解,而最好的办法是使用完成端口,那样才能真正发挥它的优势。
      

  7.   

    TransmitFile不象WriteFile,ReadFile,WSARecv,WSASend之类的,支持COMPLETION ROUTINE,而要发挥它的性能至少需要使用Overlapped,此时就只能通过WSAWaitForMultipleEvents 或者WSAGetOverlappedResult来得到通知,对于少量连接WSAWaitForMultipleEvents完全可以满足需要,但是如果连接数量多了,这个就相当麻烦,因为一次最多只能处理64个事件,换过来则可以使用WSAGetOverlappedResult来一个个检测,但是这个检测也是一个不小的开消。相比之下完成端口则要简单和方便得多。
      

  8.   

    先完成一个echo server的模型,然后再实现一个应用层传输协议,之后再完成文件的传输.
      

  9.   

    我印象中的TransmitFile是winxp之前为了复用socket而存在的函数,与xp和2003后的disconnectex函数的作用一样,我记错了?