当前位置:新注册送38元体验金 > 新注册送38元体验金编程 > 【笔记本】第二阶段工作完成,笔记本第二阶段

【笔记本】第二阶段工作完成,笔记本第二阶段

文章作者:新注册送38元体验金编程 上传时间:2019-08-22

【笔记本】第二阶段工作完成,笔记本第二阶段

完成了服务端的基本功能,把客户端也完善了一些,服务端功能实现:

开发环境:Delphi XE8 superobject DIOCP

选择DIOCP的原因:这两年,这个框架的作者很勤劳,这两年一直在不断的完善,算是Delphi这个圈子里面比较成熟的通讯框架了。

服务端写的还比较粗,文档校验、文档版本管理这些功能都没做,用是可以用了,但是还是要继续完善。没有截图,来两段代码吧。

 1 const
 2   MSG_SERVICE_USER            = 0;
 3   MSG_SERVICE_FILE            = 1;
 4 
 5 const
 6   MSG_CONNECTFAIL             = 404;    //连接失败
 7 
 8 const
 9   MSG_USER_SUCCESSFUL         = 1000;
10   MSG_USER_LOGIN              = 1001;
11   MSG_USER_REGISTER           = 1002;
12 
13 const
14   MSG_FILE_REQ_UPLOAD         = 2001;
15   MSG_FILE_READYUPLOAD        = 2002;
16   MSG_FILE_UPLOADING          = 2003;
17   MSG_FILE_REQ_DOWNLOAD       = 2004;
18   MSG_FILE_READYDOWNLOAD      = 2005;
19   MSG_FILE_DOWNLOADING        = 2006;
20   MSG_FILE_GETFILESIZE        = 2007;
21   MSG_FILE_DELETEFILE         = 2008;
22 
23 const
24   MSG_ERR_UNKNOWN             = 4001;
25   MSG_ERR_INVALIDUSER         = 4002;   //无效用户
26   MSG_ERR_USERNOTFOUND        = 4003;   //用户不存在
27   MSG_ERR_WRONGPASSWORD       = 4004;   //密码错误
28   MSG_ERR_USEREXIST           = 4005;   //用户名已经存在(注册新用户业务)
29   MSG_ERR_USERTOOMUCH         = 4006;   //用户数量已经达到上限(注册新用户业务)
30   MSG_ERR_SPACEFULL           = 4007;   //空间已满
31   MSG_ERR_NOTAUTHUPLOAD       = 4008;   //没有上传权限
32   MSG_ERR_NOTAUTHDOWNLOAD     = 4009;   //没有下载权限
33   MSG_ERR_FILENOTFOUND        = 4010;   //文件不存在

  1 unit snt.client.net.filetrans;
  2 
  3 interface
  4 
  5 uses
  6   System.SysUtils, System.Classes, System.Math, diocp.coder.tcpClient,
  7   utils.simpleMsgPack, snt.net.coder.stream, snt.net.msgcode;
  8 
  9 type
 10   TSNTFileTransContext = class(TObject)
 11   private
 12     FCoderTcpClient: TDiocpCoderTcpClient;
 13     FDiocpContext: TIocpCoderRemoteContext;
 14     FCMDStream: TMemoryStream;
 15     FCMDMsgPack: TSimpleMsgPack;
 16     procedure OnRecvObject(pvObject:TObject);
 17     procedure SendCMDObject(pvCMDObject: TSimpleMsgPack);
 18     function  GetFileSize(const pvFile: string): Int64;
 19   private
 20     FFileStream: TFileStream;
 21     FLocalFile, FRemoteFile: string;
 22     FFileSize: Int64;
 23     function  upload(const pvRemoteFile, pvToken: string): Int64;
 24     procedure uploadNextBlock(const pvToken: string = '');
 25     function  download(const pvRemoteFile: string; const pvFileSize: Int64): Int64;
 26     procedure downloadNextBlock();
 27   public
 28     constructor Create(pvCoderTcpClient: TDiocpCoderTcpClient);
 29     destructor Destroy; override;
 30 
 31     procedure init(const pvHost: string; const pvPort: Integer);
 32     procedure requestUpload(const pvLocalFile, pvToken: string);
 33     procedure requestDownload(const pvLocalFile, pvToken: string);
 34   end;
 35 
 36 implementation
 37 
 38 uses utils.safeLogger;
 39 
 40 const
 41   SEC_SIZE = 1024 * 1024;
 42 
 43 { TSNTFileTransContext }
 44 
 45 constructor TSNTFileTransContext.Create(pvCoderTcpClient: TDiocpCoderTcpClient);
 46 begin
 47   inherited Create;
 48   FCoderTcpClient:= pvCoderTcpClient;
 49   FCMDStream  := TMemoryStream.Create;
 50   FCMDMsgPack := TSimpleMsgPack.Create;
 51 end;
 52 
 53 destructor TSNTFileTransContext.Destroy;
 54 begin
 55   if Assigned(FFileStream) then FFileStream.Free;
 56   FCMDStream.Free;
 57   FCMDMsgPack.Free;
 58   inherited;
 59 end;
 60 
 61 procedure TSNTFileTransContext.init(const pvHost: string; const pvPort: Integer);
 62 begin
 63   FDiocpContext:= TIocpCoderRemoteContext(FCoderTcpClient.Add);
 64   FDiocpContext.RegisterCoderClass(TIOCPStreamDecoder, TIOCPStreamEncoder);
 65   FDiocpContext.OnContextAction:= OnRecvObject;
 66   if not FDiocpContext.Active then
 67   begin
 68     FDiocpContext.Host:= pvHost;
 69     FDiocpContext.Port:= pvPort;
 70     FDiocpContext.Connect;
 71   end;
 72 end;
 73 
 74 procedure TSNTFileTransContext.SendCMDObject(pvCMDObject: TSimpleMsgPack);
 75 var
 76   lvCMDStream:TMemoryStream;
 77 begin
 78   lvCMDStream := TMemoryStream.Create;
 79   try
 80     pvCMDObject.EncodeToStream(lvCMDStream);
 81     FDiocpContext.WriteObject(lvCMDStream);
 82   finally
 83     lvCMDStream.Free;
 84   end;
 85 end;
 86 
 87 function TSNTFileTransContext.GetFileSize(const pvFile: string): Int64;
 88 var
 89   lvFileStream: TFileStream;
 90 begin
 91   lvFileStream:= TFileStream.Create(FLocalFile, fmOpenRead);
 92   try
 93     result:= lvFileStream.Size;
 94   finally
 95     lvFileStream.Free;
 96   end;
 97 end;
 98 
 99 procedure TSNTFileTransContext.requestUpload(const pvLocalFile, pvToken: string);
100 var
101   lvMsgData: TSimpleMsgPack;
102 begin
103   lvMsgData:= TSimpleMsgPack.Create;
104   try
105     FLocalFile:= pvLocalFile;
106     lvMsgData.I['service.type']    := MSG_SERVICE_FILE;
107     lvMsgData.I['msg.code']        := MSG_FILE_REQ_UPLOAD;
108     lvMsgData.S['params.filename'] := ExtractFileName(pvLocalFile);
109     lvMsgData.I['params.filesize'] := GetFileSize(pvLocalFile);
110     lvMsgData.S['params.token']    := pvToken;
111     SendCMDObject(lvMsgData);
112   finally
113     FreeAndNil(lvMsgData);
114   end;
115 end;
116 
117 procedure TSNTFileTransContext.requestDownload(const pvLocalFile, pvToken: string);
118 var
119   lvMsgData: TSimpleMsgPack;
120 begin
121   lvMsgData:= TSimpleMsgPack.Create;
122   try
123     FLocalFile:= pvLocalFile;
124     lvMsgData.I['service.type']    := MSG_SERVICE_FILE;
125     lvMsgData.I['msg.code']        := MSG_FILE_REQ_DOWNLOAD;
126     lvMsgData.S['params.filename'] := ExtractFileName(pvLocalFile);
127     lvMsgData.S['params.token']    := pvToken;
128     SendCMDObject(lvMsgData);
129   finally
130     FreeAndNil(lvMsgData);
131   end;
132 end;
133 
134 function TSNTFileTransContext.upload(const pvRemoteFile, pvToken: string): Int64;
135 begin
136   FFileStream:= TFileStream.Create(FLocalFile, fmOpenRead);
137   FRemoteFile:= pvRemoteFile;
138   uploadNextBlock(pvToken);
139 end;
140 
141 procedure TSNTFileTransContext.uploadNextBlock(const pvToken: string);
142 var
143   lvPosition, lvSize: Int64;
144 begin
145   lvPosition:= FFileStream.Position;
146   if (FFileStream.Position = FFileStream.Size) then exit;
147 
148   FCMDMsgPack.clear();
149   FCMDMsgPack.I['service.type']   := MSG_SERVICE_FILE;
150   FCMDMsgPack.I['msg.code']       := MSG_FILE_UPLOADING;
151   FCMDMsgPack.S['params.filename']:= FRemoteFile;
152   FCMDMsgPack.S['params.token']   := pvToken;
153   FCMDMsgPack.I['params.start']   := lvPosition;
154   lvSize:= Min(SEC_SIZE, FFileStream.Size- FFileStream.Position);
155   FCMDMsgPack.ForcePathObject('params.data').LoadBinaryFromStream(FFileStream, lvSize);
156   if (FFileStream.Position = FFileStream.Size) then
157     FCMDMsgPack.B['params.isend'] := True;
158   //
159   FCMDStream.Clear;
160   FCMDMsgPack.EncodeToStream(FCMDStream);
161   FDiocpContext.WriteObject(FCMDStream);
162 end;
163 
164 
165 function TSNTFileTransContext.download(const pvRemoteFile: string;
166 
167   const pvFileSize: Int64): Int64;
168 
169 begin
170   FFileStream:= TFileStream.Create(FLocalFile, fmCreate or fmShareDenyWrite);
171   FRemoteFile:= pvRemoteFile;
172   FFileSize  := pvFileSize;
173   downloadNextBlock();
174 end;
175 
176 procedure TSNTFileTransContext.downloadNextBlock;
177 var
178   lvPosition, lvSize: Int64;
179   lvBytes: TBytes;
180 begin
181   lvBytes := FCMDMsgPack.ForcePathObject('data').AsBytes;
182   FFileStream.Write(lvBytes[0], Length(lvBytes));
183   if FFileStream.Size = FFileSize then exit;
184 
185   FCMDMsgPack.clear();
186   FCMDMsgPack.I['service.type']    := MSG_SERVICE_FILE;
187   FCMDMsgPack.I['msg.code']        := MSG_FILE_DOWNLOADING;
188   FCMDMsgPack.S['params.filename'] := FRemoteFile;
189   FCMDMsgPack.I['params.start']    := FFileStream.Position;
190   FCMDStream.Clear;
191   FCMDMsgPack.EncodeToStream(FCMDStream);
192   FDiocpContext.WriteObject(FCMDStream);
193 end;
194 
195 procedure TSNTFileTransContext.OnRecvObject(pvObject: TObject);
196 var
197   lvMsgData: TSimpleMsgPack;
198 begin
199   lvMsgData:= TSimpleMsgPack.Create;
200   try
201     lvMsgData.DecodeFromStream(TMemoryStream(pvObject));
202     // server error
203     if lvMsgData.I['result.code'] = -1 then
204     begin
205       sfLogger.logMessage(lvMsgData.S['result.msg']);
206       exit;
207     end;
208     sfLogger.logMessage(lvMsgData.S['msg.code']);
209     // logic
210     case lvMsgData.I['msg.code'] of
211       MSG_FILE_READYUPLOAD:
212         upload(lvMsgData.S['params.filename'],lvMsgData.S['params.token']);
213       MSG_FILE_UPLOADING:
214         uploadNextBlock();
215       MSG_FILE_READYDOWNLOAD:
216         download(lvMsgData.S['params.filename'],lvMsgData.I['params.filesize']);
217       MSG_FILE_DOWNLOADING:
218         downloadNextBlock();
219       MSG_ERR_NOTAUTHUPLOAD:
220         ;//没有上传权限
221       MSG_ERR_SPACEFULL:
222         ;//空间不足
223       MSG_ERR_NOTAUTHDOWNLOAD:
224         ;//没有下载权限
225       MSG_ERR_FILENOTFOUND:
226         ;//文件不存在
227     end;
228   finally
229     lvMsgData.Free;
230   end;
231 end;

 

完成了服务端的基本功能,把客户端也完善了一些,服务端功能实现: 开发环境:Delphi...

本文由新注册送38元体验金发布于新注册送38元体验金编程,转载请注明出处:【笔记本】第二阶段工作完成,笔记本第二阶段

关键词: