serversocket 的问题 做一个代理程序,用两个serversocket,一个接收服务端发过来的数据,转发给终端设备,另一个接收终端设备发过来的数据,转发给服务端,现在的问题是,当一传数据的时候,界面就不动了,不想用Application.ProcessMessages;所以想用多线程来解决,但以前没搞过,没有思路,希望高手指点一下,先谢谢拉!~ 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 Indy有一个TIdTCPPortMapper简单多了。 没找到呀,我是delphi 6,能详细说一下吗,能发个例子更好 你找找这本书的第八章代码,有针对行的参考《Delphi深度编程及其项目应用开发》,他的官方出版社中国水利水电出版社网站也有 在Indy servers 下的IdMappedPortTcp unit Communication;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ScktComp, Menus, ComCtrls, StdCtrls, ExtCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdTCPServer, DiskList;//每次传送的最大字节数const MaxBufferSize = 100;//返回确认标记const returnconfirm = '!@#$';type //用于接收数据 TIdcommserver = class(TIdTCPServer) procedure commExecute(AThread: TIdPeerThread); end;type //用于发送数据的线程 TsendThread = class(TThread) protected procedure execute; override; end;//初始化客户端function initClientConnect(const host: string; const port: integer; const AFileName: string; const AFilesize: longint): boolean; export;//关闭客户端procedure desClientConnect; export;//客户端向磁盘文件写数据function ClientWriteBuffer(var Abuffer; const aBuffersize: integer): integer; export;//初始化服务器端function initServerConnect(const port: integer; const AFileName: string; const AFilesize: longint): boolean; export;//断开服务器端连接procedure desserverconnect; export;//服务器端从磁盘队列读出数据function serverreadbuffer(var buffer; var buffersize: longint): boolean; export;var IdCommClient: TIdTcpClient; //客户端Socket组件 IdCommServer: TIdCommServer; //服务器端socket组件 clientcommqueue: TcommQueue; //客户端磁盘队列 servercommqueue: TcommQueue; //服务器端磁盘队列 recvstream: TMemorystream; //接收的内存流 sendthread: TsendThread; //发送线程implementation//监视发送队列,发现磁盘队列不为空,就进行发送;procedure TSendThread.execute;var buffersize: longint; frontposition, buffsize: longint; sendbuffer: pchar; i: longint; divbuffer: array[1..maxbuffersize + 5] of char; recvaccount: integer; recvbuffer: array[0..3] of char; ss: string; connectAgain: boolean;begin connectAgain := false; while not terminated do begin sleep(10); //判断磁盘队列是否为空 if clientCommqueue.empty = 1 then continue; //判断是否重新连接 if connectAgain = true then begin try IdCommClient.Disconnect; idcommclient.Connect; except continue; end; end; //得到头指针 frontposition := clientcommqueue.frontpointer; //得到读出队列的大小 clientcommqueue.readbuffersize(frontposition, buffersize); //分配sendBuffer缓冲区 getmem(sendbuffer, buffersize); try //读出队列 clientcommqueue.readQueue(sendbuffer^, buffersize); //判断是否段开发送 if Buffersize > Maxbuffersize then begin for I := 1 to Buffersize div Maxbuffersize do begin buffsize := maxbuffersize + 1; move(buffsize, divbuffer[1], 4); move(sendbuffer[(I - 1) * maxbuffersize], divbuffer[5], maxbuffersize); //最后一位代表还未发完,'Y'代表一条队列内容已发完 divbuffer[maxbuffersize + 5] := 'N'; try IdCommClient.WriteBuffer(divbuffer, maxbuffersize + 5, true); except connectagain := true; continue; end; sleep(10); end; buffsize := (buffersize mod maxbuffersize) + 1; move(buffsize, divbuffer[1], 4); move(sendbuffer[(I - 1) * maxbuffersize], divbuffer[5], Buffersize mod maxbuffersize); divbuffer[(buffersize mod maxbuffersize) + 5] := 'Y'; try IdCommClient.WriteBuffer(divbuffer, (Buffersize mod maxbuffersize) + 5, true); except connectagain := true; continue; end; end else begin buffsize := buffersize + 1; move(buffsize, divbuffer[1], 4); move(sendbuffer[0], divbuffer[5], buffersize); divbuffer[buffersize + 5] := 'Y'; try IdCommClient.WriteBuffer(divbuffer, Buffersize + 5, true); except connectagain := true; continue; end; end; if idcommclient.ReadFromStack(true, 1000, true, nil) <> 4 then continue; ss := idcommclient.ReadString(4); //如果未发送成功,则回写 if ss <> returnconfirm then clientcommqueue.writeQueue(sendbuffer^, buffersize); finally freemem(sendbuffer); end; end;end;//初始化客户端连接,并且指定磁盘队列;function initclientconnect(const host: string; const port: integer; const AFileName: string; const AFilesize: longint): boolean;begin //创建客户端的indy组件 IdCommClient := TIdTCPClient.Create(nil); result := true; if IdCommClient.Connected = true then exit; //打开socket,并连接服务器 IdCommClient.Host := host; IdCommClient.Port := port; try IdCommClient.Connect; except result := false; end; //创建客户端磁盘队列 clientCommQueue := TcommQueue.Create(nil); //打开磁盘队列 if clientcommqueue.open(AFilename, AFilesize) <> 1 then result := false; //创建发送监送线程 sendthread := Tsendthread.create(false);end;//客户端发送缓冲区,并进行队列处理;function ClientWriteBuffer(var Abuffer; const aBuffersize: integer): integer;var I: integer;begin result := 1; //写队列 if clientcommqueue.writequeue(abuffer, aBuffersize) <> 1 then begin result := -1; //写队列出错 exit; end;end;//断开客户端连接,并关闭磁盘队列;procedure desclientconnect;begin //发送监视线程终止 sendThread.Terminate; //断开连接 if IdCommClient.Connected = true then IdCommClient.Disconnect; IdCommClient.Free; //关闭磁盘队列 clientcommqueue.close;end;//初始化服务器端监听,并且指定接收磁盘队列;function initserverconnect(const port: integer; const AFileName: string; const AFilesize: longint): boolean;begin //创建服务器端socket IdCommServer := TIdcommServer.Create(nil); result := true; IdCommServer.OnExecute := IdCommServer.commexecute; if IdCommServer.active = true then exit; //打开服务器端socket,并开始监听连接 IdCommServer.DefaultPort := port; try IdCommServer.active := true; except result := false; end; recvstream := TMemoryStream.create; //创建服务器端磁盘队列 servercommqueue := Tcommqueue.Create(nil); //打开磁盘队列 if servercommqueue.open(AFileName, AFilesize) <> 1 then result := false;end;//服务器端接收事件procedure TIdcommserver.commexecute(AThread: TIdPeerThread);var recvsize: integer; buffer: pchar; recvbuffer: pchar;begin //接收数据,一开始接收发送的数据区的大小 Athread.Connection.ReadBuffer(recvsize, 4); getmem(buffer, recvsize); try Athread.Connection.Readbuffer(buffer^, recvsize); //判断最后一位是'Y'还是'N',以此代表是否发送完 if (recvStream.Size = 0) and (buffer[recvsize - 1] = 'Y') then begin if servercommqueue.writequeue(buffer^, recvsize - 1) = 1 then Athread.Connection.Write(returnconfirm); end else if not assigned(recvstream) and (buffer[recvsize - 1] = 'N') then begin recvstream.WriteBuffer(buffer^, recvsize - 1); end else if assigned(recvstream) and (buffer[recvsize - 1] = 'N') then begin recvstream.WriteBuffer(buffer^, recvsize - 1); end else if (assigned(recvstream)) and (buffer[recvsize - 1] = 'Y') then begin recvstream.Write(buffer^, recvsize - 1); try getmem(recvbuffer, recvstream.size); recvstream.Seek(0, soFromBeginning); recvstream.ReadBuffer(recvbuffer^, recvstream.Size); if servercommqueue.writequeue(recvbuffer^, recvstream.Size) = 1 then //回发收到信息 Athread.Connection.Write(returnconfirm); freemem(recvbuffer, recvstream.size); finally recvstream.Clear; end; end; finally freemem(buffer); end;end;//服务器端读队列function serverReadBuffer(var buffer; var buffersize: longint): boolean;begin result := true; if not servercommqueue.readQueue(buffer, buffersize) = 1 then result := false;end;//服务器端断开连接procedure desServerConnect;begin if IdCommServer.Active = true then IdCommServer.Active := false; IdCommServer.Free; recvstream.Free; //关闭磁盘队列 servercommqueue.Free;end;end. hThread:=CreateThread(nil,0,@ComProc,nil,0,ThreadId);//ComProc为调用的函数用CreateThread创建两个进程,专门处理收发,不要在主线程里面做收发,要不然有数据进就是死循环了 接分PS: 我的目标是 ----> ^_^ 接分PS: 我的目标是 ----> ^_^ 接分..PS: 我的目标是 ----> ^_^ 怎么 没什么印象 这是delphi? 不知道你用什么语言,说下思路吧,就是在你初始化窗口的线程中开一个线程用来不断判断程序的状态(当然你要给你的程序设置不同的状态值,比如说,建立连接一个状态,发数据一个状态,一便以后有程序改变状态(比如如果发送的时候socket链接断了,可以转移到建立socket的状态去再建立)),在这个新开的线程中再开建立socket的线程和接发数据的线程,接受到的数据存储到一个buff里面,之后当buff里面有数据的时候你就可以发送出去了。这些收发数据的线程里面肯定都是要用死循环的,所以最好用信号量来控制起来,这样在没有数据可收发的时候就可以节省一些资源。还有就是buff要用临界区封起来,不然会出现问题。注意到这几点应该整个程序的框架就搭建起来了。能跑了。再调调就差不多了。 没找到呀,我是delphi 6,能详细说一下吗,能发个例子更好 在Indy servers 下的IdMappedPortTcp Delphi与数据库连接时成功了但不显示数据库的数据,急...急....急.... 请问用sql语句怎么将图片存进数据库? delphi快捷键的问题 再发:求救,将程序从98迁移到xp下的打印问题,请救助。 当查询结果为0行时,AdoQuery.Close为何会出错? 在线等,请各位帮忙? 从vb转向delphi,有无好建议 delphi 多条件过滤问题,急死人了~2天都没搞出来~ Delphi6里面带的Installshield问题,以及如果支持paradox问题? 高手帮忙啊 关于GDI+从流加载PNG文件 delphi 改变panel的颜色
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, Menus, ComCtrls, StdCtrls, ExtCtrls,
IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdTCPServer, DiskList;//每次传送的最大字节数
const MaxBufferSize = 100;//返回确认标记
const returnconfirm = '!@#$';
type
//用于接收数据
TIdcommserver = class(TIdTCPServer)
procedure commExecute(AThread: TIdPeerThread);
end;type
//用于发送数据的线程
TsendThread = class(TThread)
protected
procedure execute; override;
end;//初始化客户端
function initClientConnect(const host: string; const port: integer; const AFileName: string; const AFilesize: longint): boolean; export;
//关闭客户端
procedure desClientConnect; export;
//客户端向磁盘文件写数据
function ClientWriteBuffer(var Abuffer; const aBuffersize: integer): integer; export;
//初始化服务器端
function initServerConnect(const port: integer; const AFileName: string; const AFilesize: longint): boolean; export;
//断开服务器端连接
procedure desserverconnect; export;
//服务器端从磁盘队列读出数据
function serverreadbuffer(var buffer; var buffersize: longint): boolean; export;var
IdCommClient: TIdTcpClient; //客户端Socket组件
IdCommServer: TIdCommServer; //服务器端socket组件
clientcommqueue: TcommQueue; //客户端磁盘队列
servercommqueue: TcommQueue; //服务器端磁盘队列
recvstream: TMemorystream; //接收的内存流
sendthread: TsendThread; //发送线程
implementation//监视发送队列,发现磁盘队列不为空,就进行发送;procedure TSendThread.execute;
var
buffersize: longint;
frontposition, buffsize: longint;
sendbuffer: pchar;
i: longint;
divbuffer: array[1..maxbuffersize + 5] of char;
recvaccount: integer;
recvbuffer: array[0..3] of char;
ss: string;
connectAgain: boolean;
begin
connectAgain := false;
while not terminated do
begin
sleep(10);
//判断磁盘队列是否为空
if clientCommqueue.empty = 1 then
continue;
//判断是否重新连接
if connectAgain = true then
begin
try
IdCommClient.Disconnect;
idcommclient.Connect;
except
continue;
end;
end;
//得到头指针
frontposition := clientcommqueue.frontpointer;
//得到读出队列的大小
clientcommqueue.readbuffersize(frontposition, buffersize);
//分配sendBuffer缓冲区
getmem(sendbuffer, buffersize);
try
//读出队列
clientcommqueue.readQueue(sendbuffer^, buffersize);
//判断是否段开发送
if Buffersize > Maxbuffersize then
begin
for I := 1 to Buffersize div Maxbuffersize do
begin
buffsize := maxbuffersize + 1;
move(buffsize, divbuffer[1], 4);
move(sendbuffer[(I - 1) * maxbuffersize], divbuffer[5], maxbuffersize);
//最后一位代表还未发完,'Y'代表一条队列内容已发完
divbuffer[maxbuffersize + 5] := 'N';
try
IdCommClient.WriteBuffer(divbuffer, maxbuffersize + 5, true);
except
connectagain := true;
continue;
end;
sleep(10);
end;
buffsize := (buffersize mod maxbuffersize) + 1;
move(buffsize, divbuffer[1], 4);
move(sendbuffer[(I - 1) * maxbuffersize], divbuffer[5], Buffersize mod maxbuffersize);
divbuffer[(buffersize mod maxbuffersize) + 5] := 'Y';
try
IdCommClient.WriteBuffer(divbuffer, (Buffersize mod maxbuffersize) + 5, true);
except
connectagain := true;
continue;
end;
end
else
begin
buffsize := buffersize + 1;
move(buffsize, divbuffer[1], 4);
move(sendbuffer[0], divbuffer[5], buffersize);
divbuffer[buffersize + 5] := 'Y';
try
IdCommClient.WriteBuffer(divbuffer, Buffersize + 5, true);
except
connectagain := true;
continue;
end;
end;
if idcommclient.ReadFromStack(true, 1000, true, nil) <> 4 then
continue;
ss := idcommclient.ReadString(4);
//如果未发送成功,则回写
if ss <> returnconfirm then
clientcommqueue.writeQueue(sendbuffer^, buffersize);
finally
freemem(sendbuffer);
end;
end;
end;//初始化客户端连接,并且指定磁盘队列;function initclientconnect(const host: string; const port: integer; const AFileName: string; const AFilesize: longint): boolean;
begin
//创建客户端的indy组件
IdCommClient := TIdTCPClient.Create(nil);
result := true;
if IdCommClient.Connected = true then
exit;
//打开socket,并连接服务器
IdCommClient.Host := host;
IdCommClient.Port := port;
try
IdCommClient.Connect;
except
result := false;
end;
//创建客户端磁盘队列
clientCommQueue := TcommQueue.Create(nil);
//打开磁盘队列
if clientcommqueue.open(AFilename, AFilesize) <> 1 then
result := false;
//创建发送监送线程
sendthread := Tsendthread.create(false);
end;//客户端发送缓冲区,并进行队列处理;function ClientWriteBuffer(var Abuffer; const aBuffersize: integer): integer;
var
I: integer;
begin
result := 1;
//写队列
if clientcommqueue.writequeue(abuffer, aBuffersize) <> 1 then
begin
result := -1; //写队列出错
exit;
end;
end;//断开客户端连接,并关闭磁盘队列;procedure desclientconnect;
begin
//发送监视线程终止
sendThread.Terminate;
//断开连接
if IdCommClient.Connected = true then
IdCommClient.Disconnect;
IdCommClient.Free;
//关闭磁盘队列
clientcommqueue.close;
end;//初始化服务器端监听,并且指定接收磁盘队列;function initserverconnect(const port: integer; const AFileName: string; const AFilesize: longint): boolean;
begin
//创建服务器端socket
IdCommServer := TIdcommServer.Create(nil);
result := true;
IdCommServer.OnExecute := IdCommServer.commexecute;
if IdCommServer.active = true then
exit;
//打开服务器端socket,并开始监听连接
IdCommServer.DefaultPort := port;
try
IdCommServer.active := true;
except
result := false;
end;
recvstream := TMemoryStream.create;
//创建服务器端磁盘队列
servercommqueue := Tcommqueue.Create(nil);
//打开磁盘队列
if servercommqueue.open(AFileName, AFilesize) <> 1 then
result := false;
end;//服务器端接收事件procedure TIdcommserver.commexecute(AThread: TIdPeerThread);
var
recvsize: integer;
buffer: pchar;
recvbuffer: pchar;
begin
//接收数据,一开始接收发送的数据区的大小
Athread.Connection.ReadBuffer(recvsize, 4);
getmem(buffer, recvsize);
try
Athread.Connection.Readbuffer(buffer^, recvsize);
//判断最后一位是'Y'还是'N',以此代表是否发送完
if (recvStream.Size = 0) and (buffer[recvsize - 1] = 'Y') then
begin
if servercommqueue.writequeue(buffer^, recvsize - 1) = 1 then
Athread.Connection.Write(returnconfirm);
end
else if not assigned(recvstream) and (buffer[recvsize - 1] = 'N') then
begin
recvstream.WriteBuffer(buffer^, recvsize - 1);
end
else if assigned(recvstream) and (buffer[recvsize - 1] = 'N') then
begin
recvstream.WriteBuffer(buffer^, recvsize - 1);
end
else if (assigned(recvstream)) and (buffer[recvsize - 1] = 'Y') then
begin
recvstream.Write(buffer^, recvsize - 1);
try
getmem(recvbuffer, recvstream.size);
recvstream.Seek(0, soFromBeginning);
recvstream.ReadBuffer(recvbuffer^, recvstream.Size);
if servercommqueue.writequeue(recvbuffer^, recvstream.Size) = 1 then
//回发收到信息
Athread.Connection.Write(returnconfirm);
freemem(recvbuffer, recvstream.size);
finally
recvstream.Clear;
end;
end;
finally
freemem(buffer);
end;
end;//服务器端读队列function serverReadBuffer(var buffer; var buffersize: longint): boolean;
begin
result := true;
if not servercommqueue.readQueue(buffer, buffersize) = 1 then
result := false;
end;//服务器端断开连接procedure desServerConnect;
begin
if IdCommServer.Active = true then
IdCommServer.Active := false;
IdCommServer.Free;
recvstream.Free;
//关闭磁盘队列
servercommqueue.Free;
end;end.
用CreateThread创建两个进程,专门处理收发,不要在主线程里面做收发,要不然有数据进就是死循环了
PS:
我的目标是 ----> ^_^
PS:
我的目标是 ----> ^_^
PS:
我的目标是 ----> ^_^