TCPãŸãã¯HTTPãããã³ã«ãä»ããŠããªã¥ãŒã ãããã¯ãŒã¯éä¿¡ãå®è£
ããããšããããŸããïŒ ãã®ãããªçµéšã®å Žåã
ä»éããæçµçãªè§£æ±ºçã«ã©ã®çšåºŠæºè¶³ããŸãããïŒ æåã®è³ªåã«å¯Ÿããè¯å®çãªåçïŒäº€æã®ããã«ããŒãã¹ãããªããŠãïŒããã³çµæãšããŠçããå®è£
ã®æè»æ§ã«å¯Ÿããäžæºã«ããããã®ãããªäžå¹žãåãé€ã1ã€ã®æ¹æ³ãå«ããã®èšäºãæšå¥šã§ããŸãã
èè
ã®ããã«èŠãããã®åºçç©ã®äŸ¡å€ã¯ããã¹ãŠãæãåçŽãªæè²ã§ã¯ãªããçŸå®ã®äŸãšå¯æ¥ã«é¢é£ãããã®ã§ã¯ãªãã
å¥ã®èšäºã§ãã§ã«èšåããããåæ§ã«å®éã®ã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ããã®å®éã®ãœãªã¥ãŒã·ã§ã³ã®äžéšã§ç€ºãããŠãããšããäºå®ã«ããããŸãã
Indyã¯èšäºã®ããã°ã©ã ã³ãŒãã§äœ¿çšãããŠããããšã«æ³šæããŠãã ããããã ãããããã¯ãŒã¯ã®çžäºäœçšã«é¢ããè³æã§ã¯å¥åŠã«æãããããããŸããããèªè
ã¯ãã®ã©ã€ãã©ãªããã®ããã«èªèããå¿
èŠã¯ãããŸããããããã³ã«-èšèšã«é¢ãããã®ã§ãã
æã§ã¿ã¹ã¯ãèšå®ãã
åæãšåŒã°ããæ©èœã®1ã€ã§ãããèšäºã®åºç€ãšãªã£ãã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ã¯ãäžè¬çã«è²·ãç©ãªã¹ãã§ããååã®ãªã¹ããäœæãããŠãŒã¶ãŒã¯ã圌ãšäžç·ã«åºã«è¡ããããã®ããžãã¹ãå¥ã®äººïŒãŸãã¯ã°ã«ãŒãïŒã«å§ããŸãïŒããããããã®åŸã2çªç®ã®ã±ãŒã¹ã§ã¯ãæåã«ãã®ãªã¹ãããµãŒããŒïŒäžå€®ã¹ãã¬ãŒãžãšããŠïŒã«è»¢éãã次ã«ã¿ãŒã²ããã¢ãã€ã«ããã€ã¹ã«è»¢éããå¿
èŠããããŸã-ãã®æç¹ã§ããããã¯ãŒã¯ã䜿çšããå¿
èŠããããŸãã åæã¯åæ¹åã§ããããšã匷調ãã䟡å€ããããŸããã€ãŸããåå è
ïŒå¿
ãããäœæè
ã§ã¯ãªãïŒã«ãã£ãŠè¡ãããç·šéã¯ãä»ã®ãã¹ãŠã«åæ ãããŸãã å®äŸãšããŠã2人ã®éå¿çãªã¢ããã¥ã¢èŸ²åŠè
ããå¿
èŠãªããŒã«ãäºåã«è³Œå
¥ããå¿
èŠãããã¢ã€ãã¢ã®1ã€ãå®è£
ããããšã決å®ãããšããä»®æ³ã±ãŒã¹ãèããŠã¿ãŸãããã
ã¢ã¯ã·ã§ã³ | ãªã¹ãäœæè
| äºäººç® åæ |
---|
ãªã¹ãäœæ | - ãã±ãã
- æ°ŽãŸã猶
- ã»ã¢ãªã0.5 kg
| |
ã¡ã³ããŒãè¿œå ãããŠãã®åŸ åæãã | - ãã±ãã
- æ°ŽãŸã猶
- ã»ã¢ãªã0.5 kg
| - ãã±ãã
- æ°ŽãŸã猶
- ã»ã¢ãªã0.5 kg
|
ã³ã³ãã³ãç·šé | - ãã±ãã
- æ°ŽãŸã猶
- ã»ã¢ãªã0.5 kg
- ããã
| - ãã±ãã2å
- æ°ŽãŸã猶
- ã»ã¢ãªã1 kg
|
åæãã | - ãã±ãã2å
- æ°ŽãŸã猶
- ã»ã¢ãªã1 kg
- ããã
| - ãã±ãã2å
- æ°ŽãŸã猶
- ã»ã¢ãªã1 kg
- ããã
|
èŠèŠçã«ã¯ãããã€ã¹äžã§ã¯ãåæããã»ã¹å
šäœãã¢ãã¡ãŒã·ã§ã³ã€ã³ãžã±ãŒã¿ãŒãšãã£ã³ã»ã«ãã¿ã³ã§è¡šãããŸãã
圢åŒå
äžèšã®äŸã®è¡šã¯åãªãã¹ã±ããã§ãããåæäžã«èµ·ããã¹ãããšã®æãè¡šé¢çãªèª¬æã§ãããããæ·±å»ãªæè¡çã¿ã¹ã¯ãšããŠäœ¿çšããããšã¯ã§ããŸããã å®å
šãª
ãããã³ã«ãå¿
èŠã§ã-çžäºäœçšã®ã¹ãããã®è©³çŽ°ãã€æ®µéçã§å
æ¬çãªèª¬æ-誰ããäœãããªããããã¯ãŒã¯ãä»ããŠéä¿¡ãããã
OSIã¢ãã«ã«ããã°ã
ã¢ããªã±ãŒã·ã§ã³ã¬ãã« ïŒã€ãŸããã¢ããªã±ãŒã·ã§ã³ã¬ãã«ïŒã«ãªããŸãã äŸãšããŠããã¹ãŠã®ã¢ã¯ã·ã§ã³ã®çŽ10ïŒ
ãå«ãå®éã®ããã¥ã¡ã³ãã®å°ããªéšåã衚瀺ãããŸãïŒæé軞ã¯äžã«åããããŠããŸãïŒã
ãå®¢æ§ | ããŒã¿ | ãµãŒã㌠|
---|
åæãªã¹ãã®å®çŸ© | | |
... | | |
補åãã£ã¬ã¯ããªåæ | | |
... | | |
ãŠãŒã¶ãŒåæ | | |
... | | |
ãªã¹ãã®åæïŒ | | |
1.ãµãŒããŒãžã®è¿œå | | |
... | | |
2.ã¯ã©ã€ã¢ã³ããžã®è¿œå | | |
... | | |
3.å€æŽã®äº€æ | | |
å€æŽã®äº€æãå¿
èŠãªãªã¹ãã®è»¢éã éå±€ã®æåã®ã¬ãã«ã | - ãªã¹ãID
- ãªã¹ãããã·ã¥
- 圌ã®åå«ã®ããã·ã¥ïŒ
| |
| | ããã·ã¥åæïŒ |
| ããã·ã¥äžèŽéç¥ã | 1.ãã¹ãŠã®äžèŽ- åæã®çµäº ã |
åæã®çµäºã | | |
| 転éã®èŠä»¶ïŒ
- ã¯ã©ã€ã¢ã³ãã§å€æŽããããªã¹ããã£ãŒã«ã-ããã·ã¥ãäžèŽããªãå Žåã
- çŽæ¥ã®åå«ã®è©³çŽ°-åå«ã®ããã·ã¥ãç°ãªãå Žåã
| 2.å°ãªããšã1ã€ãäžèŽããŸããã |
èŠæ±ãããããŒã¿ã®éä¿¡ã éå±€ã®ç¬¬2ã¬ãã«ã | - å€æŽããããªã¹ããã£ãŒã«ãïŒå¿
èŠãªå ŽåïŒ
- ãŠãŒã¶ãŒã«ãã詳现åïŒå¿
èŠãªå ŽåïŒïŒ
- ID
- ããã·ã¥ïŒåé€ãããŠããªãå ŽåïŒ
- è¿œå ïŒäœæè
ã®ã¿ïŒïŒ
- åé€ãããŸãããïŒèè
ã®ã¿ïŒïŒ
- èŠçŽ ããšã®è©³çŽ°ïŒå¿
èŠãªå ŽåïŒïŒ
- ID
- ããã·ã¥ïŒåé€ãããŠããªãå ŽåïŒ
- ãã®åå«ã®ããã·ã¥ã¯ãã£ããã§ãïŒåé€ãããŠããªãå ŽåïŒã
- åé€ããŸãããïŒ
| |
... | | |
ããã«ç解ããããã«ãäžèšã®ãããã³ã«ãã©ã°ã¡ã³ãã®ãã¹ãŠã®ãã¥ã¢ã³ã¹ãæãäžããå¿
èŠã¯ãããŸãã-äž»ãªããšã¯ãã¯ã©ã€ã¢ã³ãåŽïŒå·ŠåïŒã«ã¢ã¯ã·ã§ã³ãããããšãç解ããããšã§ãããããã¯ãŒã¯ãä»ããŠéä¿¡ããåæããã³ãã®ä»ã®äœæ¥ãå®è¡ãããµãŒããŒåŽïŒå³ã®åïŒããããŸãã
é¡ã®æ±ºå®
茞é
ãããã³ã«ãå®è£
ããåã«ããã©ã³ã¹ããŒãã決å®ããå¿
èŠããããŸããããã¯ãããŒã¿ã®ç©ççãªè»¢éãæ
åœããåãã¬ãã«ãŸãã¯åºç€ãšãªãã¬ãã«ã®ãããã³ã«ã§ãã HTTPãšTCPã®2ã€ã®æçœãªéžæè¢ããããŸãïŒUDPãæ確ãªçç±-é
ä¿¡ã¯ä¿èšŒãããŸãããããã§ã¯äœ¿çšã§ããŸããïŒã æçµçã«ãéžæã¯2ã€ã®çç±ã§2çªç®ã®ãªãã·ã§ã³ã«ãªããŸãããTCPã¯ããã®ãã€ããªã®æ§è³ªã«ããã転éããããã¹ãŠã®ããŒã¿ãå®å
šã«èªç±ã«ããåæ§ã«ãã¢ãã€ã«ãããžã§ã¯ãã®æåŸã®å Žæã§ã¯ãªãåªããããã©ãŒãã³ã¹ãåããŠããŸãã
ã³ãŒãã®æåã®ããŒãžã§ã³
ãã©ã³ã¹ããŒããéžæã
TIdTCPClient
ãã¯ã©ã€ã¢ã³ãåŽã®äŸã䜿çšããŠãããã³ã«ã®æ¡ä»¶ä»ãå®è£
ãæ€èšãã
TIdTCPClient
ãããŒã¹ãšããŠïŒãµãŒããŒã«åºæ¬çãªéãã¯ãããŸãã-ã³ã³ããŒãã³ãã®ã¿ã
TIdTCPServer
å€æŽãã
TIdTCPServer
ïŒã ããããå
ã
ãã©ã°ã¡ã³ãã®äžéšã®ã¿ããã¹ãŠè¡šç€ºãããŸãã
... | | |
3.å€æŽã®äº€æ | | |
å€æŽã®äº€æãå¿
èŠãªãªã¹ãã®è»¢éã éå±€ã®æåã®ã¬ãã«ã | - ãªã¹ãID
- ãªã¹ãããã·ã¥
- 圌ã®åå«ã®ããã·ã¥ïŒ
| |
| | ããã·ã¥åæïŒ |
| ããã·ã¥äžèŽéç¥ã | 1.ãã¹ãŠã®äžèŽ- åæã®çµäº ã |
åæã®çµäºã | | |
... | | |
3ã€ã®ã³ã³ããŒãã³ããæã€åçŽãªãã©ãŒã ããããšããŸãã
TForm1 = class(TForm) TCPClient: TIdTCPClient; ButtonSync: TButton; StoredProcLists: TFDStoredProc; procedure ButtonSyncClick(Sender: TObject); end;
以äžã®ãã¿ã³ã¯ãªãã¯ãã³ãã©ãŒã«ã¯åŒ·åãªç°¡ç¥åãå«ãŸããŠãããããäžéšã®ãšã©ãŒã¯ã³ã³ãã€ã«ãããŸããããæåã®ç°¡åã§æçœãªã¢ãããŒãã®æ¬è³ªãäŒããŸãã
procedure TForm1.ButtonSyncClick(Sender: TObject); var Handler: TIdIOHandler; begin TCPClient.Connect; Handler := TCPClient.IOHandler;
æå®ãããéšåã¯ãã¢ããªã±ãŒã·ã§ã³ã®å
ã®ã³ãŒããšæ¯èŒããŠã¯ããã«ç°¡åã§ããããšãå床匷調ããå¿
èŠããããŸãããããã£ãŠãå®éã«ã¯ããã®ã€ãã³ãã¯ãå®å
šãªãããã³ã«ã«å¯ŸããŠãæ°åè¡ã«ãªããŸãã ããªã¥ãŒã ãããã§ãªãå ŽåïŒæ°çŸè¡ãŸã§ïŒãã¡ã€ã³ã¹ããŒãžã§ã¡ãœãããŸãã¯ããŒã«ã«ããã·ãŒãžã£ã«åçŽã«åå²ããŠããã«å°å¿µããããšã¯å®å
šã«èš±å®¹ãããŸããããã®å Žåã§ã¯ãããŸãã-ã¹ã±ãŒã«ã¯æ·±å»ãªåé¡ããããããŸãïŒ
- ãã£ããããããã³ã«ã®æ§é ããã®è«ç段éãããã³éä¿¡ããŒã¿ãææ§ã«ããããšã¯ãå°æ¥ã®æ¹åã倧ããè€éã«ããŸãã
- ç¹å®ã®ãããã¯ãŒã¯ã©ã€ãã©ãªïŒIndyïŒãžã®ãªã³ã¯ïŒå€æŽããã£ãå Žåãã³ãŒãããªã¥ãŒã å
šäœã綿å¯ã«ããŸãªã確èªããããã«ããšã©ãŒã䌎ãæ·±å»ãªäœæ¥ãå¿
èŠã«ãªããŸãã
- ããŒã¿ãœãŒã¹ïŒ DB ïŒã ãã§ãªããããããžã®ã¢ã¯ã»ã¹ã®ã³ã³ããŒãã³ãïŒ FireDAC ïŒãžã®åæ§ã®ãã€ã³ãã£ã³ã°-ããã«ã¯åãåé¡ã䌎ããŸãã
ããã«ãã¬ãŒã·ã§ã³ã¯ããããã®æ¬ ç¹ã«å¯ŸåŠããæ¹æ³ãææ¡ããŸãã
æåã®ã¢ãããŒã
ãããã³ã«
ããªã¥ãŒã ãšããã«èµ·å ããè€éãã«å¯ŸåŠããã®ã«åœ¹ç«ã€äž»ãªã¢ã€ãã¢ã¯æ°ãããã®ã§ã¯ãããŸãã-ã察象é åããåæ ããæœè±¡åã®å°å
¥ã§ãããã®å Žåãããã¯ãããã¯ãŒã¯çžäºäœçšã§ããããã
ãããã³ã«ãªã©ã®æåã®ããã°ã©ã ã®äžè¬åãå°å
¥ãããŸãã ã
Net.Protocol
ããã®å®è£
ã¯ã¯ã©ã¹ã«åºã¥ããŠãããã¯ã©ã¹ã¯é çªã«ã¢ãžã¥ãŒã«ã«ãã£ãŠã°ã«ãŒãåãããæåã®
Net.Protocol
ã«ãªã
Net.Protocol
ïŒå¿
èŠã«å¿ããŠãŒãããè¿œå ãããŸãïŒã
ãããã³ã«ãšããçšèªã¯ãã§ã«äœ¿çšãããŠãããããæ··ä¹±ãé¿ããããã«ã
äžèšã®è¡šã¯
ãããã³ã«èšè¿°ãšåŒã°ã
ãŸã ã ãŸãããã¹ãŠã®ã¢ãžã¥ãŒã«ãã¯ã©ã€ã¢ã³ããšãµãŒããŒã«åå²ãããŠããããã§ã¯ãªãããšã«æ³šæããŠãã ãã-ãããã¯äº€æåŽã«å
±éã§ãã
ãããã³ã«ã¯æåãããªãåçŽãªã³ãŒãã§èšè¿°ãããŠããŸãã
unit Net.Protocol; interface uses IdIOHandler; type TNetTransport = TIdIOHandler; TNetProtocol = class abstract protected FTransport: TNetTransport; public constructor Create(const Transport: TNetTransport); procedure RunExchange; virtual; abstract; end; implementation constructor TNetProtocol.Create(const Transport: TNetTransport); begin FTransport := Transport; end; end.
äž»èŠãª
RunExchange
ã¡ãœãã
RunExchange
ããããã¯ãŒã¯äº€æãã€ãŸããããã³ã«èšè¿°ã«ååšãããã¹ãŠã®ã¹ããããéå§ããããã«èšèšãããŠããŸãã ã³ã³ã¹ãã©ã¯ã¿ã¯ããã©ã¡ãŒã¿ãšããŠãç©ççãªé
ä¿¡èªäœãæ
åœãããªããžã§ã¯ããåãå
¥ããŸããããã¯ãåè¿°ã®ããã«ãIndyã³ã³ããŒãã³ãã«ãã£ãŠè¡šãããTCPã§ãããŸãã«ãã©ã³ã¹ããŒãã§ãã
ã³ãŒãã®æåã®ããŒãžã§ã³ãæžãçŽããšãéåžžã«ã³ã³ãã¯ãã«ãªããŸãïŒ
TClientProtocol
ã¯
TClientProtocol
ã®åŸç¶
TNetProtocol
ïŒã
procedure TForm1.ButtonSyncClick(Sender: TObject); var Protocol: TClientProtocol; begin TCPClient.Connect; Protocol := TClientProtocol.Create(TCPClient.IOHandler); try Protocol.RunExchange; finally Protocol.Free; end; TCPClient.Disconnect; end;
ãã¡ããããã®ãããªä¿®æ£ã¯ãç¹å®ãããåé¡ã®ãããããŸã 解決ããŠããŸãã-ããã¯ä»ã®æ段ã«ãã£ãŠéæãããŸãã
ããã±ãŒãž
ãããã³ã«ã®å®è£
ã§ãã§ã«äœ¿çšãããŠãã2çªç®ã®æœè±¡åã¯ãããŒã¿
ãã±ãã ïŒä»¥äžãåã«ãã±ããïŒã§ã-ãããã¯ãŒã¯ãæäœãã責任ããããŸãã 説æã®åŒçšããããã©ã°ã¡ã³ããèŠããšã2ã€ã®ãã±ãããããã«å¯Ÿå¿ããŠããŸãïŒåŒ·èª¿è¡šç€ºãæåã®ãã±ããã¯ã¯ã©ã€ã¢ã³ãã«ãã£ãŠéä¿¡ããã2çªç®ã®ãã±ããã¯ãµãŒããŒã«ãã£ãŠéä¿¡ãããŸãïŒã
... | | |
3.å€æŽã®äº€æ | | |
å€æŽã®äº€æãå¿
èŠãªãªã¹ãã®è»¢éã éå±€ã®æåã®ã¬ãã«ã | - ãªã¹ãID
- ãªã¹ãããã·ã¥
- 圌ã®åå«ã®ããã·ã¥ïŒ
| |
| | ããã·ã¥åæïŒ |
| ããã·ã¥äžèŽéç¥ã | 1.ãã¹ãŠã®äžèŽ- åæã®çµäº ã |
åæã®çµäºã | | |
... | | |
ããã±ãŒãžã³ãŒããã·ã³ãã«ã§ãæ°ãã
Net.Packet
ã¢ãžã¥ãŒã«ã«å²ãåœãŠãããŸãã
unit Net.Packet; interface uses Net.Protocol; type TPacket = class abstract public type TPacketKind = UInt16; protected FTransport: TNetTransport; function Kind: TPacketKind; virtual; abstract; public constructor Create(const Transport: TNetTransport); procedure Send; procedure Receive; end; implementation constructor TPacket.Create(const Transport: TNetTransport); begin FTransport := Transport; end; procedure TPacket.Send; begin FTransport.Write(Kind); end; procedure TPacket.Receive; var ActualKind: TPacketKind; begin ActualKind := FTransport.ReadUInt16; if Kind <> ActualKind then
ããã±ãŒãžã«ã¯äž»ã«2ã€ã®ã¡ãœããããããŸãã
Send
-éä¿¡è
ã䜿çšããæ¹æ³ãšã
Receive
-
Receive
è
ãåŒã³åºãæ¹æ³ã§ãã ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ããããã³ã«ãããã©ã³ã¹ããŒããåãåããŸãã
Kind
ã¡ãœããã¯ãç¹å®ã®ããã±ãŒãžïŒåå«ïŒãèå¥ããããã«èšèšãããŠãããæåŸ
ãããçµæãæ£ç¢ºã«åŸãããããšã確èªã§ããŸãã
æœè±¡ããã±ãŒãžã®æŠèŠã説æããåŸãäžèšã®
ãããã³ã«ã®èª¬æã§çŽæ¥äœ¿çšãããæçšãªããŒã¿ãå«ãããã€ãã®ã¢ãžã¥ãŒã«ãå®çŸ©ããŸããæ°ããã¢ãžã¥ãŒã«ã宣èšããŸãã
unit Sync.Packets; interface uses System.Generics.Collections, Net.Packet; type TListHashesPacket = class(TPacket) private const PacketKind = 1; public type THashes = class strict private FHash: string; FItemsHash: string; FUsersHash: string; public property Hash: string read FHash write FHash; property UsersHash: string read FUsersHash write FUsersHash; property ItemsHash: string read FItemsHash write FItemsHash; end; TListHashes = TObjectDictionary<Integer, THashes>;
ã芧ã®ãšãããããã2ã€ã®ãã±ããããã®ç¥å
ã§ãã
TPacket
ããããããã£ïŒãã®å Žåã¯
HashesMatched
ãš
HashesMatched
ïŒã«æ ŒçŽãããããŒã¿ãéåä¿¡ããã³ãŒãã¯å«ãŸããŠããŸãããããããè¿ãå°æ¥ã®åé¡ã§ããããšã確èªããæ¹æ³ã瀺ããŠããŸãããä»ã®ãšãããå¥è·¡çãªæ¹æ³ã§ãã¹ãŠãæ©èœããããšã
ãããã³ã«å®è£
ãããã³ã«ããã±ãããã©ã®ããã«äœ¿çšãããã瀺ãããã«ãããã«2ã€ã®ã¢ãžã¥ãŒã«ãå°å
¥ããå¿
èŠããããŸã-ä»åã¯ã¯ã©ã€ã¢ã³ããšãµãŒããŒã«åå²ããŸãã以åã®ã¢ãžã¥ãŒã«ãšã¯ç°ãªãããããã¯
Sync.Protocol.Client
ãš
Sync.Protocol.Server
ã§ãã
ãã®ååãããã©ã¡ãã®åŽãè¡šããŠããããæããã§ãã
unit Sync.Protocol.Client; interface uses Net.Protocol; type TClientProtocol = class(TNetProtocol) private procedure SendListHashes; function ListHashesMatched: Boolean; ... public procedure RunExchange; override; end; implementation uses Sync.Packets; procedure TClientProtocol.RunExchange; begin inherited; ...
ãããŠããã¢ã®ã¢ãžã¥ãŒã«ïŒ
unit Sync.Protocol.Server; interface uses Net.Protocol; type TServerProtocol = class(TNetProtocol) private function ListHashesMatched: Boolean; ... public procedure RunExchange; override; end; implementation uses Sync.Packets; procedure TServerProtocol.RunExchange; begin inherited; ...
æçµãªãã·ã§ã³
åã®ã»ã¯ã·ã§ã³ã§ã¯ã段éãèšå®ããã ãã§ãæåã«ç¹å®ãããåé¡ã解決ããããã®ãã¬ãŒã ã¯ãŒã¯ãäœæããŸãã-ããŒã¿ãžã®ã¢ã¯ã»ã¹ããéå§ã§ããããã«ãªããŸããã
ããŒã¿
ã¡ããã©ä»ãäž¡åœäºè
ã®ãããã³ã«ãå®è£
ãããšãã«ã次ã®ã³ãŒããçºçããŸããã
åæ§ã«
äžèšã®ã³ã¡ã³ããå®éã®ã³ãŒãã«çœ®ãæããã«ã¯ããã®ãããªãã¶ã€ã³ãã¿ãŒã³ã
ãã¡ãµãŒããšããŠé©çšããããšããå§ãããŸããããŒã¿ãçŽæ¥æäœããã®ã§ã¯ãªãããããã³ã«ã¯ãããŒã¿ããŒã¹ãšéä¿¡ããããã®ä»»æã®è€éã§èšå€§ãªã¢ã¯ã·ã§ã³ãå®è£
ããé«ã¬ãã«ã®ã¡ãœãããåŒã³åºãã¿ã¹ã¯ã«ãªããŸãã ãããè¡ãã«ã¯ã
Sync.DB
ã¢ãžã¥ãŒã«ãäœæããŸãã
unit Sync.DB; interface uses FireDAC.Comp.Client; type TDBFacade = class abstract protected FConnection: TFDConnection; public constructor Create; destructor Destroy; override; procedure StartTransaction; procedure CommitTransaction; procedure RollbackTransaction; end; implementation constructor TDBFacade.Create; begin FConnection := TFDConnection.Create(nil); end; destructor TDBFacade.Destroy; begin FConnection.Free; inherited; end; procedure TDBFacade.StartTransaction; begin FConnection.StartTransaction; end; procedure TDBFacade.CommitTransaction; begin FConnection.Commit; end; procedure TDBFacade.RollbackTransaction; begin FConnection.Rollback; end; end.
ããã§å®£èšãããŠããå¯äžã®
TDBFacade
ã¯ã©ã¹ã«ã¯ããã®ãã¹ãŠã®åå«ããã©ã³ã¶ã¯ã·ã§ã³ïŒç°¡åãªã³ãŒãïŒã§åäœããããã«å¿
èŠãª3ã€ã®ã¡ãœãããå«ãŸããŠããŸãã ïŒ
ã¯ã©ã€ã¢ã³ããã¡ãµãŒãïŒ
unit Sync.DB.Client; interface uses Sync.DB, Sync.Packets; type TClientDBFacade = class(TDBFacade) public procedure CalcListHashes(const Hashes: TListHashesPacket.TListHashes); ... end; implementation uses FireDAC.Comp.Client; procedure TClientDBFacade.CalcListHashes(const Hashes: TListHashesPacket.TListHashes); var StoredProcHashes: TFDStoredProc; begin StoredProcHashes := TFDStoredProc.Create(nil); try
ãµãŒããŒåŽïŒ
unit Sync.DB.Server; interface uses Sync.DB, Sync.Packets; type TServerDBFacade = class(TDBFacade) public function CompareListHashes(const ClientHashes: TListHashesPacket.TListHashes): Boolean; ... end; implementation uses FireDAC.Comp.Client; function TServerDBFacade.CompareListHashes(const ClientHashes: TListHashesPacket.TListHashes): Boolean; var StoredProcHashes: TFDStoredProc; begin Result := True; StoredProcHashes := TFDStoredProc.Create(nil); try
ã¯ã©ã€ã¢ã³ããã¡ãµãŒããäŸãšããŠäœ¿çšããŠããèªè
ãã
CalcListHashes
ã¡ãœãã
CalcListHashes
éåžžã«åçŽã§ãããŒã¿ããŒã¹ã«é¢ãããã¹ãŠã®äœæ¥ããã®äžã«åãå
¥ããæå³ãã»ãšãã©ãªããšæãããå Žåã¯ãããã§ç€ºãã匷åãªåçŽåãæ¯èŒããããšããå§ãããŸã
ã¢ããªã±ãŒã·ã§ã³ããã®å®éã®ã³ãŒãã procedure TClientSyncDBFacade.CalcListHashes(const Hashes: TListHashesPacket.THashesCollection); var Lists: TList<TLocalListID>; procedure PrepareListsToHashing; begin PrepareStoredProcedureToWork(SyncPrepareListsToHashingProcedure); FStoredProcedure.Open; while not FStoredProcedure.Eof do begin Lists.Add( FStoredProcedure['LIST_ID'] ); FStoredProcedure.Next; end; end; procedure CalcTotalChildHashes; var ListID: TLocalListID; TotalUsersHash, TotalItemsHash: TMD5Hash; begin for ListID in Lists do begin PrepareStoredProcedureToWork(SyncSelectListUsersForHashingProcedure); FStoredProcedure.ParamByName('LIST_ID').Value := ListID; TotalUsersHash := CalcTotalHashAsBytes( FStoredProcedure, ['USER_AS_STRING'] ); PrepareStoredProcedureToWork(SyncSelectListItemAndItemMessagesHashProcedure); FStoredProcedure.ParamByName('LIST_ID').Value := ListID; TotalItemsHash := CalcTotalHashAsBytes( FStoredProcedure, ['ITEM_HASH', 'ITEM_MESSAGES_HASH'] ); PrepareStoredProcedureToWork(SyncAddTotalListHashesProcedure); FStoredProcedure.ParamByName('LIST_ID').Value := ListID; FStoredProcedure.ParamByName('TOTAL_USERS_HASH').AsHash := TotalUsersHash; FStoredProcedure.ParamByName('TOTAL_ITEMS_HASH').AsHash := TotalItemsHash; FStoredProcedure.ExecProc; end; end; procedure FillHashes; var ListHashes: TListHashesPacket.THashes; begin PrepareStoredProcedureToWork(SyncSelectListHashesProcedure); FStoredProcedure.Open; while not FStoredProcedure.Eof do begin ListHashes := TListHashesPacket.THashes.Create; try ListHashes.Hash := HashToString( FStoredProcedure.FieldByName('LIST_HASH').AsHash ); ListHashes.UsersHash := HashToString( FStoredProcedure.FieldByName('LIST_USERS_HASH').AsHash ); ListHashes.ItemsHash := HashToString( FStoredProcedure.FieldByName('LIST_ITEMS_HASH').AsHash ); except ListHashes.DisposeOf; raise; end; Hashes.Add( FStoredProcedure.FieldByName('LIST_GLOBAL_ID').AsUUID, ListHashes ); FStoredProcedure.Next; end; end; begin Lists := TList<TLocalListID>.Create; try PrepareListsToHashing; CalcRecordHashes(TListHashes); CalcRecordHashes(TListItemHashes); CalcRecordHashes(TListItemMessagesHashes); CalcTotalChildHashes; FillHashes; finally Lists.DisposeOf; end; end;
äž¡æ¹ã®ãã¡ãµãŒãã
Sync.Packets
ã¢ãžã¥ãŒã«ãã€ã³ããŒããããã®äžã§å®£èšãããããã±ãŒãžã䜿çšããŸã-ããã«ããããããã®éã«åŒ·åãª
æ¥çãäœæãããŸããããã¯ããã¡ãµãŒããšããã±ãŒãžããããã³ã«ã§äœ¿çšããããã«èšèšãããŠããããäºããç¥ã£ãŠããããã§ã圌ãã«ã¯å¥ã®çç±ã¯ãããŸããã ã¢ããªã±ãŒã·ã§ã³ã倧ãããå€ãã®éçºè
ãäœæ¥ããå Žåããã¡ãµãŒãã¡ãœããã®ããã±ãŒãžåºæã®ã¿ã€ããä»ã®ããäžè¬çãªã¿ã€ããããšãã°ããªã¹ãã®æœè±¡çãªãªã¹ããã«çœ®ãæããããšã§ãçµåãæžããå¿
èŠããããŸããããã¹ãŠã®è€éããå¢ãããã«ãããæ¯æãå¿
èŠããããŸãã çŸåšã®åŠ¥åæ¡ã¯ããããžã§ã¯ãã®å°èŠæš¡ãèæ
®ã«å
¥ããŠãªã¹ã¯ãéåžžã«é©åã«åæ£ããŠããŸãã
æçµãããã³ã«ãã¥ãŒ
ãã¡ãµãŒãã®å°å
¥åŸããã¹ãŠã®ãããã³ã«ã¡ãœããã¯æçµçãªå®å®ãã圢åŒã«ãªããŸãã
unit Sync.Protocol.Client; interface uses Net.Protocol, Sync.DB.Client; type TClientProtocol = class(TNetProtocol) private FDBFacade: TClientDBFacade; procedure SendListHashes; ... public procedure RunExchange; override; end; implementation uses Sync.Packets; procedure TClientProtocol.RunExchange; begin inherited; FDBFacade.StartTransaction; try ...
unit Sync.Protocol.Server; interface uses Net.Protocol, Sync.DB.Server; type TServerProtocol = class(TNetProtocol) private FDBFacade: TServerDBFacade; function ListHashesMatched: Boolean; ... public procedure RunExchange; override; end; implementation uses Sync.Packets; procedure TServerProtocol.RunExchange; begin inherited; FDBFacade.StartTransaction; try ...
ããã±ãŒãžæ¹èš
çµã¿ç«ãŠãããæ§é å
šäœãå®æãããããã«ãæåŸã®ããããéåžžã«éèŠãªçªãåãããŸã-æçšãªæ
å ±ãéä¿¡ããããããã±ãŒãžã«æããããšã§ããããã®ã¿ã¹ã¯ã¯2ã€ã®ã³ã³ããŒãã³ãã«äŸ¿å©ã«åå²ãããŸãïŒäŸãã°ãéä¿¡ïŒïŒ
- ãŸãããããã¯ãŒã¯ãä»ããäŒéã«é©ãã圢åŒã§ããŒã¿ãããã¯ ïŒ ã·ãªã¢ã«å ïŒããå¿
èŠããããŸãã
- ããã±ãŒãžåããããã®ãç©ççã«éä¿¡ããå¿
èŠããããŸãã
ããã±ãŒãžåã¯ããŸããŸãªæ¹æ³ã§å®è¡ã§ããŸãããã€ããªåœ¢åŒãXMLãJSONãªã©ãã¢ãã€ã«ããã€ã¹ã«ã¯è±å¯ãªãªãœãŒã¹ããªããããæåŸã®JSONãªãã·ã§ã³ãéžæãããŸããã ïŒ; éžæãããã¹ãå®è£
ããã«ã¯ã
TPacket
2ã€ã®ã¡ãœãããè¿œå ã
TPacket
ã
unit Net.Packet; interface uses Net.Protocol, System.JSON; type TPacket = class abstract ... private function PackToJSON: TJSONObject; procedure UnpackFromJSON(const JSON: TJSONObject); ... end;
ã¡ãœããã¯2ã€ã®æ¹æ³ãå¯èœã§ãããããå®è£
ã¯ç€ºãããŠããŸããïŒã¡ãœããã¯ä¿è·ããã³ä»®æ³ãšããŠå®£èšããããã¹ãŠã®çžç¶äººããã±ãŒãžã¯ãè¿œå ãããããŒã¿ããããã£ã«å¿ããŠåå¥ã«JSONã®ããã±ãŒãžåããã³å±éããŸãã¯2çªç®ã®ãªãã·ã§ã³-ã¡ãœããã¯ãã©ã€ããŒãã®ãŸãŸã§ãããã«ïŒJSONãžã®èªåå€æçšã®ã³ãŒããå«ãŸããŠããŸããããã«ããããããžã¹ãã£ãã¯ããªå¿é
ããåå«ãå®å
šã«æé€ãããŸãã æåã®ãªãã·ã§ã³ã¯ãããã±ãŒãžã®æ°ãšãã®è€éããå°ããå ŽåïŒæãåçŽãªã¿ã€ãã®ããããã£ã§æ°ååãŸã§ïŒã«æå¹ã§ãããæ³æ¡ãããé«ãå€ã«ãªãå Žå-äœè
ã®ãããžã§ã¯ãã«ã¯32åãããããšãã°ãéåžžã«è€éã§ã
ãã®ãããªããã±ãŒãž TListPacket = class(TStreamPacket) public type TPhoto = class(TPackableObject) strict private FSortOrder: Int16; FItemMessageID: TItemMessageID; public property ItemMessageID: TItemMessageID read FItemMessageID write FItemMessageID; property SortOrder: Int16 read FSortOrder write FSortOrder; end; TPhotos = TStandardPacket.TPackableObjectDictionary<TMessagePhotoID, TPhoto>; TMessage = class(TPackableObject) strict private FAuthor: TUserID; FAddDate: TDateTime; FText: string; FListItemID: TListItemID; public property ListItemID: TListItemID read FListItemID write FListItemID; property Author: TUserID read FAuthor write FAuthor; property AddDate: TDateTime read FAddDate write FAddDate; property Text: string read FText write FText; end; TMessages = TStandardPacket.TPackableObjectDictionary<TItemMessageID, TMessage>; TListDescendant = class(TPackableObject) strict private FListID: TListID; public property ListID: TListID read FListID write FListID; end; TItem = class(TListDescendant) strict private FAddDate: TDateTime; FAmount: TAmount; FEstimatedPrice: Currency; FExactPrice: Currency; FStandardGoods: TID; FInTrash: Boolean; FUnitOfMeasurement: TID; FStrikeoutDate: TDateTime; FCustomGoods: TGoodsID; public property StandardGoods: TID read FStandardGoods write FStandardGoods; property CustomGoods: TGoodsID read FCustomGoods write FCustomGoods; property Amount: TAmount read FAmount write FAmount; property UnitOfMeasurement: TID read FUnitOfMeasurement write FUnitOfMeasurement; property EstimatedPrice: Currency read FEstimatedPrice write FEstimatedPrice; property ExactPrice: Currency read FExactPrice write FExactPrice; property AddDate: TDateTime read FAddDate write FAddDate; property StrikeoutDate: TDateTime read FStrikeoutDate write FStrikeoutDate; property InTrash: Boolean read FInTrash write FInTrash; end; TItems = TStandardPacket.TPackableObjectDictionary<TListItemID, TItem>; TUser = class(TListDescendant) strict private FUserID: TUserID; public property UserID: TUserID read FUserID write FUserID; end; TUsers = TStandardPacket.TPackableObjectList<TUser>; TList = class(TPackableObject) strict private FName: string; FAuthor: TUserID; FAddDate: TDateTime; FDeadline: TDate; FInTrash: Boolean; public property Author: TUserID read FAuthor write FAuthor; property Name: string read FName write FName; property AddDate: TDateTime read FAddDate write FAddDate; property Deadline: TDate read FDeadline write FDeadline; property InTrash: Boolean read FInTrash write FInTrash; end; TLists = TStandardPacket.TPackableObjectDictionary<TListID, TList>; private FLists: TLists; FMessages: TMessages; FItems: TItems; FUsers: TUsers; FPhotos: TPhotos; public property Lists: TLists read FLists write FLists; property Users: TUsers read FUsers write FUsers; property Items: TItems read FItems write FItems; property Messages: TMessages read FMessages write FMessages; property Photos: TPhotos read FPhotos write SetPhotos; end;
ããã±ãŒãžã³ã°ããã»ã¹ã®èªååãªãã§ã¯ããã§ã«éåžžã«ç¡è¬ã§ãã ç¹ã«ã
RTTIã䜿çšãããšãããã±ãŒãžã®å¿
èŠãªããããã£ãéžæããŠå€ãæäœã§ããŸããããã®ãããã¯ã¯èšäºã®ç¯å²å€ã§ãããããã³ãŒãã¯è¡šç€ºãããŸããã
以åã«å®£èšãããããã±ãŒãžã®å¯èœãªJSONè¡šçŸãæäŸTListHashesPacket
ããŠãèªè
ãæçµçã«å
ã®ã¯ã©ã¹ãšãã®ã·ãªã¢ã«åããã圢åŒãšã®å¯Ÿå¿ãç解ããã®ãå©ãããšåœ¹ç«ã€ããã§ãïŒ { 16: { Hash: "d0860029f1400147deef86d3246d29a4", UsersHash: "77febf816dac209a22880c313ffae6ad", ItemsHash: "1679091c5a880faf6fb5e6087eb1b2dc" }, 38: { Hash: "81c8061686c10875781a2b37c398c6ab", UsersHash: "d3556bff1785e082b1508bb4e611c012", ItemsHash: "0e3a37aa85a14e359df74fa77eded3f6" } }
ããã±ãŒãžããããã®ã®ç©ççãªèŒžéã¯éåžžã«ç°¡åã§ã-ããã€ãã®åºæ¬çãªæ¹æ³ãè¿œå ããã ãã§ãTPacket
ïŒ unit Net.Packet; interface ... implementation uses System.SysUtils, IdGlobal; ... procedure TPacket.Send; var DataLength: Integer; RawData: TBytes; JSON: TJSONObject; begin FTransport.Write(Kind); JSON := PackToJSON; try SetLength(RawData, JSON.EstimatedByteSize); DataLength := JSON.ToBytes( RawData, Low(RawData) ); FTransport.Write(DataLength); FTransport.Write( TIdBytes(RawData), DataLength ); finally JSON.Free; end; end; procedure TPacket.Receive; var ActualKind: TPacketKind; DataLength: Integer; RawData: TBytes; JSON: TJSONObject; begin ActualKind := FTransport.ReadUInt16; if Kind <> ActualKind then
ãããã«
ææ¡ããããœãªã¥ãŒã·ã§ã³ã¯ãæåã«æèµ·ãããåé¡ã«ã©ã®çšåºŠå¹æçã«å¯ŸåŠããŸããïŒããã§ã¯ã©ã€ã¢ã³ããªã©ã®ãããã³ã«ã³ãŒããèŠããšããã®ã¡ãœããã¯ãããã³ã«èšè¿°ã®çšèªã§åäœããããããããã®éã®å¯Ÿå¿ãéåžžã«æ確ãã€è¿
éã«èŠã€ããããšãã§ããŸãããããã¯ãŒã¯ã©ã€ãã©ãªãšããŒã¿ãžã®äŸåã¯ããŒã«ã©ã€ãºããã3ã€ã®ã¢ãžã¥ãŒã«ã«é
眮ãããŸãïŒè²ã§ããŒã¯ãããŠããŸãïŒããã®ãããIndyããä»ã®äœããžã®ç§»è¡ã«ã¯2ã€ã®ã¡ãœãã y ã®ã¿ãå€æŽããå¿
èŠããããŸãTPacket
- ããŒãã£ã®1ã€ã§FireDAC Send
ãReceive
眮ãæããïŒãŸãã¯ãäžè¬çã«ãªããžããªãšããŠããŒã¿ããŒã¹ãæŸæ£ããïŒã®ã¯ãã¡ãµãŒãã¡ãœããã«ã®ã¿åœ±é¿ãããããã³ã«èªäœã®ç·šéã¯ãŸã£ããå¿
èŠãããŸãããæ®å¿µãªããšã«ãçŸåšã®ãœãªã¥ãŒã·ã§ã³ã¯ããã®å©ç¹ããã¹ãŠåããŠããŠããå®éã®äœ¿çšã§ã¯ä»ã®éèŠãªãã¥ã¢ã³ã¹ãèæ
®ããå¿
èŠããããããå®éã®äœ¿çšã«ã¯ãŸã å®å
šã«ã¯é©ããŠããŸããããããã¯ãŒã¯ãµãã·ã¹ãã ã«ã¯ã»ãšãã©é©çšãããŸãããããã¯ããããã³ã«ã«éããããã¯ã©ã€ã¢ã³ãã衚瀺ãããããšãæå³ããŸãïŒãã¹ãŠã®ãŠãŒã¶ãŒãå®æçãã€åãã§ã¢ããªã±ãŒã·ã§ã³ãæŽæ°ããããã§ã¯ãããŸããïŒããµãŒããŒã®å¿çã¯2ã€ãããŸããå€ããããã³ã«ã§ã¯ã©ã€ã¢ã³ãã«ãµãŒãã¹ãæäŸããããšãæåŠããããããŸããŸãªããŒãžã§ã³ã§ã®åææäœããµããŒãããŸãããã®è³ªåã«å¯Ÿããçãã¯ãèšäºã®ç¬¬2éšã§æäŸã§ããŸã-åãäžãããããããã¯ã«é¢å¿ãããå ŽåïŒå人ã¡ãã»ãŒãžãŸãã¯ã³ã¡ã³ãã§è¡šçŸããããšãææ¡ãããŠããŸãïŒã