Udp传输与线程(200分)

  • 主题发起人 主题发起人 allenshy
  • 开始时间 开始时间
A

allenshy

Unregistered / Unconfirmed
GUEST, unregistred user!
1.我准备把Udp收发数据做成线程,可以跟控制界面分离
2.当传输大量数据时(要求实时),用TNMUDP组件编程时,发现读数据很慢,如何改善呢?
3.有人提议用线程封装,管用吗?,用什么办法呢
下面是一个例子,希望有人帮我把它做成线程。
服务器端(控制端)程序:
unit zq2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, NMUDP;

type
TServer = class(TForm)
SUDP: TNMUDP;
Image1: TImage;
Button1: TButton;
Label1: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure SUDPDataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Server: TServer;

implementation

{$R *.dfm}
const BufSize=2048;
var
RsltStream,TmpStream:TMemoryStream;

procedure TServer.FormCreate(Sender: TObject);
begin
RsltStream:=TMemoryStream.Create;
TmpStream:=TMemoryStream.Create;

end;

procedure TServer.FormDestroy(Sender: TObject);
begin
RsltStream.Free;
TmpStream.Free;

end;

procedure TServer.Button1Click(Sender: TObject);
var ReqCode:array[0..29] of char;ReqCodeStr:string;
begin
ReqCodeStr:='show'+Edit1.Text;
StrpCopy(ReqCode,ReqCodeStr);
TmpStream.Clear;
RsltStream.Clear;
SUDP.RemoteHost:=Edit2.Text;
SUDP.SendBuffer(ReqCode,30);

end;

procedure TServer.SUDPDataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
var ReqCode:array[0..29] of char;ReqCodeStr:string;
begin
ReqCodeStr:='show'+Edit1.text;
StrpCopy(ReqCode,ReqCodeStr);
SUDP.ReadStream(TmpStream);
RsltStream.CopyFrom(TmpStream,NumberBytes);
if NumberBytes< BufSize then { 数据已读完 }
begin
RsltStream.Position:=0;
Image1.Picture.Bitmap.LoadFromStream(RsltStream);
TmpStream.Clear;
RsltStream.Clear;
end
else
begin
TmpStream.Clear;
ReqCode:='show';
SUDP.RemoteHost:=Edit2.Text;
SUDP.SendBuffer(ReqCode,30);
end;

end;

procedure TServer.Button2Click(Sender: TObject);
begin
Image1.Picture.CleanupInstance;
end;

end.

客户端(被控制端)程序

unit zq1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, NMUDP;

type
TClient = class(TForm)
CUDP: TNMUDP;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure CUDPDataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
procedure ScreenCap(LeftPos,TopPos,RightPos,BottomPos:integer);

private
{ Private declarations }
public
{ Public declarations }
end;

var
Client: TClient;

implementation

{$R *.dfm}
const BufSize=2048;{ 发送每一笔数据的缓冲区大小 }
var
BmpStream:TMemoryStream;
LeftSize:Longint;{ 发送每一笔数据后剩余的字节数 }

//function ScreenCap(LeftPos, TopPos, RightPos, BottomPos: integer):boolean;StdCall;external;

procedure TClient.FormCreate(Sender: TObject);
begin
BmpStream:=TMemoryStream.Create;

end;

procedure TClient.FormDestroy(Sender: TObject);
begin
BmpStream.Free;

end;

procedure TClient.CUDPDataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
var
CtrlCode:array[0..29] of char;
Buf:array[0..BufSize-1] of char;
TmpStr:string;
SendSize,LeftPos,TopPos,RightPos,BottomPos:integer;

begin
CUDP.ReadBuffer(CtrlCode,NumberBytes);{ 读取控制码 }
if CtrlCode[0]+CtrlCode[1]+CtrlCode[2]+CtrlCode[3]='show' then
begin { 控制码前4位为“show”表示主控机发出了抓屏指令 }
if BmpStream.Size=0 then { 没有数据可发,必须截屏生成数据 }
begin
TmpStr:=StrPas(CtrlCode);
TmpStr:=Copy(TmpStr,5,Length(TmpStr)-4);
LeftPos:=StrToInt(Copy(TmpStr,1,Pos(':',TmpStr)-1));
TmpStr:=Copy(TmpStr,Pos(':',TmpStr)+1,Length(TmpStr)
-Pos(':',TmpStr));
TopPos:=StrToInt(Copy(TmpStr,1,Pos(':',TmpStr)-1));
TmpStr:=Copy(TmpStr,Pos(':',TmpStr)+1,Length(TmpStr)-
Pos(':',TmpStr));
RightPos:=StrToInt(Copy(TmpStr,1,Pos(':',TmpStr)-1));
BottomPos:=StrToInt(Copy(TmpStr,Pos(':',TmpStr
)+1,Length(TmpStr)-Pos(':',TmpStr)));
ScreenCap(LeftPos,TopPos,RightPos,BottomPos); {
截取屏幕 }
LeftSize:=BmpStream.Size;
end;
if LeftSize>BufSize then SendSize:=BufSize //LeftSize有多大
else SendSize:=LeftSize;
BmpStream.ReadBuffer(Buf,SendSize); //把图像数据流的数据读如缓冲区Buf,大小为..SendSize
LeftSize:=LeftSize-SendSize;
if LeftSize=0 then BmpStream.Clear;{ 清空流 }
CUDP.RemoteHost:=FromIP; { FromIP为主控机IP地址 }
CUDP.SendBuffer(Buf,SendSize); { 将数据发到主控机的2222口 }
end;

end;

procedure TClient.ScreenCap(LeftPos, TopPos, RightPos, BottomPos: integer);
var
RectWidth,RectHeight:integer;
SourceDC,DestDC,Bhandle:integer;
Bitmap:TBitmap;
begin
RectWidth:=RightPos-LeftPos;
RectHeight:=BottomPos-TopPos;
SourceDC:=CreateDC('DISPLAY','','',nil);
DestDC:=CreateCompatibleDC(SourceDC);
Bhandle:=CreateCompatibleBitmap(SourceDC,
RectWidth,RectHeight);
SelectObject(DestDC,Bhandle);
BitBlt(DestDC,0,0,RectWidth,RectHeight,SourceDC,
LeftPos,TopPos,SRCCOPY);
Bitmap:=TBitmap.Create;
Bitmap.Handle:=BHandle;
BitMap.SaveToStream(BmpStream); //把数据装入流BmpStream;
BmpStream.Position:=0;
//LeftSize:=BmpStream.Size; //LeftSize的大小
Bitmap.Free;
DeleteDC(DestDC);
ReleaseDC(Bhandle,SourceDC);

end;

end.
 
直接用Socket Api写吧!
 
可以把OndataReceived()事件封装进线程吗?
 
可以用vc,网上有封装的udp类,
直接调用即可
 
那你自己做吧
 
每人回只好。。。
 
后退
顶部