那个就不是在ONREAD和ONWRITE读写数据了。<br><br>在ServerSocket1GetThread时,自己来创建线程与client通信的。<br><br>如以下示例(转)<br>-------------------------<br>TCP/IP 多线程传文件<br>---------------------<br><br>//===========================================================<br>//服务器端<br><br>unit svSocketThread;<br><br>interface<br><br>uses<br> SysUtils, Classes, ComCtrls, ScktComp, ExtCtrls, StdCtrls;<br><br>type<br> TServerThread=class(TServerClientThread)<br> private<br> WriteSize: integer; //发送数据缓冲区大小,以字节为单位<br> FilesName: string; //文件名<br> FilesStrm : TFileStream; //文件流<br> FilesLength: integer; //文件大小<br> FileCurrLength: integer; //当前传送多少个字节<br> ListItem: TListItem;<br> ErrorRaise : Boolean;<br> procedure ThreadCountDec;<br> procedure ListItemAdd;<br> procedure ListItemEnd;<br> procedure ListItemErr;<br> protected<br> procedure ClientExecute; override;<br> public<br> constructor Create(CreateSuspended: Boolean;<br> ASocket: TServerClientWinSocket; AFileName: string;<br> AWriteSize: integer); overload;<br> destructor Destroy; override; <br> end;<br><br><br><br>implementation<br>uses svMain,utCommon;<br><br><br>//==============================================================================<br><br>{=== ServerThread ===}<br><br>constructor TServerThread.Create(CreateSuspended: Boolean; ASocket: TServerClientWinSocket;<br> AFileName: string; AWriteSize: Integer);<br>begin<br> inherited Create(CreateSuspended, ASocket);<br><br> FilesName := AFileName; //传送的文件名<br> WriteSize := AWriteSize*1024;<br> FilesLength:=0;<br> FileCurrLength := 0;<br><br> FilesStrm := TFileStream.Create(FilesName, fmOpenRead or fmShareDenyNone);<br> FilesLength:= FilesStrm.Size;<br><br> ErrorRaise := False;<br>end;<br><br>destructor TServerThread.Destroy;<br>begin<br> FreeAndNil(FilesStrm);<br> FilesName:='';<br> if ErrorRaise then<br> Synchronize(ListItemErr)<br> else<br> Synchronize(ListItemEnd);<br> Synchronize(ThreadCountDec);<br> <br> inherited;<br>end;<br><br><br>procedure TServerThread.ClientExecute;<br>const<br> ReadLen = 1024;<br>var<br> pStream: TWinSocketStream;<br> Buffer: Pointer;<br> ReadText, SendText: String;<br>begin<br> //创建连接流对像,与客户通信<br> pStream := TWinSocketStream.Create(ClientSocket, 60000);<br><br> try //try 1<br> //--------------------------------------------------------------------------<br> while (not Terminated) and ClientSocket.Connected do begin<br> try //try 2<br> //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br> //分配读数据缓冲区<br> Buffer := AllocMem(ReadLen);<br><br> if pStream.WaitForData(6000) then begin //if 1<br><br> pStream.Read(Buffer^, ReadLen);<br> ReadText := PChar(Buffer);<br> FreeMem(Buffer);<br> <br> if ReadText = KEY_Clt[1] then begin //客户请求文件名<br> //在ListView上增加用户信息<br> Synchronize(ListItemAdd);<br> //返回待下载地文件名<br> SendText := KEY_Srv[1]+ FilesNameSepStr+ ExtractFileName(FilesName);<br> pStream.Write(SendText[1], Length(SendText)+1);<br> end<br> else if ReadText = KEY_Clt[2] then begin //客户请求文件长度<br> //返回对应文件大小<br> SendText := KEY_Srv[2]+ FilesLengthSepStr+ IntToStr(FilesStrm.Size);<br> pStream.Write(SendText[1], Length(SendText)+1);<br> end<br> else if ReadText = KEY_Clt[3] then begin //请求开始发送文件<br> Buffer := AllocMem(WriteSize);<br> Inc(FileCurrLength, pStream.Write(Buffer^, FilesStrm.Read(Buffer^, WriteSize)));<br> FreeMem(Buffer);<br> end<br> else if ReadText = KEY_Clt[4] then begin //下载文件完毕通知<br> //结束线程<br> Terminate;<br> end;<br><br> end; //end if 1<br> //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br> except<br> ErrorRaise := True;<br> Terminate;<br> end; //end try 2<br><br> end; //end while<br> //--------------------------------------------------------------------------<br> finally<br> ClientSocket.Close;<br> pStream.Free;<br> end; //end try 1<br>end;<br><br>procedure TServerThread.ListItemAdd;<br>begin<br> ListItem := frmMainServer.LView_UserInfo.Items.Add;<br> ListItem.Caption := DateTimeToStr(Now);<br> with ListItem.SubItems do begin<br> Add(ClientSocket.RemoteHost);<br> Add(ClientSocket.RemoteAddress);<br> Add(IntToStr(ClientSocket.RemotePort));<br> Add(FilesName);<br> Add('传送文件');<br> end;<br>end;<br><br>procedure TServerThread.ListItemEnd;<br>begin<br> if ListItem <> nil then with ListItem.SubItems do<br> Strings[Count-1] := '传送完毕';<br>end;<br><br>procedure TServerThread.ListItemErr;<br>begin <br> if ListItem <> nil then with ListItem.SubItems do<br> Strings[Count-1] := '传送错误';<br>end;<br><br><br>procedure TServerThread.ThreadCountDec;<br>begin<br> with frmMainServer do<br> begin <br> //线程计数减一<br> Dec(FActiveThreadCount);<br> SBar1.Panels.Items[0].Text := '当前线程数:' + IntToStr(FActiveThreadCount);<br> end;<br>end;<br><br>end.<br>//-----------------------------------------------------<br>procedure TfrmMainServer.ServerSocket2GetThread(Sender: TObject;<br> ClientSocket: TServerClientWinSocket;<br> var SocketThread: TServerClientThread);<br>begin<br> SocketThread := TServerThread.Create(True,ClientSocket, FFileName, FBuffSize);<br> SocketThread.FreeOnTerminate := True;<br> SocketThread.Resume;<br> Inc(FActiveThreadCount);<br> SBar1.Panels.Items[0].Text := '当前线程数:' + IntToStr(FActiveThreadCount);<br>end;<br><br><br>//=========================================================================================<br><br>//客户端<br><br>unit ctClientThread;<br><br>interface<br><br>uses<br> SysUtils, Classes, ComCtrls, ScktComp, ExtCtrls, StdCtrls;<br><br>type<br> TClientThread = class(TThread)<br> private<br> CltSocket: TClientSocket;<br> FilesName: string;<br> FilesStrm: TFileStream;<br> FilesLength: Integer;<br> FileCurrLength, CurrReadSize: Integer; //以字节为单位<br> ReadLen: integer; //每次读取数据的缓冲区大小<br> ParentDir: String;<br> procedure Init(LengthText: String);<br> procedure StepProgressToEnd;<br> procedure StepProgress;<br> protected<br> procedure Execute; override;<br> public<br> constructor Create(CreateSuspended: Boolean; ClientSocket: TClientSocket; AParentDir: String);overload;<br> destructor Destroy; override;<br> end;<br><br>implementation<br>uses utCommon,ctMain;<br><br>//==============================================================================<br><br>{=== TClientThread ===}<br><br>constructor TClientThread.Create(CreateSuspended: Boolean; ClientSocket: TClientSocket; AParentDir: String);<br>begin<br> ParentDir := AParentDir;<br> inherited Create(CreateSuspended);<br> CltSocket := ClientSocket;<br> ReadLen :=4*1024;<br>end;<br><br>destructor TClientThread.Destroy;<br>begin<br> CltSocket.Close;<br> FreeAndNil(FilesStrm);<br> FilesName:='';<br> inherited;<br>end;<br><br>procedure TClientThread.Execute;<br>var<br> pStream: TWinSocketStream;<br> ReadBuffer: Pointer;<br> ReadText, TaskName, SendText: String;<br> Start, FileReading: Boolean;<br>begin <br> Start := False;<br> FileReading := False;<br><br> pStream := TWinSocketStream.Create(CltSocket.Socket, 60000);<br> try<br> //--------------------------------------------------------------------------<br> while (not Terminated) and CltSocket.Active do begin<br> if not Start then begin<br> SendText := KEY_Clt[1];<br> pStream.Write(SendText[1], Length(SendText));<br> Start := True;<br> end;<br><br> ReadBuffer := AllocMem(ReadLen);<br><br> if pStream.WaitForData(6000) then begin //if 1<br> //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br> CurrReadSize := pStream.Read(ReadBuffer^, ReadLen);<br><br> if FileReading then begin //if 2<br> //**************************<br> Inc(FileCurrLength, FilesStrm.Write(ReadBuffer^, CurrReadSize));<br> Synchronize(StepProgress);<br><br> if FileCurrLength >= FilesLength then begin<br> SendText := KEY_Clt[4];<br> pStream.Write(SendText[1], Length(SendText));<br> Synchronize(StepProgressToEnd);<br> FileCurrLength := 0;<br> Terminate;<br> end<br> else begin<br> SendText := KEY_Clt[3];<br> pStream.Write(SendText[1], Length(SendText));<br> end;<br> //**************************<br> end<br> else begin<br> //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br> ReadText := PChar(ReadBuffer);<br> TaskName := Copy(ReadText, 1, Length(KEY_Srv[1]));<br> if TaskName = KEY_Srv[1] then begin //文件名<br> Delete(ReadText, 1, Length(KEY_Srv[1])+1);<br> FilesName := ReadText;<br> SendText := KEY_Clt[2];<br> pStream.Write(SendText[1], Length(SendText));<br> end<br> else if TaskName = KEY_Srv[2] then begin //文件长度<br> Delete(ReadText, 1, Length(KEY_Srv[1])+1);<br> Init(ReadText);<br> SendText := KEY_Clt[3];<br> pStream.Write(SendText[1], Length(SendText));<br> FileReading := True;<br> end;<br> //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br> end; //end if 2<br> //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br> end; //end if 1<br><br> FreeMem(ReadBuffer);<br> end; //end while<br> //--------------------------------------------------------------------------<br> finally<br> pStream.Free;<br> CltSocket.Close;<br> end;<br>end;<br><br><br>procedure TClientThread.Init(LengthText: String);<br>begin<br> FileCurrLength := 0;<br> FilesName := ParentDir +'copy_'+FilesName;<br><br> if FileExists(FilesName) then<br> DeleteFile(FilesName);<br><br> FilesStrm := TFileStream.Create(FilesName, fmCreate);<br> FilesLength :=strtointdef(LengthText,0);<br><br> if FilesLength<>0 then begin<br> frmMainClient.PBar1.Max :=FilesLength div ReadLen;<br> if (FilesLength mod ReadLen)<>0 then<br> frmMainClient.PBar1.Max:=frmMainClient.PBar1.Max+1;<br> end ;<br>end;<br><br>procedure TClientThread.StepProgress;<br>begin<br> frmMainClient.PBar1.Position:=frmMainClient.PBar1.Position +1; <br>end;<br><br>procedure TClientThread.StepProgressToEnd;<br>begin<br> frmMainClient.InitUI(2);<br>end; <br><br>end.<br>//-------------------------------------------------<br>procedure TfrmMainClient.btnDownClick(Sender: TObject);<br>begin<br> case TComponent(Sender).Tag of<br> 0:<br> begin<br> InitUI(1);<br> //创建读写线程<br> ClientThread := TClientThread.Create(True, ClientSocket2, ExtractFilePath(ParamStr(0)));<br> ClientThread.FreeOnTerminate := True;<br><br> //建立连接<br> ClientSocket2.Open;<br><br> //线程开始运行<br> ClientThread.Resume;<br> end;<br> 1:<br> begin<br> ClientThread.Terminate;<br> Close;<br> end;<br> 2:<br> Close;<br> end;<br>end;<br><br>//=========================================================================<br><br>//公用文件<br><br>unit utCommon;<br><br>interface<br><br>uses<br> Classes,SysUtils;<br><br>const<br> Key_Clt: array[1..4] of string=<br> ('AskForFilesName',<br> 'AskForFilesLength',<br> 'AskForFilesData',<br> 'WantToDiscount');<br><br> Key_Srv: array[1..2] of string=<br> ('Return1',<br> 'Return2') ;<br><br> FilesNameSepStr='|';<br> FilesLengthSepStr=',';<br><br>type<br> TTestRec=record<br> No: string[8];<br> Name: string[16];<br> end;<br><br>function StringToStrings(SepStr: string; s: string): TStrings;<br>function StringsToString(SepStr: string; Strs: TStrings; GetFileName: Boolean=False): string;<br><br>implementation<br><br>//==============================================================================<br><br>function StringToStrings(SepStr: string; s: string): TStrings;<br>var P: integer;<br>begin<br> Result:=TStringList.Create ;<br> P:=Pos(SepStr,s);<br> while p<>0 do begin<br> Result.Add(Copy(s,1,p-1));<br> Delete(s,1,p-1+length(SepStr));<br> P:=Pos(SepStr,s);<br> end;<br> Result.Add(s);<br>end;<br><br>function StringsToString(SepStr: string; Strs: TStrings; GetFileName: Boolean=False): string;<br>var i: integer;<br>begin<br> Result:='';<br> for i:=0 to Strs.Count-1 do<br> if not GetFileName then<br> Result:=Result+SepStr+Strs<br> else<br> Result:=Result+SepStr+ExtractFileName(Strs);<br><br> Delete(Result,1,length(SepStr));<br>end;<br><br><br><br>end.<br>//-----------------------------------------------------------------------------------------------