码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-04-21 16:35:28      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:

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

  1. 通讯消息定义
  2. 用户管理结构设计
    • 在服务端用一个json文件存取用户数据
    • 自定义文件存取路径(考虑分布式部署)
  3. 用户注册
  4. 用户登录
  5. 文件上传校验
  6. 文件下载校验
  7. 批量文件上传、下载

开发环境: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;

 

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

标签:

原文地址:http://www.cnblogs.com/crymm/p/5417377.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!