一个关于TcpServer/TcpClient的问题!!请前辈不吝赐教!!(50分)

  • 主题发起人 主题发起人 ivycheung
  • 开始时间 开始时间
I

ivycheung

Unregistered / Unconfirmed
GUEST, unregistred user!
我想写一个通讯程序,局域网上的两台电脑,一台向另一台发送信息后,另一台电脑的程序里能弹出一个显示信息内容showmessage的窗口,我刚刚接触网域通讯,也翻看了大富翁以前的相关贴子,大家都说去看那个netchat的dome,但是我看了很久也不得要领,请各位能简单的明显一下??谢谢,万分感激
 
如果是稳定的局域网就可以直接使用Indy中的UDP控件。例子可以参考下面这个。
服务端最后使用了一个TFilestream,将接收的数据保存为一个文件了。稍做修改就可满足你的要求了。
客户端程序:
unit clientUnit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdAntiFreezeBase, IdAntiFreeze, IdBaseComponent, IdComponent,
IdUDPBase, IdUDPClient, ExtCtrls,jpeg;

type
Tfrmclient = class(TForm)
Timer1: TTimer;
IdUDPClient1: TIdUDPClient;
IdAntiFreeze1: TIdAntiFreeze;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmclient: Tfrmclient;
Fstream : TMemorystream;

implementation

const bufsize=4096-1;

{$R *.dfm}

procedure Tfrmclient.FormCreate(Sender: TObject);
begin
Fstream:=TMemorystream.Create;
Timer1.Interval:=30000;
idudpclient1.Host:='172.16.88.3';
idudpclient1.Port:=9090;
// idudpclient1.Active:=true;
end;

procedure Tfrmclient.FormDestroy(Sender: TObject);
begin
Fstream.Free;
end;

procedure Tfrmclient.Timer1Timer(Sender: TObject);
var
receivedstring,filename:string;
dc:hdc;
fjpeg:tjpegimage;
fscreencanvas:tcanvas;
fbitmap:Tbitmap;
buf:array[0..bufsize] of char;
sendlen:integer;
intoffset:int64;
sRect,Drect:TRect;
begin
try
filename:=formatdatetime('yyyymmddhhnnsszzz',now);
idudpclient1.Send('send'+filename);
receivedstring:=idudpclient1.ReceiveString();
if uppercase(receivedstring)='OK' then
begin
dc:=getdc(0);
fScreencanvas:=Tcanvas.Create;
Fscreencanvas.Handle:=dc;
fbitmap:=tbitmap.Create;
fbitmap.Width:=screen.Width;
fbitmap.Height:=screen.Height;
sRect:=Rect(0,0,screen.Width,screen.Height);
dRect:=Rect(0,0,screen.Width,screen.Height);
fbitmap.Canvas.CopyRect(sRect,fscreencanvas,dRect);
fjpeg:=Tjpegimage.Create;
fjpeg.Assign(fbitmap);
fjpeg.CompressionQuality:=8;
fjpeg.SaveToStream(fstream);
fstream.Position:=0;
// if fstream.Size<0 then exit;
intoffset:=0;
while true do
begin
if intoffset>=fstream.Size then break;
fstream.Position:=intoffset;
sendlen:=fstream.Read(buf,sizeof(buf));
idudpclient1.SendBuffer(buf,sendlen);
application.ProcessMessages;
intoffset:=intoffset+sendlen;
end;
end;
releasedc(0,dc);
fbitmap.Free;
fjpeg.Free;
fstream.Clear;
idudpclient1.Send('end');
except
//idudpclient1.Send('end');
end;
end;

end.

服务端程序:
unit serverUnit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdAntiFreezeBase, IdAntiFreeze, IdBaseComponent, IdComponent,
IdUDPBase, IdUDPServer, StdCtrls,IdSocketHandle;

type
Tfrmserver = class(TForm)
Button1: TButton;
IdUDPServer1: TIdUDPServer;
IdAntiFreeze1: TIdAntiFreeze;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmserver: Tfrmserver;
mem : Tfilestream;

implementation

{$R *.dfm}

procedure Tfrmserver.Button1Click(Sender: TObject);
begin
idudpserver1.DefaultPort:=9090;
idudpserver1.Active:=true;
end;

procedure Tfrmserver.Button2Click(Sender: TObject);
begin
idudpserver1.Active:=false;
end;

procedure Tfrmserver.FormDestroy(Sender: TObject);
begin
if mem<>nil then mem.Free;
mem:=nil;
end;

procedure Tfrmserver.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
var
str,filename:string;
begin
adata.Seek(0,0);
setlength(str,adata.size);
adata.Read(str[1],adata.Size);
if uppercase(str)='END' then
if mem<>nil then begin mem.free;mem:=nil;exit; end;
if pos('SEND',uppercase(str))>0 then
begin
filename:=str;
delete(filename,1,length('SEND'));
filename:='d:/temp/'+abinding.PeerIP+'-'+filename+'.jpg';
if fileexists(filename) then deletefile(filename);
str:='OK';
Abinding.SendTo(abinding.PeerIP,abinding.PeerPort,str[1],length(str));
if mem<>nil then
begin
mem.free;
mem:=nil;
end;
if not fileexists(filename) then
mem:=TFilestream.Create(filename,fmopenreadwrite or fmcreate)
else
mem:=TFilestream.Create(filename,fmopenreadwrite);
end
else
if uppercase(str)<>'END' THEN
begin
if mem<>nil then
begin
adata.Seek(0,0);
mem.CopyFrom(adata,adata.Size);
end;
end;
end;
 
非常谢谢sxdthonda的这么大段语句,但是恕偶程度太低,实在是看得头晕眼花,对不起喔
能不能请你给帮我解释一下那个dome的这一段意思也行[:D]
procedure TForm1.TcpServer1Accept(sender: TObject;
ClientSocket: TCustomIpClient);
var
s,ys: string;
DataThread: TClientDataThread;
begin
DataThread:= TClientDataThread.Create(true);
DataThread.TargetList := memRecv.Lines;
DataThread.ListBuffer.Add('*** Connection Accepted ***');
DataThread.ListBuffer.Add('Remote Host: ' + ClientSocket.LookupHostName(ClientSocket.RemoteHost) +
' (' + ClientSocket.RemoteHost + ')');
DataThread.ListBuffer.Add('===== Begin message =====');
s := ClientSocket.Receiveln;
while s <> '' do
begin
DataThread.ListBuffer.Add(s);
s := ClientSocket.Receiveln;
end;
DataThread.ListBuffer.Add('===== End of message =====');
DataThread.Resume;

end;
 
建议先看WinSock相关电子书,再做书上或帮助上的Demo。一开始用Indy或是其它控件,
是很不习惯的,可能用很久还不明白是怎么回事,当你有了WinSock基础再用会事半功倍的。其实看WinSock电子书最多一个星期看完,边看边做例子很快就会熟悉的,到时你就是
大侠哈哈哈!!!
 
亲爱的大侠jfyes,关键是我现在急等着用呀,如果不急我倒是可以慢慢来研究[:(]
 
简单看了一下,基本的意思就是服务器端接收客户端的请求后针对每个客户端连接生成一个线程负责接收数据.接收到一条数据后唤醒线程.具体那个线程Execute方法做什么了自己看一下吧!
 
如果你只是局域网内发的话.就容易了.利用UDPServer控件就能实现你的要求了.
MSg : String;//只发送字符
IdUDPServer1.SendBuffer(IP,Port,Msg,sizeof(Msg);
然后接收端:OnUDPRead事件(也用一个UDPServer)
AData.readBuffer(Msg,Sizeof(Msg))
ShowMessage(Msg);

接分..(努力赚分,兄弟别让我失望)

借个地方说两句.
最近在写个通信程序.类似QQ.写得我烦死了.也头痛死了.唉
 
发信息例子 http://www.delphibbs.com/keylife/images/u196832/UDP20060220.rar
有两个VCL/ SDK
 
我也正想着这个问题。

关注中...

顺便帮你up
 
后退
顶部