Communication.PAS
上传用户:psxgmh
上传日期:2013-04-08
资源大小:15112k
文件大小:8k
源码类别:

Delphi/CppBuilder

开发平台:

Delphi

  1. unit Communication;
  2. interface
  3. uses
  4.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  5.   Dialogs, ScktComp, Menus, ComCtrls, StdCtrls, ExtCtrls,
  6.   IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdTCPServer, DiskList;
  7. //每次传送的最大字节数
  8. const MaxBufferSize = 100;
  9. //返回确认标记
  10. const returnconfirm = '!@#$';
  11. type
  12.   //用于接收数据
  13.   TIdcommserver = class(TIdTCPServer)
  14.     procedure commExecute(AThread: TIdPeerThread);
  15.   end;
  16. type
  17.   //用于发送数据的线程
  18.   TsendThread = class(TThread)
  19.   protected
  20.     procedure execute; override;
  21.   end;
  22. //初始化客户端
  23. function initClientConnect(const host: string; const port: integer; const AFileName: string; const AFilesize: longint): boolean; export;
  24. //关闭客户端
  25. procedure desClientConnect; export;
  26. //客户端向磁盘文件写数据
  27. function ClientWriteBuffer(var Abuffer; const aBuffersize: integer): integer; export;
  28. //初始化服务器端
  29. function initServerConnect(const port: integer; const AFileName: string; const AFilesize: longint): boolean; export;
  30. //断开服务器端连接
  31. procedure desserverconnect; export;
  32. //服务器端从磁盘队列读出数据
  33. function serverreadbuffer(var buffer; var buffersize: longint): boolean; export;
  34. var
  35.   IdCommClient: TIdTcpClient; //客户端Socket组件
  36.   IdCommServer: TIdCommServer; //服务器端socket组件
  37.   clientcommqueue: TcommQueue; //客户端磁盘队列
  38.   servercommqueue: TcommQueue; //服务器端磁盘队列
  39.   recvstream: TMemorystream; //接收的内存流
  40.   sendthread: TsendThread; //发送线程
  41. implementation
  42. //监视发送队列,发现磁盘队列不为空,就进行发送;
  43. procedure TSendThread.execute;
  44. var
  45.   buffersize: longint;
  46.   frontposition, buffsize: longint;
  47.   sendbuffer: pchar;
  48.   i: longint;
  49.   divbuffer: array[1..maxbuffersize + 5] of char;
  50.   recvaccount: integer;
  51.   recvbuffer: array[0..3] of char;
  52.   ss: string;
  53.   connectAgain: boolean;
  54. begin
  55.   connectAgain := false;
  56.   while not terminated do
  57.   begin
  58.     sleep(10);
  59.     //判断磁盘队列是否为空
  60.     if clientCommqueue.empty = 1 then
  61.       continue;
  62.     //判断是否重新连接
  63.     if connectAgain = true then
  64.     begin
  65.       try
  66.         IdCommClient.Disconnect;
  67.         idcommclient.Connect;
  68.       except
  69.         continue;
  70.       end;
  71.     end;
  72.     //得到头指针
  73.     frontposition := clientcommqueue.frontpointer;
  74.     //得到读出队列的大小
  75.     clientcommqueue.readbuffersize(frontposition, buffersize);
  76.     //分配sendBuffer缓冲区
  77.     getmem(sendbuffer, buffersize);
  78.     try
  79.       //读出队列
  80.       clientcommqueue.readQueue(sendbuffer^, buffersize);
  81.       //判断是否段开发送
  82.       if Buffersize > Maxbuffersize then
  83.       begin
  84.         for I := 1 to Buffersize div Maxbuffersize do
  85.         begin
  86.           buffsize := maxbuffersize + 1;
  87.           move(buffsize, divbuffer[1], 4);
  88.           move(sendbuffer[(I - 1) * maxbuffersize], divbuffer[5], maxbuffersize);
  89.           //最后一位代表还未发完,'Y'代表一条队列内容已发完
  90.           divbuffer[maxbuffersize + 5] := 'N';
  91.           try
  92.             IdCommClient.WriteBuffer(divbuffer, maxbuffersize + 5, true);
  93.           except
  94.             connectagain := true;
  95.             continue;
  96.           end;
  97.           sleep(10);
  98.         end;
  99.         buffsize := (buffersize mod maxbuffersize) + 1;
  100.         move(buffsize, divbuffer[1], 4);
  101.         move(sendbuffer[(I - 1) * maxbuffersize], divbuffer[5], Buffersize mod maxbuffersize);
  102.         divbuffer[(buffersize mod maxbuffersize) + 5] := 'Y';
  103.         try
  104.           IdCommClient.WriteBuffer(divbuffer, (Buffersize mod maxbuffersize) + 5, true);
  105.         except
  106.           connectagain := true;
  107.           continue;
  108.         end;
  109.       end
  110.       else
  111.       begin
  112.         buffsize := buffersize + 1;
  113.         move(buffsize, divbuffer[1], 4);
  114.         move(sendbuffer[0], divbuffer[5], buffersize);
  115.         divbuffer[buffersize + 5] := 'Y';
  116.         try
  117.           IdCommClient.WriteBuffer(divbuffer, Buffersize + 5, true);
  118.         except
  119.           connectagain := true;
  120.           continue;
  121.         end;
  122.       end;
  123.       if idcommclient.ReadFromStack(true, 1000, true, nil) <> 4 then
  124.         continue;
  125.       ss := idcommclient.ReadString(4);
  126.       //如果未发送成功,则回写
  127.       if ss <> returnconfirm then
  128.         clientcommqueue.writeQueue(sendbuffer^, buffersize);
  129.     finally
  130.       freemem(sendbuffer);
  131.     end;
  132.   end;
  133. end;
  134. //初始化客户端连接,并且指定磁盘队列;
  135. function initclientconnect(const host: string; const port: integer; const AFileName: string; const AFilesize: longint): boolean;
  136. begin
  137.   //创建客户端的indy组件
  138.   IdCommClient := TIdTCPClient.Create(nil);
  139.   result := true;
  140.   if IdCommClient.Connected = true then
  141.     exit;
  142.   //打开socket,并连接服务器
  143.   IdCommClient.Host := host;
  144.   IdCommClient.Port := port;
  145.   try
  146.     IdCommClient.Connect;
  147.   except
  148.     result := false;
  149.   end;
  150.   //创建客户端磁盘队列
  151.   clientCommQueue := TcommQueue.Create(nil);
  152.   //打开磁盘队列
  153.   if clientcommqueue.open(AFilename, AFilesize) <> 1 then
  154.     result := false;
  155.   //创建发送监送线程
  156.   sendthread := Tsendthread.create(false);
  157. end;
  158. //客户端发送缓冲区,并进行队列处理;
  159. function ClientWriteBuffer(var Abuffer; const aBuffersize: integer): integer;
  160. var
  161.   I: integer;
  162. begin
  163.   result := 1;
  164.   //写队列
  165.   if clientcommqueue.writequeue(abuffer, aBuffersize) <> 1 then
  166.   begin
  167.     result := -1; //写队列出错
  168.     exit;
  169.   end;
  170. end;
  171. //断开客户端连接,并关闭磁盘队列;
  172. procedure desclientconnect;
  173. begin
  174.   //发送监视线程终止
  175.   sendThread.Terminate;
  176.   //断开连接
  177.   if IdCommClient.Connected = true then
  178.     IdCommClient.Disconnect;
  179.   IdCommClient.Free;
  180.   //关闭磁盘队列
  181.   clientcommqueue.close;
  182. end;
  183. //初始化服务器端监听,并且指定接收磁盘队列;
  184. function initserverconnect(const port: integer; const AFileName: string; const AFilesize: longint): boolean;
  185. begin
  186.   //创建服务器端socket
  187.   IdCommServer := TIdcommServer.Create(nil);
  188.   result := true;
  189.   IdCommServer.OnExecute := IdCommServer.commexecute;
  190.   if IdCommServer.active = true then
  191.     exit;
  192.   //打开服务器端socket,并开始监听连接
  193.   IdCommServer.DefaultPort := port;
  194.   try
  195.     IdCommServer.active := true;
  196.   except
  197.     result := false;
  198.   end;
  199.   recvstream := TMemoryStream.create;
  200.   //创建服务器端磁盘队列
  201.   servercommqueue := Tcommqueue.Create(nil);
  202.   //打开磁盘队列
  203.   if servercommqueue.open(AFileName, AFilesize) <> 1 then
  204.     result := false;
  205. end;
  206. //服务器端接收事件
  207. procedure TIdcommserver.commexecute(AThread: TIdPeerThread);
  208. var
  209.   recvsize: integer;
  210.   buffer: pchar;
  211.   recvbuffer: pchar;
  212. begin
  213.   //接收数据,一开始接收发送的数据区的大小
  214.   Athread.Connection.ReadBuffer(recvsize, 4);
  215.   getmem(buffer, recvsize);
  216.   try
  217.     Athread.Connection.Readbuffer(buffer^, recvsize);
  218.     //判断最后一位是'Y'还是'N',以此代表是否发送完
  219.     if (recvStream.Size = 0) and (buffer[recvsize - 1] = 'Y') then
  220.     begin
  221.       if servercommqueue.writequeue(buffer^, recvsize - 1) = 1 then
  222.         Athread.Connection.Write(returnconfirm);
  223.     end
  224.     else if not assigned(recvstream) and (buffer[recvsize - 1] = 'N') then
  225.     begin
  226.       recvstream.WriteBuffer(buffer^, recvsize - 1);
  227.     end
  228.     else if assigned(recvstream) and (buffer[recvsize - 1] = 'N') then
  229.     begin
  230.       recvstream.WriteBuffer(buffer^, recvsize - 1);
  231.     end
  232.     else if (assigned(recvstream)) and (buffer[recvsize - 1] = 'Y') then
  233.     begin
  234.       recvstream.Write(buffer^, recvsize - 1);
  235.       try
  236.         getmem(recvbuffer, recvstream.size);
  237.         recvstream.Seek(0, soFromBeginning);
  238.         recvstream.ReadBuffer(recvbuffer^, recvstream.Size);
  239.         if servercommqueue.writequeue(recvbuffer^, recvstream.Size) = 1 then
  240.           //回发收到信息
  241.           Athread.Connection.Write(returnconfirm);
  242.         freemem(recvbuffer, recvstream.size);
  243.       finally
  244.         recvstream.Clear;
  245.       end;
  246.     end;
  247.   finally
  248.     freemem(buffer);
  249.   end;
  250. end;
  251. //服务器端读队列
  252. function serverReadBuffer(var buffer; var buffersize: longint): boolean;
  253. begin
  254.   result := true;
  255.   if not servercommqueue.readQueue(buffer, buffersize) = 1 then
  256.     result := false;
  257. end;
  258. //服务器端断开连接
  259. procedure desServerConnect;
  260. begin
  261.   if IdCommServer.Active = true then
  262.     IdCommServer.Active := false;
  263.   IdCommServer.Free;
  264.   recvstream.Free;
  265.     //关闭磁盘队列
  266.   servercommqueue.Free;
  267. end;
  268. end.