关于Socket传送大量数据...(50分)

  • 主题发起人 主题发起人 kaif1
  • 开始时间 开始时间
K

kaif1

Unregistered / Unconfirmed
GUEST, unregistred user!

各位同志,俺在程序中使用TClientSocket和TServerSocket

编一个传送大量数据的程序,因为所要发送的数据较多,所

以俺用了一个循环来依次发送数据,刚开始,发现仅前两次

发送的数据接收端收到,后面的数据将分节丢失。小弟想可

能是因为接收接收频率及速度方面的问题,于是在程序中加

入了一个信息接收到的标志,结果正常,但小弟怎么看怎么

觉得有点不对劲。小弟现在有如下问题:

1、Socket的SendText一次可发送多少的数据?Delphi中String

可达2G,SendText的极限是多少,最佳长度约是多少?

2、Socket只有发送Stream的功能,但接收是一个大大的Buffer,

如何定义此Buffer才好呢?

3、那里有用TClientSocket/TServerSocket传送文件的例子可下

载(非TClientSocket/TServerSocket方案也可)?

或那位高手可以给出一个Demo?


谢谢!

---------------------------------------------------------
附:小弟测试分段传数据的代码(自Delphi自带的Chat改写)

unit main;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, StdCtrls, Buttons, ScktComp, ExtCtrls, ComCtrls;

type
TChatForm = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
Exit1: TMenuItem;
FileConnectItem: TMenuItem;
FileListenItem: TMenuItem;
StatusBar1: TStatusBar;
Bevel1: TBevel;
Panel1: TPanel;
Memo1: TMemo;
Memo2: TMemo;
N1: TMenuItem;
SpeedButton1: TSpeedButton;
Disconnect1: TMenuItem;
ServerSocket: TServerSocket;
ClientSocket: TClientSocket;
Button1: TButton;
procedure FileListenItemClick(Sender: TObject);
procedure FileConnectItemClick(Sender: TObject);
procedure Exit1Click(Sender: TObject);
procedure Memo1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormCreate(Sender: TObject);
procedure ServerSocketError(Sender: TObject; Number: Smallint;
var Description: string; Scode: Integer; const Source,
HelpFile: string; HelpContext: Integer; var CancelDisplay: Wordbool);
procedure Disconnect1Click(Sender: TObject);
procedure ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
procedure ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketAccept(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button1Click(Sender: TObject);
private
Flag: boolean;
protected
IsServer: Boolean;
end;

var
ChatForm: TChatForm;
Server: String;

implementation

{$R *.DFM}

procedure TChatForm.FileListenItemClick(Sender: TObject);
begin
FileListenItem.Checked := not FileListenItem.Checked;
if FileListenItem.Checked then
begin
ClientSocket.Active := False;
ServerSocket.Active := True;
Statusbar1.Panels[0].Text := 'Listening...';
end
else
begin
if ServerSocket.Active then
ServerSocket.Active := False;
Statusbar1.Panels[0].Text := '';
end;
end;

procedure TChatForm.FileConnectItemClick(Sender: TObject);
begin
if ClientSocket.Active then ClientSocket.Active := False;
if InputQuery('Computer to connect to', 'Address Name:', Server) then
if Length(Server) > 0 then
with ClientSocket do
begin
Host := Server;
Active := True;
FileListenItem.Checked := False;
end;
end;

procedure TChatForm.Exit1Click(Sender: TObject);
begin
ServerSocket.Close;
ClientSocket.Close;
Close;
end;

procedure TChatForm.Memo1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VK_Return then
if IsServer then
ServerSocket.Socket.Connections[0].SendText(Memo1.Lines[Memo1.Lines.Count - 1])
else
ClientSocket.Socket.SendText(Memo1.Lines[Memo1.Lines.Count - 1]);
end;

procedure TChatForm.FormCreate(Sender: TObject);
begin
FileListenItemClick(nil);
Flag := True;
end;

procedure TChatForm.ServerSocketError(Sender: TObject; Number: Smallint;
var Description: string; Scode: Integer; const Source, HelpFile: string;
HelpContext: Integer; var CancelDisplay: Wordbool);
begin
ShowMessage(Description);
end;

procedure TChatForm.Disconnect1Click(Sender: TObject);
begin
ClientSocket.Active := False;
ServerSocket.Active := True;
Statusbar1.Panels[0].Text := 'Listening...';
end;

procedure TChatForm.ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Statusbar1.Panels[0].Text := 'Connected to: ' + Socket.RemoteHost;
end;

procedure TChatForm.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
S: string;
begin
//Memo2.Lines.Add(Socket.ReceiveText);
S := Socket.ReceiveText;
if s = 'next' then begin flag := true; exit; end;
if S <> '' then
Memo2.Lines.add(IntToStr(Ord(S[1])));
if IsServer then
ServerSocket.Socket.Connections[0].SendText('next')
else
ClientSocket.Socket.SendText('next');
end;

procedure TChatForm.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
S: string;
begin
//Memo2.Lines.Add(Socket.ReceiveText);
S := Socket.ReceiveText;
if s = 'next' then begin flag := true; exit; end;
if S <> '' then
Memo2.Lines.add(IntToStr(Ord(S[1])));
if IsServer then
ServerSocket.Socket.Connections[0].SendText('next')
else
ClientSocket.Socket.SendText('next');
end;

procedure TChatForm.ServerSocketAccept(Sender: TObject;
Socket: TCustomWinSocket);
begin
IsServer := True;
Statusbar1.Panels[0].Text := 'Connected to: ' + Socket.RemoteAddress;
end;

procedure TChatForm.ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo2.Lines.Clear;
end;

procedure TChatForm.ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
FileListenItemClick(nil);
end;

procedure TChatForm.ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Memo2.Lines.Add('Error connecting to : ' + Server);
ErrorCode := 0;
end;

procedure TChatForm.ServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Statusbar1.Panels[0].Text := 'Listening...';
end;

procedure TChatForm.Button1Click(Sender: TObject);
var
I:Byte;J:integer;
s: string;
begin
for i := 0 to 255 do
begin
repeat
Application.ProcessMessages;
until flag;
S := chr(i);
flag := false;
if IsServer then
ServerSocket.Socket.Connections[0].SendText(Char(I))
else
ClientSocket.Socket.SendText(Char(I));
end;
end;

end.
 
我不知道你用的阻塞还是非阻塞方式。
建议你用阻塞方式的流方式。
流方式的缓存大小没关系,他只是你每次从流里面读出的字节,其余的还在socket 的buffer.
理论上你只要一段不停的发,一段不同的收就可以,
我通常发送的字节数不超过1024,你可以把一个大字节的分成若干断发。
我也不知道其中的原因,但是我发现很多软件(期货,股票的tcp/ip程序)最大的包都是
1024.
希望对你有帮助。
 
接受答案了.
 
后退
顶部