Е, разбирате, че това е нетривиален проблем. Написах библиотека, за да постигна това за комерсиално приложение миналата година и отне около 6 месеца, за да го стигна до мястото, където бях доволен от него.
Като оставим настрана аргумента за използване на порт 80 и HTTP (TCP/IP), за да избегнете проблеми със защитната стена и поддръжката, трябва да проектирате протокол. Тъй като моят проект беше много натоварен с данни, аз използвах двоичен протокол (вместо раздутия xml), който може да обработва всякакви данни. Исках също така да бъде двупосочен, за да мога да ВМЕСКАМ данни, както и да изпълнявам заявки. Използвах CGI/FastCGI на сървъра.
Двоичният протокол, който проектирах, е доста прост (винаги по-добър) и разделя големи трансфери на парчета с размер, определен от потребителя (около 600k изглежда е добре). Всяка част има заглавка, последвана от данните.
Въпреки че този протокол може да се използва за предаване на всякакъв вид данни, обикновено се използва за данни за стил на база данни, както предполага вашият въпрос. За да се справя с това, реших да използвам подход на редове/колони към дизайна. Данните се съхраняват един ред в даден момент, което означава, че всяка от колоните се съхранява за ред първи, след това всички колони за ред 2 ... ред n.
Форматът на данните от една колона е:
' Col1Type 1Bytes - BYTE ' Data Type (REMSQL_TEXT etc)
' Col1Len 4Bytes - DWORD ' Length in bytes the Column Data - up to 4.2GB
' Col1Data nBytes - BYTE ' String data
(в C BYTE е CHAR)
Това означава, че всяка колона има дескриптор за тип данни. Всички типове данни могат да бъдат представени с:
REMSQL_NONE = 0 ' DataType undefined
REMSQL_QUAD = 1 ' 64-bit signed integer
REMSQL_DBLE = 2 ' 64-bit IEEE floating point number
REMSQL_TEXT = 3 ' STRING - (CHAR) string of Ascii Bytes
REMSQL_BLOB = 4 ' BLOB - (CHAR) string of Binary Bytes
REMSQL_NULL = 5 ' NULL - Empty Column
Тези типове данни съвпадат с основни типове данни на SQLite и са числено еквивалентни на изброяването на основни типове данни на SQL3.
В този дизайн, ако полето е празно (NULL), значи сте взели само 5 байта, за да го съхраните. Ако едно поле има 200 байта текст например, са необходими само 205 байта, за да го съхрани. По-голямата полза е в синтактичния анализ на данните, тъй като пропускането на колони може да се направи без четене през всичките 200 байта, за да се намери някакъв завършващ символ.
Заглавката на Chunk трябва да съдържа неща като брой редове, брой колони, общо байтове и т.н. и т.н. Ако използвате DWORD (неподписани 64-битови цели числа), тогава теоретичното ограничение за парче е 4.2gigs, което би трябвало да е достатъчно дори за предаване на локална мрежа.
Реализацията изисква писане на SQLite/MYSQL обвивки за тази функционалност. Използвам изключително протокола BINARY, което отнема малко време, но по същество се нуждаете от следните функции:Клиентска страна:SendRequest() - Изпраща заявка, чака отговор
От страна на сървъра:ProcessRequest() - Получава заявка, обработва я и връща отговор
В моя случай отговорът може да бъде !00MB данни или повече. Извличам целия набор от данни от MySQL и го записвам на диск на сървъра. След това връщам празна част, която съдържа метриките на набора от данни. След това клиентът изисква набора от данни на парчета от 600k, един по един. Ако връзката се загуби, тя просто продължава откъдето е спряла.
И накрая, наборът от данни беше предимно текст (имена, адреси и т.н.), така че е узрял за компресиране. Сигурността беше много голям проблем в този случай, така че криптирането беше от съществено значение. Това става малко по-сложно за изпълнение, но основно компресирате цялата част, подложка до дължина, която е кратна на блоковите шифри BLOCKSIZE и го криптирате.
В процеса на всичко това пиша много бърз клас за създаване на низове, реализация на AES криптиране в ASM и цяла библиотека FastCGI (www.coastrd.com)
Така че, както казах, нетривиално. Скоро ще направя тази библиотека достъпна. Ако искате да го проверите, изпратете ми имейл.
След като сте написали комуникацията, можете да започнете да проектирате синхронизацията. Бих използвал или хеш за всеки запис, или обикновен булев флаг. Ако нещо се промени на сървъра, просто изпратете целия запис и го презапишете от страна на клиента (ако приемем, че се опитвате да поддържате клиентите синхронизирани...)
Ако пишете своя собствена, моля, публикувайте отново тук за вашия опит!
PS Помислете за промяна на заглавието, за да бъде по-удобно за търсене. Може би нещо като:
„Синхронизиране на клиентска база данни на SQLite с база данни на MySQL сървър“