闷
解决方案 »
- 在wwDBGrid中显示的数据,选中部分数据做处理,怎么知道选中的笔数
- 60分求Delphi主窗体调用 Dll下的子Frame或form
- SPCOM 串口?
- 現在我要弄一個程序,讓他播了movie接著播img。就這樣一個一個循環。怎么弄?
- 如何返回当月的最大天数
- 在线等,非常急。。。TMultiP这个库那里有下载。大家帮帮我。我快被老板板逼疯了!!! (帮我顶)
- 怎样安装控件的帮助文件?
- 有关ADO的Eoleexception类异常
- Tadoquery的更新方法,说大一点,数据集的更新方法(读更新)
- VC++语句用DELPHI如何表示
- 请问怎样能使“text”类型显示在dbgrid中?
- MEMORYSTATUS的問題
DELPHI中,用TClientSocket和一个TServerSocket连接,正常发送和接收少量消息时,完全正常。但是,如果服务器端发送大量消息(相对而言,200以上)时,客户端就会来由于不及处理而产生数据的丢失现象,如何解决?
一个数据包大概在1~4K左右。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ScktComp;
type
TCon = record
FileName : String;
TotalSize : Integer;
Status : Integer;
end; PCON = ^TCON; TForm1 = class(TForm)
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
ClientSocket: TClientSocket;
ServerSocket: TServerSocket;
btnServerActive: TButton;
btnClientCon: TButton;
btnClientDisConn: TButton;
BtnClientSendF: TButton;
Memo1: TMemo;
OpenDialog: TOpenDialog;
Edit1: TEdit;
Label1: TLabel;
procedure btnClientConClick(Sender: TObject);
procedure btnClientDisConnClick(Sender: TObject);
procedure BtnClientSendFClick(Sender: TObject);
procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure btnServerActiveClick(Sender: TObject);
procedure ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}var Count : Integer;function GetFileSize(const FileName: string):integer;
var f : TFileStream;
begin
f := TFileStream.Create(FileName,fmOpenRead or fmShareDenyNone);
Result :=f.Size;
F.Free;
end;procedure TForm1.btnClientConClick(Sender: TObject);
begin
ClientSocket.Active := True;
with OpenDialog do
begin
Execute;
if FileName <> '' then
begin
Edit1.Text := 'UPLOAD '+ ExtractFileName(FileName) +' '+Inttostr(GetFileSize(FileName));
Label1.Caption := FileName;
ClientSocket.Socket.SendText(edit1.Text);
end;
end;
end;procedure TForm1.btnClientDisConnClick(Sender: TObject);
begin
ClientSocket.Active := False;
end;procedure TForm1.BtnClientSendFClick(Sender: TObject);
var fs : TFileStream;
Buf : pointer;
begin
fs := TFileStream.Create(Label1.Caption ,fmOpenRead or fmShareDenyNone);
GetMem(Buf,fs.Size);
fs.Seek(0,soFromBeginning);
fs.ReadBuffer(Buf^,fs.Size);
memo1.Lines.Add('has send : '+inttostr(ClientSocket.Socket.SendBuf(Buf^,fs.Size)));
end;procedure TForm1.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.add(socket.ReceiveText);
end;procedure TForm1.ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ErrorCode := 0;
end;procedure TForm1.btnServerActiveClick(Sender: TObject);
begin
ServerSocket.Active := True;
end;procedure TForm1.ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var c : pcon;
begin
c :=new(pcon);
c.FileName := '';
c.TotalSize := 0 ;
c.Status := 0;
Socket.Data := c;
Socket.SendText('已经连接,请输入UPLOAD FILENAME SIZE'#13#10);
end;procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var C : PCON;
cmd:String;
Buffer : pointer;
nRetr : integer;
fs : TFileStream;
const bufferSize = 1024 ;begin
C:= Socket.Data ;
case c.Status of
0 :
begin
cmd := trim(Socket.ReceiveText) ;
if Pos('UPLOAD ',uppercase(cmd)) > 0 then
begin
c.FileName := trim(Copy(cmd,Pos(' ',cmd)+1,Length(cmd)));
c.TotalSize := StrToInt(Copy(c.FileName,Pos(' ',c.FileName)+1,Length(c.FileName)));
c.FileName := trim(Copy(c.FileName,1,Pos(' ',c.FileName)));
c.Status := 1;
Socket.Data := C;
Socket.SendText('you can send File !'#13#10);
end;
end;
1 :
begin
Count := count + 1;
GetMem(Buffer,BufferSize);
nRetr := Socket.ReceiveBuf(Buffer^,BufferSize);
Memo1.Lines.Add(IntToStr(Count) + ' ' + IntToStr(nRetr));
if not FIleExists('c:\'+c.FileName) then
begin
fs :=TFileStream.Create('c:\'+c.FileName,fmCreate or fmShareDenyNone);
fs.Seek(0,soFromBeginning);
end
else
begin
fs :=TFileStream.Create('c:\'+c.FileName,fmOpenWrite or fmShareDenyNone);
fs.Seek(0,soFromEnd);
end;
fs.WriteBuffer(Buffer^,nRetr);
fs.Destroy;
FreeMem(Buffer);
end;
end;
end;procedure TForm1.ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ErrorCode := 0;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
Count := 0;
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ClientSocket.Active := False;
ServerSocket.Active := False;
end;
end.
你的程序还是只发送一个数据包,这在我的程序里也能处理。
如果是发送多个数据包的话,有没有好的办法:
如:
for i:=0 to 1000 do
SendToClient(addr,msg[i]);
客户端如何及时处理而不至于丢失数据。
THANKS。
S:准备就绪,可以接收;
C:需要上传的文件信息;
S:收到文件信息:
C:第一个包;
S:收到第一个包;创建文件,开始写数据;
C:中间的包;
S:收到中间的包;继续写数据;
C:发送最后一个包,关闭文件;
S:收到最后一个包;写数据,关闭文件。
下载文件的过程是这样的: C:请求下载文件;
S:准备就绪,可以下载;
C:需要下载的文件信息(文件名);
S:反馈文件信息(文件大小);
C:准备就绪,可以接收数据;
S:第一个包;
C:收到第一个包;创建文件,开始写数据;
S:中间的包;
C:收到中间的包;继续写数据;
S:发送最后一个包,关闭文件;
C:收到最后一个包;写数据,关闭文件;下载成功;
S:下载成功。
其中,发送中间的包和收到中间的包根据包的数量可以重复。不难看出,上面的两个过程是典型的“你一句我一句”的应答方式。