ការរិះគន់លើពិធីសារ និងវិធីសាស្រ្តរៀបចំរបស់ Telegram ។ ផ្នែកទី 1 បច្ចេកទេស៖ បទពិសោធន៍នៃការសរសេរអតិថិជនពីដំបូង - TL, MT

ថ្មីៗនេះ ការបង្ហោះអំពី Telegram ល្អប៉ុណ្ណា ភាពអស្ចារ្យ និងបទពិសោធន៍របស់បងប្អូន Durov ក្នុងការកសាងប្រព័ន្ធបណ្តាញជាដើម បានចាប់ផ្តើមលេចឡើងជាញឹកញាប់នៅលើ Habre ។ ក្នុងពេលជាមួយគ្នានេះ មានមនុស្សតិចតួចណាស់ដែលបានដាក់ខ្លួននៅក្នុងឧបករណ៍បច្ចេកទេស - ភាគច្រើនពួកគេប្រើសាមញ្ញដោយស្មើភាព (និងខុសពី MTProto) Bot API ដោយផ្អែកលើ JSON ហើយជាធម្មតាគ្រាន់តែទទួលយក នៅលើជំនឿ ការសរសើរ និង PR ទាំងអស់ដែលវិលជុំវិញអ្នកនាំសារ។ ជិតមួយឆ្នាំកន្លះមុន សហសេវិករបស់ខ្ញុំនៅអង្គការ Eshelon NGO Vasily (ជាអកុសល គណនីរបស់គាត់នៅលើ Habré ត្រូវបានលុបជាមួយនឹងសេចក្តីព្រាង) បានចាប់ផ្តើមសរសេរកម្មវិធី Telegram ផ្ទាល់ខ្លួនរបស់គាត់តាំងពីដំបូងនៅ Perl ហើយក្រោយមកអ្នកនិពន្ធនៃបន្ទាត់ទាំងនេះបានចូលរួម។ ហេតុអ្វីបានជា Perl អ្នកខ្លះនឹងសួរភ្លាមៗ? ដោយសារតែគម្រោងបែបនេះមានរួចហើយជាភាសាផ្សេង តាមពិតនេះមិនមែនជាចំណុចទេ វាអាចមានភាសាផ្សេងទៀតដែលមិនមាន បណ្ណាល័យដែលត្រៀមរួចជាស្រេចហើយតាមនោះអ្នកនិពន្ធត្រូវតែទៅគ្រប់វិធី ពីទទេ. លើសពីនេះទៅទៀត ការគ្រីបគ្រីបគឺជាបញ្ហានៃការជឿទុកចិត្ត ប៉ុន្តែសូមផ្ទៀងផ្ទាត់។ ជាមួយនឹងផលិតផលដែលផ្តោតលើសុវត្ថិភាព អ្នកមិនអាចគ្រាន់តែពឹងផ្អែកលើបណ្ណាល័យដែលត្រៀមរួចជាស្រេចពីក្រុមហ៊ុនផលិតនោះទេ ហើយជឿជាក់លើវាដោយខ្វាក់ភ្នែក (ទោះជាយ៉ាងណាក៏ដោយ នេះគឺជាប្រធានបទសម្រាប់ផ្នែកទីពីរ)។ នៅពេលនេះ បណ្ណាល័យដំណើរការបានល្អនៅកម្រិត "មធ្យម" (អនុញ្ញាតឱ្យអ្នកធ្វើសំណើ API ណាមួយ)។

ទោះយ៉ាងណាក៏ដោយ វានឹងមិនមានការគ្រីប ឬគណិតវិទ្យាច្រើននៅក្នុងស៊េរីនៃការបង្ហោះនេះទេ។ ប៉ុន្តែវានឹងមានព័ត៌មានលម្អិតបច្ចេកទេសជាច្រើនទៀត និងឈើច្រត់ស្ថាបត្យកម្ម (ក៏មានប្រយោជន៍សម្រាប់អ្នកដែលនឹងមិនសរសេរពីដំបូងឡើយ ប៉ុន្តែនឹងប្រើបណ្ណាល័យជាភាសាណាមួយ)។ ដូច្នេះ គោលដៅសំខាន់គឺព្យាយាមអនុវត្តអតិថិជនតាំងពីដំបូង នេះបើយោងតាមឯកសារផ្លូវការ. នោះគឺ ចូរសន្មតថាកូដប្រភពនៃអតិថិជនផ្លូវការត្រូវបានបិទ (ម្តងទៀតនៅក្នុងផ្នែកទីពីរ យើងនឹងរៀបរាប់លម្អិតបន្ថែមទៀតអំពីប្រធានបទនៃការពិតដែលថានេះជាការពិត។ វា​កើតឡើង ដូច្នេះ) ប៉ុន្តែដូចកាលពីសម័យមុន ជាឧទាហរណ៍ មានស្តង់ដារដូចជា RFC - តើវាអាចទៅរួចទេក្នុងការសរសេរអតិថិជនយោងទៅតាមការបញ្ជាក់តែម្នាក់ឯង “ដោយមិនមើល” កូដប្រភព ថាតើវាជាផ្លូវការ (Telegram Desktop, mobile) ឬ Telethon មិនផ្លូវការ?

តារាង​មាតិកា:

ឯកសារ... វាមានហើយមែនទេ? តើពិតទេ?..

បំណែកនៃចំណាំសម្រាប់អត្ថបទនេះបានចាប់ផ្តើមត្រូវបានប្រមូលកាលពីរដូវក្តៅមុន។ គ្រប់ពេលវេលានេះនៅលើគេហទំព័រផ្លូវការ https://core.telegram.org ឯកសារគឺនៅស្រទាប់ 23, i.e. ជាប់គាំងនៅកន្លែងណាមួយក្នុងឆ្នាំ 2014 (ចាំថាមិនមានប៉ុស្តិ៍ពីមុនទេ?) ជាការពិតណាស់ តាមទ្រឹស្តី នេះគួរតែអនុញ្ញាតឱ្យយើងអនុវត្តអតិថិជនដែលមានមុខងារនៅពេលនោះក្នុងឆ្នាំ 2014។ ប៉ុន្តែសូម្បីតែនៅក្នុងរដ្ឋនេះក៏ដោយ ឯកសារទីមួយមិនពេញលេញ និងទីពីរ នៅកន្លែងដែលវាផ្ទុយពីខ្លួនវា។ កាលពីជាងមួយខែមុន គឺក្នុងខែកញ្ញា ឆ្នាំ 2019 ដោយចៃដន្យ វាត្រូវបានគេរកឃើញថាមានការអាប់ដេតដ៏ធំនៃឯកសារនៅលើគេហទំព័រសម្រាប់ Layer 105 ថ្មីៗនេះ ជាមួយនឹងចំណាំថាឥឡូវនេះអ្វីៗទាំងអស់ត្រូវអានម្តងទៀត។ ជាការពិត អត្ថបទជាច្រើនត្រូវបានកែប្រែ ប៉ុន្តែជាច្រើននៅតែមិនផ្លាស់ប្តូរ។ ដូច្នេះហើយ នៅពេលអានការរិះគន់ខាងក្រោមអំពីឯកសារ អ្នកគួរតែចាំថា ចំណុចទាំងនេះខ្លះលែងពាក់ព័ន្ធទៀតហើយ ប៉ុន្តែខ្លះទៀតនៅមាននៅឡើយ។ យ៉ាងណាមិញ 5 ឆ្នាំនៅក្នុងពិភពសម័យទំនើបមិនមែនគ្រាន់តែជារយៈពេលដ៏យូរប៉ុណ្ណោះទេ យ៉ាងខ្លាំង ជាច្រើន ចាប់តាំងពីពេលនោះមក (ជាពិសេសប្រសិនបើអ្នកមិនគិតពីគេហទំព័រ geochat ដែលបានបោះចោល និងរស់ឡើងវិញចាប់តាំងពីពេលនោះមក) ចំនួនវិធីសាស្រ្ត API នៅក្នុងគ្រោងការណ៍បានកើនឡើងពីមួយរយទៅជាងពីររយហាសិប!

កន្លែងដែលត្រូវចាប់ផ្តើមជាអ្នកនិពន្ធវ័យក្មេង?

វាមិនមានបញ្ហាថាតើអ្នកសរសេរពីដំបូងឬប្រើទេ ឧទាហរណ៍ បណ្ណាល័យដែលត្រៀមរួចជាស្រេចដូចជា Telethon សម្រាប់ PythonMadeline សម្រាប់ PHPក្នុងករណីណាក៏ដោយអ្នកនឹងត្រូវការជាមុនសិន ចុះឈ្មោះកម្មវិធីរបស់អ្នក។ - ទទួលបានប៉ារ៉ាម៉ែត្រ api_id и api_hash (អ្នកដែលបានធ្វើការជាមួយ VKontakte API យល់ភ្លាមៗ) ដែលម៉ាស៊ីនមេនឹងកំណត់អត្តសញ្ញាណកម្មវិធី។ នេះ។ ត្រូវតែ ធ្វើវាដោយហេតុផលផ្លូវច្បាប់ ប៉ុន្តែយើងនឹងនិយាយបន្ថែមទៀតអំពីមូលហេតុដែលអ្នកនិពន្ធបណ្ណាល័យមិនអាចបោះពុម្ពវានៅក្នុងផ្នែកទីពីរ។ អ្នកប្រហែលជាពេញចិត្តនឹងតម្លៃតេស្ត ទោះបីជាវាមានកម្រិតខ្លាំងក៏ដោយ - ការពិតគឺថាឥឡូវនេះអ្នកអាចចុះឈ្មោះបាន។ តែមួយគត់ កម្មវិធី ដូច្នេះកុំប្រញាប់ប្រញាល់ចូលទៅក្នុងវា។

ឥឡូវនេះតាមទស្សនៈបច្ចេកទេស យើងគួរតែចាប់អារម្មណ៍លើការពិតដែលថាបន្ទាប់ពីការចុះឈ្មោះយើងគួរតែទទួលបានការជូនដំណឹងពី Telegram អំពីការធ្វើបច្ចុប្បន្នភាពឯកសារ ពិធីការជាដើម។ នោះគឺគេអាចសន្មត់ថាគេហទំព័រដែលមានចតត្រូវបានបោះបង់ចោលយ៉ាងសាមញ្ញ ហើយបន្តធ្វើការជាពិសេសជាមួយអ្នកដែលចាប់ផ្តើមបង្កើតអតិថិជន ដោយសារតែ វាងាយស្រួលជាង។ ប៉ុន្តែ​អត់​មាន​អ្វី​ដូច​ដែល​គេ​សង្កេត​ឃើញ​នោះ​ទេ គ្មាន​ព័ត៌មាន​មក​ទេ។

ហើយប្រសិនបើអ្នកសរសេរពីដំបូង នោះការប្រើប៉ារ៉ាម៉ែត្រដែលទទួលបានគឺពិតជានៅឆ្ងាយណាស់។ ទោះបីជា https://core.telegram.org/ ហើយនិយាយអំពីពួកគេនៅក្នុង Getting Start ជាដំបូងនៃការទាំងអស់ តាមពិតទៅ ដំបូងអ្នកនឹងត្រូវអនុវត្ត ពិធីការ MTProto - ប៉ុន្តែប្រសិនបើអ្នកជឿ ប្លង់យោងទៅតាមគំរូ OSI នៅចុងបញ្ចប់នៃទំព័រសម្រាប់ការពិពណ៌នាទូទៅនៃពិធីការ នោះវាគ្មានប្រយោជន៍ទាំងស្រុង។

ជាការពិតទាំងមុន និងក្រោយ MTProto នៅកម្រិតជាច្រើនក្នុងពេលតែមួយ (ដូចដែលបណ្តាញបរទេសដែលធ្វើការនៅក្នុង OS kernel និយាយថា ការរំលោភលើស្រទាប់) ប្រធានបទដ៏ធំ ឈឺចាប់ និងគួរឱ្យភ័យខ្លាចនឹងកើតឡើង ...

សៀរៀលគោលពីរ៖ TL (ភាសាប្រភេទ) និងគ្រោងការណ៍ និងស្រទាប់របស់វា និងពាក្យគួរឱ្យខ្លាចជាច្រើនទៀត

តាមពិតប្រធានបទនេះគឺជាគន្លឹះនៃបញ្ហារបស់ Telegram ។ ហើយ​នឹង​មាន​ពាក្យ​គួរ​ឱ្យ​ខ្លាច​ជា​ច្រើន​ប្រសិន​បើ​អ្នក​ព្យាយាម​ស្វែង​យល់​វា​។

ដូច្នេះ នេះជាដ្យាក្រាម។ បើពាក្យនេះចូលមកក្នុងចិត្តអ្នក ចូរនិយាយថា គ្រោងការណ៍ JSON, អ្នកគិតត្រឹមត្រូវ។ គោលដៅគឺដូចគ្នា៖ ភាសាមួយចំនួនដើម្បីពិពណ៌នាអំពីសំណុំទិន្នន័យដែលបានបញ្ជូន។ នេះគឺជាកន្លែងដែលភាពស្រដៀងគ្នាបញ្ចប់។ ប្រសិនបើពីទំព័រ ពិធីការ MTProtoឬពីមែកធាងប្រភពនៃអតិថិជនផ្លូវការ យើងនឹងព្យាយាមបើកគ្រោងការណ៍មួយចំនួន យើងនឹងឃើញអ្វីមួយដូចជា៖

int ? = Int;
long ? = Long;
double ? = Double;
string ? = String;

vector#1cb5c415 {t:Type} # [ t ] = Vector t;

rpc_error#2144ca19 error_code:int error_message:string = RpcError;

rpc_answer_unknown#5e2ad36e = RpcDropAnswer;
rpc_answer_dropped_running#cd78e586 = RpcDropAnswer;
rpc_answer_dropped#a43ad8b7 msg_id:long seq_no:int bytes:int = RpcDropAnswer;

msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;

---functions---

set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:bytes = Set_client_DH_params_answer;

ping#7abe77ec ping_id:long = Pong;
ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;

invokeAfterMsg#cb9f372d msg_id:long query:!X = X;
invokeAfterMsgs#3dc4b4f0 msg_ids:Vector<long> query:!X = X;

account.updateProfile#78515775 flags:# first_name:flags.0?string last_name:flags.1?string about:flags.2?string = User;
account.sendChangePhoneCode#8e57deb flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool = auth.SentCode;

មនុស្សម្នាក់ដែលឃើញវាជាលើកដំបូងនឹងវិចារណញាណអាចទទួលស្គាល់តែផ្នែកនៃអ្វីដែលត្រូវបានសរសេរ - ច្បាស់ណាស់ទាំងនេះគឺជារចនាសម្ព័ន្ធ (ទោះបីជាឈ្មោះនៅឯណានៅខាងឆ្វេងឬខាងស្តាំ?) មានវាលនៅក្នុងពួកវា។ បន្ទាប់​មក ប្រភេទ​មួយ​បន្ទាប់​ពី​ពោះវៀនធំ... ប្រហែល។ នៅទីនេះក្នុងតង្កៀបមុំប្រហែលជាមានគំរូដូចជានៅក្នុង C ++ (តាមពិតទៅ មិនពិត) ហើយតើនិមិត្តសញ្ញាផ្សេងទៀតមានន័យយ៉ាងណា សញ្ញាសួរ សញ្ញាឧទានភាគរយ សញ្ញាហស (ហើយជាក់ស្តែងវាមានន័យខុសគ្នានៅកន្លែងផ្សេងៗគ្នា) ជួនកាលមានវត្តមាន និងជួនកាលមិនមែន លេខគោលដប់ប្រាំមួយ ហើយសំខាន់បំផុត របៀបទទួលបានពីនេះ ត្រឹមត្រូវមួយ (ដែលនឹងមិនត្រូវបានបដិសេធដោយម៉ាស៊ីនមេ) ស្ទ្រីមបៃ? អ្នកនឹងត្រូវអានឯកសារ (បាទ មានតំណភ្ជាប់ទៅគ្រោងការណ៍នៅក្នុងកំណែ JSON នៅក្បែរនោះ - ប៉ុន្តែវាមិនធ្វើឱ្យវាច្បាស់ជាងនេះទេ).

បើកទំព័រ សៀរៀលទិន្នន័យគោលពីរ ហើយចូលទៅក្នុងពិភពវេទមន្តនៃផ្សិត និងគណិតវិទ្យាដាច់ពីគ្នា ដែលស្រដៀងនឹងម៉ាតាននៅឆ្នាំទី 4 ។ អក្ខរក្រម ប្រភេទ តម្លៃ ឧបករណ៍ផ្សំ ឧបករណ៍ផ្សំមុខងារ ទម្រង់ធម្មតា ប្រភេទសមាសធាតុ ប្រភេទប៉ូលីម័រហ្វី... ហើយនោះគ្រាន់តែជាទំព័រដំបូងប៉ុណ្ណោះ! បន្ទាប់កំពុងរង់ចាំអ្នក។ ភាសា TLដែលទោះបីជាវាមានឧទាហរណ៍នៃសំណើ និងការឆ្លើយតបដ៏កម្រមួយរួចហើយក៏ដោយ ប៉ុន្តែមិនបានផ្តល់ចម្លើយទាល់តែសោះចំពោះករណីធម្មតាបន្ថែមទៀត ដែលមានន័យថាអ្នកនឹងត្រូវឆ្លងកាត់ការរំលឹកឡើងវិញនៃគណិតវិទ្យាដែលបានបកប្រែពីភាសារុស្សីទៅជាភាសាអង់គ្លេសនៅលើប្រាំបីផ្សេងទៀតដែលបានបង្កប់។ ទំព័រ!

អ្នកអានដែលស្គាល់ភាសាមុខងារ និងការសន្និដ្ឋានប្រភេទស្វ័យប្រវត្តិ ពិតណាស់នឹងឃើញភាសាពិពណ៌នានៅក្នុងភាសានេះ សូម្បីតែពីឧទាហរណ៍ដូចជាស៊ាំជាង ហើយអាចនិយាយបានថានេះពិតជាមិនអាក្រក់ជាគោលការណ៍ទេ។ ការជំទាស់នេះគឺ៖

  • បាទ គោលដៅ ស្តាប់ទៅល្អ ប៉ុន្តែនាង មិនបានសម្រេច
  • ការអប់រំនៅសាកលវិទ្យាល័យរុស្ស៊ីមានភាពខុសប្លែកគ្នាសូម្បីតែក្នុងចំណោមជំនាញ IT ក៏ដោយ មិនមែនគ្រប់គ្នាសុទ្ធតែបានចូលរៀនវគ្គដែលត្រូវគ្នានោះទេ។
  • ទីបំផុតដូចដែលយើងនឹងឃើញនៅក្នុងការអនុវត្តវាគឺ មិនចាំបាច់ចាប់តាំងពីមានតែសំណុំរងមានកំណត់នៃសូម្បីតែ TL ដែលត្រូវបានពិពណ៌នាត្រូវបានប្រើ

ដូចបាននិយាយ LeoNerd នៅលើឆានែល #perl នៅក្នុងបណ្តាញ FreeNode IRC ដែលបានព្យាយាមអនុវត្តច្រកពី Telegram ទៅ Matrix (ការបកប្រែសម្រង់គឺមិនត្រឹមត្រូវពីអង្គចងចាំ):

វាមានអារម្មណ៍ថាមាននរណាម្នាក់ត្រូវបានគេណែនាំអោយវាយទ្រឹស្ដីជាលើកដំបូង រំភើប និងចាប់ផ្តើមព្យាយាមលេងជាមួយវា ដោយមិនខ្វល់ថាវាចាំបាច់ក្នុងការអនុវត្តនោះទេ។

សូមមើលដោយខ្លួនឯង ប្រសិនបើតម្រូវការសម្រាប់ប្រភេទទទេ (int, វែង។ វ៉ិចទ័រ. នោះ​គឺ​តាម​ពិត​ទៅ អារេប្រសិនបើអ្នកហៅវត្ថុលទ្ធផលដោយឈ្មោះត្រឹមត្រូវ។

ប៉ុន្តែ​ដំបូង

ការពិពណ៌នាខ្លីនៃសំណុំរងនៃវាក្យសម្ព័ន្ធ TL សម្រាប់អ្នកដែលមិនអានឯកសារផ្លូវការ

constructor = Type;
myVec ids:Vector<long> = Type;

fixed#abcdef34 id:int = Type2;

fixedVec set:Vector<Type2> = FixedVec;

constructorOne#crc32 field1:int = PolymorType;
constructorTwo#2crc32 field_a:long field_b:Type3 field_c:int = PolymorType;
constructorThree#deadcrc bit_flags_of_what_really_present:# optional_field4:bit_flags_of_what_really_present.1?Type = PolymorType;

an_id#12abcd34 id:int = Type3;
a_null#6789cdef = Type3;

និយមន័យតែងតែចាប់ផ្តើម អ្នកសាងសង់បន្ទាប់ពីនោះជាជម្រើស (ក្នុងការអនុវត្ត - ជានិច្ច) តាមរយៈនិមិត្តសញ្ញា # ត្រូវតែជា កាកបាទក្រហមកម្ពុជា ៣២ ពីខ្សែអក្សរពិពណ៌នាធម្មតានៃប្រភេទនេះ។ បន្ទាប់​មក​ការ​ពណ៌នា​អំពី​វាល ប្រសិនបើ​ពួកវា​មាន នោះ​ប្រភេទ​អាច​នឹង​ទទេ។ ទាំងអស់នេះបញ្ចប់ដោយសញ្ញាស្មើគ្នា ឈ្មោះប្រភេទដែលអ្នកសាងសង់នេះ - នោះជាការពិត ប្រភេទរង - ជាកម្មសិទ្ធិ។ បុរសនៅខាងស្តាំនៃសញ្ញាស្មើ ប៉ូលីម័រហ្វីក - នោះគឺប្រភេទជាក់លាក់មួយចំនួនអាចឆ្លើយតបនឹងវា។

ប្រសិនបើនិយមន័យកើតឡើងបន្ទាប់ពីបន្ទាត់ ---functions---បន្ទាប់មកវាក្យសម្ព័ន្ធនឹងនៅដដែល ប៉ុន្តែអត្ថន័យនឹងខុសគ្នា៖ អ្នកសាងសង់នឹងក្លាយជាឈ្មោះនៃមុខងារ RPC វាលនឹងក្លាយជាប៉ារ៉ាម៉ែត្រ (ល្អ នោះមានន័យថាវានឹងនៅតែដូចគ្នាទៅនឹងរចនាសម្ព័ន្ធដែលបានផ្តល់ឱ្យដូចដែលបានពិពណ៌នាខាងក្រោម។ នេះគ្រាន់តែជាអត្ថន័យដែលបានកំណត់) និង "ប្រភេទប៉ូលីម័រហ្វីក" - ប្រភេទនៃលទ្ធផលត្រឡប់មកវិញ។ ពិត វា​នឹង​នៅ​តែ​នៅ​តែ​ជា​ពហុម័រ - គ្រាន់​តែ​បាន​កំណត់​ក្នុង​ផ្នែក ---types---ប៉ុន្តែអ្នកសាងសង់នេះនឹង "មិនត្រូវបានពិចារណា" ។ ផ្ទុកលើសទម្ងន់នៃប្រភេទមុខងារដែលហៅថាដោយអាគុយម៉ង់របស់ពួកគេ i.e. សម្រាប់ហេតុផលមួយចំនួន មុខងារជាច្រើនដែលមានឈ្មោះដូចគ្នា ប៉ុន្តែហត្ថលេខាផ្សេងគ្នា ដូចជានៅក្នុង C++ មិនត្រូវបានផ្តល់ឱ្យនៅក្នុង TL ទេ។

ហេតុអ្វីបានជា "constructor" និង "polymorphic" ប្រសិនបើវាមិនមែនជា OOP? តាមពិតទៅ វានឹងកាន់តែងាយស្រួលសម្រាប់នរណាម្នាក់ក្នុងការគិតអំពីរឿងនេះនៅក្នុងពាក្យ OOP ដែលជាប្រភេទប៉ូលីម័រហ្វីកជាថ្នាក់អរូបី ហើយអ្នកសាងសង់គឺជាថ្នាក់បន្តផ្ទាល់របស់វា ហើយ final នៅក្នុងវាក្យស័ព្ទនៃភាសាមួយចំនួន។ ជាការពិត មានតែនៅទីនេះប៉ុណ្ណោះ។ ភាពស្រដៀងគ្នា ជាមួយនឹងវិធីសាស្រ្តសាងសង់លើសទម្ងន់ពិតប្រាកដនៅក្នុងភាសាសរសេរកម្មវិធី OO ។ ដោយសារទីនេះគ្រាន់តែជារចនាសម្ព័ន្ធទិន្នន័យ គ្មានវិធីសាស្រ្ត (ទោះបីជាការពិពណ៌នាអំពីមុខងារ និងវិធីសាស្រ្តបន្ថែមទៀតគឺពិតជាមានសមត្ថភាពបង្កើតភាពច្របូកច្របល់នៅក្នុងក្បាលដែលពួកគេមាន ប៉ុន្តែនោះជាបញ្ហាផ្សេង) - អ្នកអាចគិតពីអ្នកសាងសង់ជាតម្លៃពី ដែល កំពុងត្រូវបានសាងសង់ វាយនៅពេលអានស្ទ្រីមបៃ។

តើរឿងនេះកើតឡើងដោយរបៀបណា? deserializer ដែលតែងតែអាន 4 បៃមើលឃើញតម្លៃ 0xcrc32 - និងយល់ពីអ្វីដែលនឹងកើតឡើងបន្ទាប់ field1 ជាមួយប្រភេទ int, i.e. អានយ៉ាងពិតប្រាកដ 4 បៃ លើវាលដែលត្រួតលើគ្នាជាមួយប្រភេទ PolymorType អាន។ ឃើញ 0x2crc32 ហើយយល់ថាមានវាលពីរបន្ថែមទៀត ទីមួយ longដែលមានន័យថាយើងអាន 8 បៃ។ ហើយបន្ទាប់មកម្តងទៀត ប្រភេទស្មុគស្មាញ ដែលត្រូវបាន deserialized នៅក្នុងវិធីដូចគ្នា។ ឧទាហរណ៍, Type3 អាចត្រូវបានប្រកាសនៅក្នុងសៀគ្វីភ្លាមៗនៅពេលដែល constructors ពីររៀងគ្នា បន្ទាប់មកពួកគេត្រូវតែជួបទាំងពីរ 0x12abcd34បន្ទាប់ពីនោះអ្នកត្រូវអាន 4 បៃទៀត។ int, ឬ 0x6789cdefបន្ទាប់ពីនោះនឹងគ្មានអ្វីសោះ។ អ្វីផ្សេងទៀត - អ្នកត្រូវដកករណីលើកលែងមួយ។ ទោះយ៉ាងណាក៏ដោយបន្ទាប់ពីនេះយើងត្រលប់ទៅអាន 4 បៃ int វាល field_c в constructorTwo ហើយជាមួយនឹងការនោះយើងបញ្ចប់ការអានរបស់យើង។ PolymorType.

ទី​បំផុត​ប្រសិន​បើ​ចាប់​បាន​ 0xdeadcrc សម្រាប់ constructorThreeបន្ទាប់មកអ្វីៗកាន់តែស្មុគស្មាញ។ វាលដំបូងរបស់យើងគឺ bit_flags_of_what_really_present ជាមួយប្រភេទ # - តាមពិតនេះគ្រាន់តែជាឈ្មោះក្លែងក្លាយសម្រាប់ប្រភេទប៉ុណ្ណោះ។ natមានន័យថា "លេខធម្មជាតិ" ។ នោះជាការពិត int ដែលមិនបានចុះហត្ថលេខា គឺជាករណីតែមួយគត់នៅពេលដែលលេខដែលមិនបានចុះហត្ថលេខាកើតឡើងនៅក្នុងសៀគ្វីពិត។ ដូច្នេះបន្ទាប់គឺជាសំណង់ដែលមានសញ្ញាសួរមានន័យថាវាលនេះ - វានឹងមានវត្តមាននៅលើខ្សែលុះត្រាតែប៊ីតដែលត្រូវគ្នាត្រូវបានកំណត់នៅក្នុងវាលដែលសំដៅលើ (ប្រហាក់ប្រហែលដូចជាប្រតិបត្តិករ ternary) ។ ដូច្នេះ ចូរសន្មតថាប៊ីតនេះត្រូវបានកំណត់ ដែលមានន័យថា បន្ថែមទៀតយើងត្រូវអានវាលដូច Typeដែលក្នុងឧទាហរណ៍របស់យើងមាន 2 constructors ។ មួយ​គឺ​ទទេ (មាន​តែ​អ្នក​កំណត់​អត្តសញ្ញាណ) មួយ​ទៀត​មាន​វាល ids ជាមួយប្រភេទ ids:Vector<long>.

អ្នក​ប្រហែល​ជា​គិត​ថា​ទាំង​គំរូ និង​ទូទៅ​គឺ​ស្ថិត​នៅ​ក្នុង​គុណសម្បត្តិ ឬ Java។ ប៉ុន្តែទេ។ ស្ទើរតែ។ នេះ។ តែមួយគត់ ករណីនៃការប្រើប្រាស់តង្កៀបមុំនៅក្នុងសៀគ្វីពិត ហើយវាត្រូវបានប្រើសម្រាប់តែវ៉ិចទ័រប៉ុណ្ណោះ។ ក្នុងមួយបៃ ស្ទ្រីមទាំងនេះនឹងជា 4 CRC32 បៃសម្រាប់ប្រភេទវ៉ិចទ័រខ្លួនវាតែងតែដូចគ្នា បន្ទាប់មក 4 បៃ - ចំនួននៃធាតុអារេ ហើយបន្ទាប់មកធាតុទាំងនេះដោយខ្លួនឯង។

បន្ថែមលើការពិតដែលថា សៀរៀលតែងតែកើតឡើងនៅក្នុងពាក្យ 4 បៃ គ្រប់ប្រភេទទាំងអស់គឺគុណរបស់វា - ប្រភេទដែលភ្ជាប់មកជាមួយក៏ត្រូវបានពិពណ៌នាផងដែរ។ bytes и string ជាមួយនឹងសៀរៀលដោយដៃនៃប្រវែង និងការតម្រឹមនេះដោយ 4 - ល្អ វាហាក់ដូចជាធម្មតា ហើយថែមទាំងមានប្រសិទ្ធភាពដែរ? ទោះបីជា TL ត្រូវបានគេអះអាងថាជាសៀរៀលគោលពីរដែលមានប្រសិទ្ធភាពក៏ដោយ ទៅកាន់ឋាននរកជាមួយពួកគេជាមួយនឹងការពង្រីកអ្វីទាំងអស់ សូម្បីតែតម្លៃប៊ូលីន និងខ្សែអក្សរតែមួយដល់ 4 បៃ តើ JSON នឹងនៅតែក្រាស់ជាងនេះទេ? មើល សូម្បីតែវាលដែលមិនចាំបាច់អាចត្រូវបានរំលងដោយទង់ប៊ីត អ្វីគ្រប់យ៉ាងគឺល្អ ហើយថែមទាំងអាចពង្រីកបានសម្រាប់ពេលអនាគត ដូច្នេះហេតុអ្វីមិនបន្ថែមវាលជម្រើសថ្មីទៅអ្នកសាងសង់នៅពេលក្រោយ?..

ប៉ុន្តែមិនមែនទេ ប្រសិនបើអ្នកអានមិនមែនជាការពិពណ៌នាសង្ខេបរបស់ខ្ញុំទេ ប៉ុន្តែជាឯកសារពេញលេញ ហើយគិតអំពីការអនុវត្ត។ ទីមួយ CRC32 របស់អ្នកសាងសង់ត្រូវបានគណនាតាមបន្ទាត់ធម្មតានៃការពិពណ៌នាអត្ថបទនៃគ្រោងការណ៍ (ដកដកឃ្លាបន្ថែម។ ជាលទ្ធផល សៀរៀល។ ហើយ​តើ​អតិថិជន​ចាស់​នឹង​ធ្វើ​យ៉ាង​ណា​ប្រសិនបើ​គាត់​បាន​ទទួល​វាល​ដែល​មាន​ទង់​ថ្មី ហើយ​គាត់​មិន​ដឹង​ថា​ត្រូវ​ធ្វើអ្វី​ជាមួយ​ពួកគេ​បន្ទាប់​?

ទីពីរ ចូរយើងចងចាំ កាកបាទក្រហមកម្ពុជា ៣២ដែលត្រូវបានប្រើនៅទីនេះជាសំខាន់ មុខងារ hash ដើម្បី​កំណត់​ដោយឡែក​ពី​ប្រភេទ​អ្វី​ដែល​កំពុង​ត្រូវ​បាន (de)serialized។ នៅទីនេះយើងកំពុងប្រឈមមុខនឹងបញ្ហានៃការប៉ះទង្គិចគ្នា - ហើយទេប្រូបាប៊ីលីតេមិនមែនជាមួយក្នុង 232 ទេ ប៉ុន្តែធំជាង។ តើអ្នកណាដែលចាំថា CRC32 ត្រូវបានរចនាឡើងដើម្បីរកឱ្យឃើញ (និងកែ) កំហុសនៅក្នុងបណ្តាញទំនាក់ទំនង ហើយស្របទៅតាមការកែលម្អលក្ខណៈសម្បត្តិទាំងនេះចំពោះការធ្វើឱ្យខូចដល់អ្នកដទៃ? ជាឧទាហរណ៍ វាមិនខ្វល់នឹងការរៀបចំបៃឡើងវិញទេ៖ ប្រសិនបើអ្នកគណនា CRC32 ពីបន្ទាត់ពីរនោះ ក្នុងវិនាទី អ្នកប្តូរ 4 បៃដំបូងជាមួយ 4 បៃបន្ទាប់ - វានឹងដូចគ្នា។ នៅពេលដែលការបញ្ចូលរបស់យើងគឺជាខ្សែអក្សរពីអក្ខរក្រមឡាតាំង (និងសញ្ញាវណ្ណយុត្តិបន្តិច) ហើយឈ្មោះទាំងនេះមិនចៃដន្យជាពិសេស លទ្ធភាពនៃការរៀបចំឡើងវិញបែបនេះកើនឡើងយ៉ាងខ្លាំង។

និយាយអីញ្ចឹង តើអ្នកណាបានពិនិត្យអ្វីនៅទីនោះ? ពិតជា CRC32? មួយនៃកូដប្រភពដំបូង (សូម្បីតែមុន Waltman) មានមុខងារ hash ដែលគុណតួអក្សរនីមួយៗដោយលេខ 239 ដូច្នេះមនុស្សទាំងនេះជាទីស្រឡាញ់ ហាហា!

ទីបំផុត មិនអីទេ យើងបានដឹងថាអ្នកសាងសង់ដែលមានប្រភេទវាល Vector<int> и Vector<PolymorType> នឹងមាន CRC32 ផ្សេងគ្នា។ ចុះ​ការ​អនុវត្ត​តាម​អ៊ីនធឺណិត​វិញ? ហើយតាមទស្សនៈទ្រឹស្តី តើនេះក្លាយជាផ្នែកមួយនៃប្រភេទ? ឧបមាថាយើងឆ្លងកាត់អារេនៃលេខមួយម៉ឺន Vector<int> អ្វីគ្រប់យ៉ាងគឺច្បាស់លាស់ប្រវែងនិង 40000 បៃទៀត។ ហើយប្រសិនបើនេះ។ Vector<Type2>ដែលមានវាលតែមួយ int ហើយវាតែម្នាក់ឯងនៅក្នុងប្រភេទ - តើយើងត្រូវធ្វើម្តងទៀត 10000xabcdef0 34 ដងហើយបន្ទាប់មក 4 បៃ intឬភាសាអាចឯករាជ្យសម្រាប់យើងពីអ្នកសាងសង់ fixedVec ហើយជំនួសឱ្យ 80000 បៃ ផ្ទេរម្តងទៀតត្រឹមតែ 40000 ទេ?

នេះមិនមែនជាសំណួរទ្រឹស្តីទំនេរទាល់តែសោះ - ស្រមៃថាអ្នកទទួលបានបញ្ជីអ្នកប្រើប្រាស់ជាក្រុម ដែលម្នាក់ៗមានលេខសម្គាល់ ឈ្មោះ នាមត្រកូល - ភាពខុសគ្នានៃចំនួនទិន្នន័យដែលបានផ្ទេរតាមរយៈការតភ្ជាប់ទូរស័ព្ទអាចមានសារៈសំខាន់។ វាច្បាស់ណាស់ប្រសិទ្ធភាពនៃសៀរៀល Telegram ដែលត្រូវបានផ្សព្វផ្សាយដល់យើង។

ដូច្នេះ…

វ៉ិចទ័រដែលមិនដែលត្រូវបានចេញផ្សាយ

ប្រសិនបើអ្នកព្យាយាមចូលទៅក្នុងទំព័រនៃការពិពណ៌នានៃ combinators ហើយដូច្នេះនៅលើ អ្នកនឹងឃើញថាវ៉ិចទ័រ (និងសូម្បីតែម៉ាទ្រីស) កំពុងព្យាយាមជាផ្លូវការដើម្បីបញ្ចេញតាមរយៈ tuples នៃសន្លឹកជាច្រើន។ ប៉ុន្តែនៅទីបញ្ចប់ពួកគេភ្លេច ជំហានចុងក្រោយត្រូវបានរំលង ហើយនិយមន័យនៃវ៉ិចទ័រមួយត្រូវបានផ្តល់ឱ្យយ៉ាងសាមញ្ញ ដែលមិនទាន់បានចងភ្ជាប់ជាមួយប្រភេទមួយ។ តើ​មាន​រឿង​អ្វី​កើតឡើង? ជាភាសា ការសរសេរកម្មវិធីជាពិសេសមុខងារដែលមានមុខងារ វាជារឿងធម្មតាណាស់ក្នុងការពិពណ៌នាអំពីរចនាសម្ព័ន្ធឡើងវិញ - អ្នកចងក្រងជាមួយនឹងការវាយតម្លៃខ្ជិលនឹងយល់ និងធ្វើអ្វីៗគ្រប់យ៉ាងដោយខ្លួនឯង។ ជាភាសា សៀរៀលទិន្នន័យ អ្វី​ដែល​ត្រូវ​ការ​គឺ​ប្រសិទ្ធភាព៖ វា​គ្រប់គ្រាន់​ដើម្បី​ពណ៌នា​ដោយ​សាមញ្ញ បញ្ជី, i.e. រចនាសម្ព័ន្ធនៃធាតុពីរ - ទីមួយគឺជាធាតុទិន្នន័យ ទីពីរគឺជារចនាសម្ព័ន្ធដូចគ្នាដោយខ្លួនឯង ឬចន្លោះទទេសម្រាប់កន្ទុយ (កញ្ចប់ (cons) នៅក្នុង Lisp) ។ ប៉ុន្តែនេះច្បាស់ណាស់នឹងត្រូវការ នៃគ្នា ធាតុចំណាយបន្ថែម 4 បៃ (CRC32 ក្នុងករណីនៅក្នុង TL) ដើម្បីពិពណ៌នាអំពីប្រភេទរបស់វា។ អារេក៏អាចពិពណ៌នាយ៉ាងងាយស្រួលផងដែរ។ ទំហំថេរប៉ុន្តែក្នុងករណីអារេនៃប្រវែងមិនស្គាល់ជាមុន យើងបំបែកចេញ។

ដូច្នេះ ដោយសារ TL មិនអនុញ្ញាតឱ្យបញ្ចេញវ៉ិចទ័រ វាត្រូវតែបន្ថែមនៅចំហៀង។ ទីបំផុតឯកសារនិយាយថា៖

សៀរៀលតែងតែប្រើ constructor “vector” ដូចគ្នា (const 0x1cb5c415 = crc32(“vector t:Type # [ t ] = Vector t”) ដែលមិនអាស្រ័យលើតម្លៃជាក់លាក់នៃអថេរនៃប្រភេទ t ។

តម្លៃនៃប៉ារ៉ាម៉ែត្រស្រេចចិត្ត t មិនជាប់ពាក់ព័ន្ធក្នុងការសៀរៀលទេ ព្រោះវាមានប្រភពមកពីប្រភេទលទ្ធផល (តែងតែស្គាល់មុនការបំភាន់)។

សូមក្រឡេកមើលឱ្យកាន់តែច្បាស់៖ vector {t:Type} # [ t ] = Vector t - ប៉ុន្តែ កន្លែងណា។ និយមន័យ​នេះ​ខ្លួន​ឯង​មិន​បាន​និយាយ​ថា​លេខ​ដំបូង​ត្រូវ​តែ​ស្មើ​នឹង​ប្រវែង​វ៉ិចទ័រ​ទេ! ហើយវាមិនមកពីណាទេ។ នេះគឺជាការផ្តល់ឱ្យដែលត្រូវតែរក្សាទុកក្នុងចិត្តនិងអនុវត្តដោយដៃរបស់អ្នក។ នៅកន្លែងផ្សេងទៀត ឯកសារនេះថែមទាំងនិយាយដោយស្មោះត្រង់ថា ប្រភេទមិនពិត៖

Vector t polymorphic pseudotype គឺជា "ប្រភេទ" ដែលតម្លៃរបស់វាជាលំដាប់នៃតម្លៃនៃប្រភេទ t ណាមួយ ទាំងប្រអប់ ឬទទេ។

... ប៉ុន្តែមិនផ្តោតលើវាទេ។ នៅពេលដែលអ្នកធុញទ្រាន់នឹងការតស៊ូផ្នែកគណិតវិទ្យា (ប្រហែលជាស្គាល់អ្នកពីវគ្គសិក្សានៅសកលវិទ្យាល័យ) សម្រេចចិត្តបោះបង់ ហើយមើលពីរបៀបធ្វើការជាមួយវាក្នុងការអនុវត្ត ចំណាប់អារម្មណ៍ដែលបន្សល់ទុកក្នុងក្បាលរបស់អ្នកគឺថា នេះគឺធ្ងន់ធ្ងរ។ គណិតវិទ្យាជាស្នូល វាត្រូវបានបង្កើតយ៉ាងច្បាស់ដោយ Cool People (គណិតវិទូពីរនាក់ - អ្នកឈ្នះ ACM) ហើយមិនមែនតែនរណាម្នាក់នោះទេ។ គោលដៅ - ដើម្បីបង្ហាញ - ត្រូវបានសម្រេច។

ដោយវិធីនេះអំពីលេខ។ អនុញ្ញាតឱ្យយើងរំលឹកអ្នកថា # វាជាពាក្យមានន័យដូច natលេខធម្មជាតិ៖

មានកន្សោមប្រភេទ (ប្រភេទ-expr) និងកន្សោមលេខ (nat-expr) ទោះយ៉ាងណាក៏ដោយពួកគេត្រូវបានកំណត់តាមរបៀបដូចគ្នា។

type-expr ::= expr
nat-expr ::= expr

ប៉ុន្តែនៅក្នុងវេយ្យាករណ៍ពួកគេត្រូវបានពិពណ៌នាតាមរបៀបដូចគ្នា i.e. ភាពខុសគ្នានេះត្រូវតែចងចាំម្តងទៀត ហើយដាក់ឱ្យអនុវត្តដោយដៃ។

បាទ បាទ ប្រភេទគំរូ (vector<int>, vector<User>) មាន​គ្រឿង​សម្គាល់​ទូទៅ (#1cb5c415), i.e. ប្រសិនបើអ្នកដឹងថាការហៅទូរស័ព្ទត្រូវបានប្រកាសជា

users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;

បន្ទាប់មកអ្នកលែងរង់ចាំតែវ៉ិចទ័រទៀតហើយ ប៉ុន្តែវ៉ិចទ័ររបស់អ្នកប្រើប្រាស់។ កាន់តែច្បាស់, គួរតែ រង់ចាំ - នៅក្នុងកូដពិត រាល់ធាតុទាំងអស់ ប្រសិនបើមិនមែនជាប្រភេទទទេ នឹងមាន constructor ហើយក្នុងវិធីល្អក្នុងការអនុវត្ត វាចាំបាច់ណាស់ក្នុងការត្រួតពិនិត្យ - ប៉ុន្តែយើងត្រូវបានគេផ្ញើយ៉ាងពិតប្រាកដនៅក្នុងគ្រប់ធាតុនៃវ៉ិចទ័រនេះ ប្រភេទនោះ។? ចុះ​បើ​វា​ជា​ប្រភេទ PHP មួយ​ណា​ដែល​អារេ​អាច​មាន​ប្រភេទ​ផ្សេងៗ​គ្នា​ក្នុង​ធាតុ​ផ្សេងៗ?

នៅចំណុចនេះអ្នកចាប់ផ្តើមគិត - តើ TL បែបនេះចាំបាច់ទេ? ប្រហែលជាសម្រាប់រទេះ វាអាចប្រើឧបករណ៍សៀរៀលរបស់មនុស្ស ដែលជាប្រូតូប៊ូហ្វដូចគ្នាដែលមានរួចហើយ? នោះជាទ្រឹស្តី តោះមើលការអនុវត្ត។

ការអនុវត្ត TL ដែលមានស្រាប់នៅក្នុងកូដ

TL បានកើតនៅក្នុងជម្រៅនៃ VKontakte សូម្បីតែមុនពេលព្រឹត្តិការណ៍ដ៏ល្បីល្បាញជាមួយនឹងការលក់ភាគហ៊ុនរបស់ Durov និង (ប្រហែល) សូម្បីតែមុនពេលការអភិវឌ្ឍន៍ Telegram បានចាប់ផ្តើម។ ហើយនៅក្នុងប្រភពបើកចំហ កូដប្រភពនៃការអនុវត្តដំបូង អ្នកអាចរកឃើញឈើច្រត់គួរឱ្យអស់សំណើចជាច្រើន។ ហើយភាសាខ្លួនវាត្រូវបានអនុវត្តនៅទីនោះយ៉ាងពេញលេញជាងវានៅក្នុង Telegram ។ ឧទាហរណ៍ សញ្ញាហាមមិនត្រូវបានប្រើទាល់តែសោះនៅក្នុងគ្រោងការណ៍ (មានន័យថា pseudotype ដែលភ្ជាប់មកជាមួយ (ដូចជាវ៉ិចទ័រ) ដែលមានអាកប្បកិរិយាខុសឆ្គង)។ ឬ

Templates are not used now. Instead, the same universal constructors (for example, vector {t:Type} [t] = Vector t) are used w

ប៉ុន្តែ ចូរយើងពិចារណា ដើម្បីភាពពេញលេញ ដើម្បីតាមដាន ដូច្នេះដើម្បីនិយាយ ការវិវត្តន៍នៃគំនិតយក្ស។

#define ZHUKOV_BYTES_HACK

#ifdef ZHUKOV_BYTES_HACK

/* dirty hack for Zhukov request */

ឬមួយដ៏ស្រស់ស្អាតនេះ៖

    static const char *reserved_words_polymorhic[] = {

      "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", NULL

      };

បំណែកនេះនិយាយអំពីគំរូដូចជា៖

intHash {alpha:Type} vector<coupleInt<alpha>> = IntHash<alpha>;

នេះគឺជានិយមន័យនៃប្រភេទគំរូ hashmap ជាវ៉ិចទ័រនៃ int - Type pairs ។ នៅក្នុង C++ វានឹងមើលទៅដូចនេះ៖

    template <T> class IntHash {
      vector<pair<int,T>> _map;
    }

ដូច្នេះ alpha - ពាក្យគន្លឹះ! ប៉ុន្តែមានតែនៅក្នុង C++ ទេដែលអ្នកអាចសរសេរ T ប៉ុន្តែអ្នកគួរតែសរសេរ alpha, beta... ប៉ុន្តែមិនលើសពី 8 parameters នោះហើយជាកន្លែងដែល Fantasy បញ្ចប់។ វាហាក់ដូចជាមានពេលមួយនៅ St. Petersburg ការសន្ទនាមួយចំនួនដូចនេះបានកើតឡើង៖

-- Надо сделать в TL шаблоны
-- Бл... Ну пусть параметры зовут альфа, бета,... Какие там ещё буквы есть... О, тэта!
-- Грамматика? Ну потом напишем

-- Смотрите, какой я синтаксис придумал для шаблонов и вектора!
-- Ты долбанулся, как мы это парсить будем?
-- Да не ссыте, он там один в схеме, захаркодить -- и ок

ប៉ុន្តែនេះគឺអំពីការអនុវត្តដែលបានបោះពុម្ពផ្សាយជាលើកដំបូងនៃ TL "ជាទូទៅ" ។ ចូរបន្តទៅការពិចារណាលើការអនុវត្តនៅក្នុងអតិថិជន Telegram ខ្លួនឯង។

ពាក្យទៅកាន់ Vasily:

Vasily, [09.10.18 17:07] ភាគច្រើន លាគឺក្តៅដោយសារគេបង្កើតបណ្តុំអរូបី រួចយកញញួរដាក់លើពួកវា ហើយគ្របម៉ាស៊ីនបង្កើតកូដដោយឈើច្រត់
ជាលទ្ធផលដំបូងពី dock pilot.jpg
បន្ទាប់មកពីកូដ dzhekichan.webp

ជាការពិតណាស់ ពីមនុស្សដែលស្គាល់ក្បួនដោះស្រាយ និងគណិតវិទ្យា យើងអាចរំពឹងថាពួកគេបានអាន Aho, Ullmann ហើយស្គាល់ឧបករណ៍ដែលបានក្លាយជាស្តង់ដារជាក់ស្តែងនៅក្នុងឧស្សាហកម្មជាច្រើនទសវត្សរ៍សម្រាប់ការសរសេរកម្មវិធីចងក្រង DSL របស់ពួកគេមែនទេ?..

ដោយ Telegram-cli គឺ Vitaly Valtman ដូចដែលអាចយល់បានពីការកើតឡើងនៃទម្រង់ TLO នៅខាងក្រៅព្រំដែន (cli) របស់វា ដែលជាសមាជិកនៃក្រុម - ឥឡូវនេះបណ្ណាល័យសម្រាប់ការញែក TL ត្រូវបានបែងចែក ដោយឡែកពីគ្នា។តើអ្វីជាចំណាប់អារម្មណ៍របស់នាង ឧបករណ៍ញែក TL? ..

16.12 04:18 Vasily: ខ្ញុំគិតថាមាននរណាម្នាក់មិនបានស្ទាត់ជំនាញ lex+yacc
16.12 04:18 Vasily: ខ្ញុំមិនអាចពន្យល់វាផ្សេងបានទេ។
16.12 04:18 Vasily: ល្អឬពួកគេត្រូវបានបង់សម្រាប់ចំនួនបន្ទាត់នៅក្នុង VK
16.12 04:19 Vasily: បន្ទាត់ 3k+ ល។<censored> ជំនួសឱ្យឧបករណ៍ញែក

ប្រហែលជាករណីលើកលែង? តោះមើលពីរបៀប ធ្វើ នេះគឺជាអតិថិជនផ្លូវការ - Telegram Desktop៖

    nametype = re.match(r'([a-zA-Z.0-9_]+)(#[0-9a-f]+)?([^=]*)=s*([a-zA-Z.<>0-9_]+);', line);
    if (not nametype):
      if (not re.match(r'vector#1cb5c415 {t:Type} # [ t ] = Vector t;', line)):
         print('Bad line found: ' + line);

1100+ បន្ទាត់នៅក្នុង Python ដែលជាកន្សោមធម្មតាពីរបី + ករណីពិសេសដូចជាវ៉ិចទ័រ ដែលជាការពិតណាស់ត្រូវបានប្រកាសនៅក្នុងគ្រោងការណ៍ដូចដែលវាគួរតែយោងទៅតាមវាក្យសម្ព័ន្ធ TL ប៉ុន្តែពួកគេពឹងផ្អែកលើវាក្យសម្ព័ន្ធនេះដើម្បីញែកវា... សំណួរកើតឡើងថាហេតុអ្វីបានជាអព្ភូតហេតុទាំងអស់?иវា​កាន់តែ​មាន​ស្រទាប់​បើ​គ្មាន​អ្នក​វិភាគ​តាម​ឯកសារ​នោះ​ទេ?!

និយាយអីញ្ចឹង... នៅចាំថាយើងបាននិយាយអំពីការត្រួតពិនិត្យ CRC32 ទេ? ដូច្នេះនៅក្នុងម៉ាស៊ីនបង្កើតកូដ Telegram Desktop មានបញ្ជីករណីលើកលែងសម្រាប់ប្រភេទទាំងនោះដែល CRC32 គណនា មិនត្រូវគ្នា។ ជាមួយនឹងអ្វីដែលបានបង្ហាញនៅក្នុងដ្យាក្រាម!

Vasily, [18.12/22 49:XNUMX] ហើយនៅទីនេះខ្ញុំនឹងគិតអំពីថាតើ TL បែបនេះគឺចាំបាច់ឬអត់
ប្រសិនបើខ្ញុំចង់រញ៉េរញ៉ៃជាមួយការអនុវត្តជំនួស ខ្ញុំនឹងចាប់ផ្តើមបញ្ចូលការបំបែកបន្ទាត់ ពាក់កណ្តាលនៃអ្នកញែកនឹងបំបែកលើនិយមន័យពហុជួរ
ទោះយ៉ាងណាក៏ដោយ tdesktop ផងដែរ។

ចងចាំចំណុចអំពីបន្ទាត់តែមួយ យើងនឹងត្រលប់ទៅវាវិញបន្តិចក្រោយមក។

មិនអីទេ Telegram-cli មិនផ្លូវការទេ Telegram Desktop គឺផ្លូវការ ប៉ុន្តែចុះយ៉ាងណាវិញ? អ្នកណាដឹង?.. នៅក្នុងកូដម៉ាស៊ីនភ្ញៀវ Android មិនមានកម្មវិធីញែកគ្រោងការណ៍ទាល់តែសោះ (ដែលចោទជាសំណួរអំពីប្រភពបើកចំហ ប៉ុន្តែនេះគឺសម្រាប់ផ្នែកទីពីរ) ប៉ុន្តែមានកូដគួរឱ្យអស់សំណើចជាច្រើនផ្សេងទៀត ប៉ុន្តែមានច្រើនទៀតនៅលើពួកវានៅក្នុង ផ្នែកខាងក្រោម។

តើ​សំណួរ​អ្វី​ទៀត​ដែល​សៀរៀល​លើកឡើង​ក្នុង​ការអនុវត្ត​? ជាឧទាហរណ៍ ពួកគេបានធ្វើកិច្ចការជាច្រើន ពិតណាស់ជាមួយនឹងវាលប៊ីត និងវាលតាមលក្ខខណ្ឌ៖

វ៉ាស៊ីលី៖ flags.0? true
មាន​ន័យ​ថា​វាល​មាន​វត្តមាន​និង​ស្មើ​នឹង​ពិត​ប្រសិន​បើ​ទង់​ត្រូវ​បាន​កំណត់​

វ៉ាស៊ីលី៖ flags.1? int
មាន​ន័យ​ថា​វាល​នេះ​មាន​វត្តមាន​ហើយ​ត្រូវ​ការ deserialized

Vasily៖ លាហើយ កុំបារម្ភពីអ្វីដែលអ្នកកំពុងធ្វើ!
Vasily៖ មានការលើកឡើងនៅកន្លែងណាមួយក្នុងឯកសារថា ពិតគឺជាប្រភេទប្រវែងសូន្យ ប៉ុន្តែវាមិនអាចទៅរួចទេក្នុងការប្រមូលផ្តុំអ្វីមួយពីឯកសាររបស់ពួកគេ
Vasily៖ នៅក្នុងការអនុវត្តប្រភពបើកចំហនេះក៏មិនមែនជាករណីដែរ ប៉ុន្តែមានឈើច្រត់ និងជំនួយជាច្រើន

ចុះ Telethon? សម្លឹងឆ្ពោះទៅមុខប្រធានបទនៃ MTProto ជាឧទាហរណ៍មួយ - នៅក្នុងឯកសារមានបំណែកបែបនេះ ប៉ុន្តែសញ្ញា % វាត្រូវបានពិពណ៌នាថាជា "ដែលត្រូវគ្នាទៅនឹងប្រភេទទទេដែលបានផ្តល់ឱ្យ" ពោលគឺឧ។ នៅក្នុងឧទាហរណ៍ខាងក្រោមមានកំហុស ឬអ្វីមួយដែលមិនមានឯកសារ៖

Vasily, [22.06.18 18:38] នៅកន្លែងតែមួយ៖

msg_container#73f1f8dc messages:vector message = MessageContainer;

នៅ​ក្នុង​មួយ​ផ្សេង​គ្នា​:

msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;

ហើយទាំងនេះគឺជាភាពខុសគ្នាធំពីរ ដែលនៅក្នុងជីវិតពិតប្រភេទនៃវ៉ិចទ័រអាក្រាតមួយចំនួនបានមក

ខ្ញុំមិនបានឃើញនិយមន័យវ៉ិចទ័រទទេ ហើយមិនបានឆ្លងកាត់មួយ។

ការវិភាគត្រូវបានសរសេរដោយដៃនៅក្នុង telethon

នៅក្នុងដ្យាក្រាមរបស់គាត់ និយមន័យត្រូវបានបញ្ចេញមតិ msg_container

ជាថ្មីម្តងទៀតសំណួរនៅតែមានអំពី % ។ វាមិនត្រូវបានពិពណ៌នាទេ។

Vadim Goncharov, [22.06.18 19:22] និងនៅក្នុង tdesktop?

Vasily, [22.06.18 19:23] ប៉ុន្តែការញែក TL របស់ពួកគេនៅលើម៉ាស៊ីនធម្មតាទំនងជានឹងមិនស៊ីវាទេ

// parsed manually

TL គឺជាអរូបីដ៏ស្រស់ស្អាត គ្មាននរណាម្នាក់អនុវត្តវាទាំងស្រុងនោះទេ។

ហើយ % មិនមាននៅក្នុងកំណែរបស់ពួកគេនៃគ្រោងការណ៍ទេ។

ប៉ុន្តែនៅទីនេះឯកសារផ្ទុយពីខ្លួនវា ដូច្នេះ idk

វាត្រូវបានគេរកឃើញនៅក្នុងវេយ្យាករណ៍ ពួកគេអាចភ្លេចពណ៌នាអំពីអត្ថន័យ

អ្នកបានឃើញឯកសារនៅលើ TL អ្នកមិនអាចដោះស្រាយវាដោយគ្មានកន្លះលីត្របានទេ។

"អញ្ចឹង ចូរនិយាយថា" អ្នកអានម្នាក់ទៀតនឹងនិយាយថា "អ្នករិះគន់អ្វីមួយ ដូច្នេះបង្ហាញខ្ញុំពីរបៀបដែលវាគួរតែត្រូវបានធ្វើ" ។

Vasily ឆ្លើយតបថា "ចំពោះអ្នកញែក ខ្ញុំចូលចិត្តអ្វីៗដូចជា

    args: /* empty */ { $$ = NULL; }
        | args arg { $$ = g_list_append( $1, $2 ); }
        ;

    arg: LC_ID ':' type-term { $$ = tl_arg_new( $1, $3 ); }
            | LC_ID ':' condition '?' type-term { $$ = tl_arg_new_cond( $1, $5, $3 ); free($3); }
            | UC_ID ':' type-term { $$ = tl_arg_new( $1, $3 ); }
            | type-term { $$ = tl_arg_new( "", $1 ); }
            | '[' LC_ID ']' { $$ = tl_arg_new_mult( "", tl_type_new( $2, TYPE_MOD_NONE ) ); }
            ;

ដូចម្ដេចដែលចូលចិត្តវាប្រសើរជាង

struct tree *parse_args4 (void) {
  PARSE_INIT (type_args4);
  struct parse so = save_parse ();
  PARSE_TRY (parse_optional_arg_def);
  if (S) {
    tree_add_child (T, S);
  } else {
    load_parse (so);
  }
  if (LEX_CHAR ('!')) {
    PARSE_ADD (type_exclam);
    EXPECT ("!");
  }
  PARSE_TRY_PES (parse_type_term);
  PARSE_OK;
}

        # Regex to match the whole line
        match = re.match(r'''
            ^                  # We want to match from the beginning to the end
            ([w.]+)           # The .tl object can contain alpha_name or namespace.alpha_name
            (?:
                #             # After the name, comes the ID of the object
                ([0-9a-f]+)    # The constructor ID is in hexadecimal form
            )?                 # If no constructor ID was given, CRC32 the 'tl' to determine it

            (?:s              # After that, we want to match its arguments (name:type)
                {?             # For handling the start of the '{X:Type}' case
                w+            # The argument name will always be an alpha-only name
                :              # Then comes the separator between name:type
                [wd<>#.?!]+  # The type is slightly more complex, since it's alphanumeric and it can
                               # also have Vector<type>, flags:# and flags.0?default, plus :!X as type
                }?             # For handling the end of the '{X:Type}' case
            )*                 # Match 0 or more arguments
            s                 # Leave a space between the arguments and the equal
            =
            s                 # Leave another space between the equal and the result
            ([wd<>#.?]+)     # The result can again be as complex as any argument type
            ;$                 # Finally, the line should always end with ;
            ''', tl, re.IGNORECASE | re.VERBOSE)

នេះគឺជា lexer ទាំងមូល៖

    ---functions---         return FUNCTIONS;
    ---types---             return TYPES;
    [a-z][a-zA-Z0-9_]*      yylval.string = strdup(yytext); return LC_ID;
    [A-Z][a-zA-Z0-9_]*      yylval.string = strdup(yytext); return UC_ID;
    [0-9]+                  yylval.number = atoi(yytext); return NUM;
    #[0-9a-fA-F]{1,8}       yylval.number = strtol(yytext+1, NULL, 16); return ID_HASH;

    n                      /* skip new line */
    [ t]+                  /* skip spaces */
    //.*$                 /* skip comments */
    /*.**/              /* skip comments */
    .                       return (int)yytext[0];

ទាំងនោះ។ សាមញ្ញ​គឺ​ដាក់​វា​ដោយ​ស្លូតបូត។»

ជាទូទៅ ជាលទ្ធផល សេក និងម៉ាស៊ីនបង្កើតកូដសម្រាប់សំណុំរងដែលបានប្រើពិតប្រាកដនៃ TL សមនឹងចូលទៅក្នុងប្រហែល 100 បន្ទាត់នៃវេយ្យាករណ៍ និង ~ 300 បន្ទាត់នៃម៉ាស៊ីនភ្លើង (រាប់ទាំងអស់ printកូដដែលបានបង្កើត) រួមទាំងប្រភេទព័ត៌មានទន្សាយសម្រាប់វិចារណកថាក្នុងថ្នាក់នីមួយៗ។ ប្រភេទប៉ូលីម័រហ្វីកនីមួយៗប្រែទៅជាថ្នាក់មូលដ្ឋានអរូបីទទេ ហើយអ្នកសាងសង់ទទួលមរតកពីវា ហើយមានវិធីសាស្រ្តសម្រាប់ serialization និង deserialization ។

កង្វះនៃប្រភេទនៅក្នុងភាសាប្រភេទ

ការវាយអក្សរខ្លាំងគឺជារឿងល្អមែនទេ? ទេ នេះមិនមែនជា holivar (ទោះបីជាខ្ញុំចូលចិត្តភាសាថាមវន្តក៏ដោយ) ប៉ុន្តែជា postulate នៅក្នុងក្របខ័ណ្ឌនៃ TL ។ ដោយផ្អែកលើវា ភាសាគួរតែផ្តល់ការត្រួតពិនិត្យគ្រប់ប្រភេទសម្រាប់ពួកយើង។ ជាការប្រសើរណាស់, មិនអីទេ, ប្រហែលជាមិនមែនជាគាត់ផ្ទាល់, ប៉ុន្តែការអនុវត្ត, ប៉ុន្តែយ៉ាងហោចណាស់គាត់គួរតែពណ៌នាពួកគេ។ ហើយតើយើងចង់បានឱកាសបែបណា?

ជាដំបូងនៃការទាំងអស់, ឧបសគ្គ។ នៅទីនេះយើងឃើញនៅក្នុងឯកសារសម្រាប់ការផ្ទុកឡើងឯកសារ៖

បន្ទាប់មកមាតិកាគោលពីររបស់ឯកសារត្រូវបានបំបែកជាផ្នែកៗ។ ផ្នែកទាំងអស់ត្រូវតែមានទំហំដូចគ្នា ( ផ្នែក_ទំហំ ) ហើយលក្ខខណ្ឌខាងក្រោមត្រូវតែបំពេញ៖

  • part_size % 1024 = 0 (បែងចែកដោយ 1KB)
  • 524288 % part_size = 0 (512KB ត្រូវតែបែងចែកស្មើៗគ្នាដោយ part_size)

ផ្នែកចុងក្រោយមិនចាំបាច់បំពេញលក្ខខណ្ឌទាំងនេះទេ បើទំហំរបស់វាតិចជាង part_size។

ផ្នែកនីមួយៗគួរតែមានលេខលំដាប់ ឯកសារ_ផ្នែកជាមួយនឹងតម្លៃចាប់ពី 0 ដល់ 2,999។

បន្ទាប់ពីឯកសារត្រូវបានបែងចែក អ្នកត្រូវជ្រើសរើសវិធីសាស្ត្រសម្រាប់រក្សាទុកវានៅលើម៉ាស៊ីនមេ។ ប្រើ upload.saveBigFilePart ក្នុងករណីដែលទំហំពេញនៃឯកសារលើសពី 10 MB និង upload.saveFilePart សម្រាប់ឯកសារតូចៗ។
[…] កំហុស​បញ្ចូល​ទិន្នន័យ​មួយ​ក្នុង​ចំណោម​កំហុស​បញ្ចូល​ទិន្នន័យ​ខាងក្រោម​អាច​នឹង​ត្រូវ​បាន​ត្រឡប់​មក​វិញ៖

  • FILE_PARTS_INVALID — ចំនួនផ្នែកមិនត្រឹមត្រូវ។ តម្លៃមិនស្ថិតនៅចន្លោះ 1..3000

តើនេះមាននៅក្នុងដ្យាក្រាមទេ? តើ​នេះ​ជា​ការ​បញ្ចេញ​មតិ​ដោយ​ប្រើ TL ដែរ​ឬ​ទេ? ទេ ប៉ុន្តែសូមអភ័យទោស សូម្បីតែ Turbo Pascal របស់ជីតាក៏អាចពិពណ៌នាអំពីប្រភេទដែលបានបញ្ជាក់ផងដែរ។ ជួរ. ហើយ​គាត់​បាន​ដឹង​រឿង​មួយ​ទៀត ដែល​ឥឡូវ​គេ​ស្គាល់​ច្បាស់​ថា​ជា enum - ប្រភេទ​មួយ​ដែល​មាន​ការ​រាប់​បញ្ចូល​នៃ​ចំនួន​ថេរ (តូច) នៃ​តម្លៃ។ នៅក្នុងភាសាដូចជា C - numeric សូមចំណាំថារហូតមកដល់ពេលនេះយើងបាននិយាយតែអំពីប្រភេទប៉ុណ្ណោះ។ លេខ. ប៉ុន្តែក៏មាន arrays, strings... ជាឧទាហរណ៍ វាជាការល្អក្នុងការពណ៌នាថា string នេះអាចផ្ទុកបានតែលេខទូរស័ព្ទ មែនទេ?

គ្មានអ្វីនៅក្នុង TL ទេ។ ប៉ុន្តែមានឧទាហរណ៍នៅក្នុង JSON Schema ។ ហើយប្រសិនបើនរណាម្នាក់ផ្សេងទៀតអាចប្រកែកអំពីការបែងចែកនៃ 512 KB ថាវានៅតែត្រូវពិនិត្យនៅក្នុងកូដ បន្ទាប់មកត្រូវប្រាកដថាអតិថិជនគ្រាន់តែ មិនអាច ផ្ញើលេខចេញពីជួរ 1..3000 (ហើយកំហុសដែលត្រូវគ្នាមិនអាចកើតឡើងទេ) វាអាចទៅរួចមែនទេ? ..

ដោយវិធីនេះអំពីកំហុសនិងតម្លៃត្រឡប់។ សូម្បីតែអ្នកដែលបានធ្វើការជាមួយ TL ធ្វើឱ្យភ្នែករបស់ពួកគេព្រិល - វាមិនភ្លឺចំពោះយើងភ្លាមៗនោះទេ។ គ្នា មុខងារនៅក្នុង TL ពិតជាអាចត្រឡប់មិនត្រឹមតែប្រភេទត្រឡប់ដែលបានពិពណ៌នាប៉ុណ្ណោះទេ ប៉ុន្តែក៏មានកំហុសផងដែរ។ ប៉ុន្តែ នេះ​មិន​អាច​កាត់​បាន​តាម​វិធី​ណា​មួយ​ដោយ​ប្រើ TL ខ្លួន​វា​ទេ។ ជាការពិតណាស់ វាច្បាស់ហើយ ហើយមិនត្រូវការអ្វីនៅក្នុងការអនុវត្តទេ (ទោះបីជាការពិត RPC អាចត្រូវបានធ្វើតាមរបៀបផ្សេងៗក៏ដោយ យើងនឹងត្រលប់មកចំណុចនេះនៅពេលក្រោយ) ប៉ុន្តែចុះយ៉ាងណាចំពោះភាពបរិសុទ្ធនៃគោលគំនិតនៃគណិតវិទ្យានៃប្រភេទអរូបី។ ពីពិភពស្ថានសួគ៌?.. ខ្ញុំបានរើសទាញ - ដូច្នេះត្រូវគ្នា។

ហើយចុងក្រោយ ចុះយ៉ាងណាចំពោះការអាន? នៅទីនោះ ជាទូទៅខ្ញុំចង់ បរិយាយ តើវាត្រឹមត្រូវនៅក្នុងគ្រោងការណ៍ (នៅក្នុងគ្រោងការណ៍ JSON ម្តងទៀតវាគឺជា) ប៉ុន្តែប្រសិនបើអ្នកមានភាពតានតឹងជាមួយវារួចហើយ ចុះយ៉ាងណាចំពោះផ្នែកជាក់ស្តែងវិញ - យ៉ាងហោចណាស់សម្លឹងមើលភាពខុសប្លែកគ្នាក្នុងពេលធ្វើបច្ចុប្បន្នភាព? មើលដោយខ្លួនឯងនៅ ឧទាហរណ៍ជាក់ស្តែង:

-channelFull#76af5481 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int = ChatFull;
+channelFull#1c87a71a flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int = ChatFull;

-message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;
+message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;

វាអាស្រ័យលើមនុស្សគ្រប់រូប ប៉ុន្តែឧទាហរណ៍ GitHub បដិសេធក្នុងការរំលេចការផ្លាស់ប្តូរនៅក្នុងជួរវែងបែបនេះ។ ល្បែង "ស្វែងរកភាពខុសគ្នា 10" ហើយអ្វីដែលខួរក្បាលឃើញភ្លាមៗនោះគឺថាការចាប់ផ្តើម និងចុងបញ្ចប់នៃឧទាហរណ៍ទាំងពីរគឺដូចគ្នា អ្នកត្រូវអានដោយធុញទ្រាន់នៅកន្លែងណាមួយនៅកណ្តាល... តាមគំនិតរបស់ខ្ញុំ នេះមិនមែនគ្រាន់តែជាទ្រឹស្តីប៉ុណ្ណោះទេ។ ប៉ុន្តែដោយមើលឃើញសុទ្ធសាធ កខ្វក់និងកខ្វក់.

ដោយវិធីនេះអំពីភាពបរិសុទ្ធនៃទ្រឹស្តី។ ហេតុអ្វីបានជាយើងត្រូវការវាលប៊ីត? វាហាក់ដូចជាពួកគេមិនមែនទេ ក្លិន អាក្រក់ពីទស្សនៈនៃទ្រឹស្ដីប្រភេទ? ការពន្យល់អាចត្រូវបានគេមើលឃើញនៅក្នុងកំណែមុននៃដ្យាក្រាម។ ដំបូង បាទ នោះហើយជារបៀបដែលវាគឺសម្រាប់រាល់ការកណ្តាស់ ប្រភេទថ្មីត្រូវបានបង្កើតឡើង។ rudiments ទាំងនេះនៅតែមាននៅក្នុងទម្រង់នេះ ឧទាហរណ៍៖

storage.fileUnknown#aa963b05 = storage.FileType;
storage.filePartial#40bc6f52 = storage.FileType;
storage.fileJpeg#7efe0e = storage.FileType;
storage.fileGif#cae1aadf = storage.FileType;
storage.filePng#a4f63c0 = storage.FileType;
storage.filePdf#ae1e508d = storage.FileType;
storage.fileMp3#528a0677 = storage.FileType;
storage.fileMov#4b09ebbc = storage.FileType;
storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;

ប៉ុន្តែឥឡូវនេះសូមស្រមៃថា ប្រសិនបើអ្នកមានជម្រើសចំនួន 5 នៅក្នុងរចនាសម្ព័ន្ធរបស់អ្នក នោះអ្នកនឹងត្រូវការ 32 ប្រភេទសម្រាប់ជម្រើសដែលអាចធ្វើបានទាំងអស់។ ការផ្ទុះរួមគ្នា។ ដូច្នេះ ភាពបរិសុទ្ធនៃគ្រីស្តាល់នៃទ្រឹស្ដី TL បានខ្ចាត់ខ្ចាយជាថ្មីម្ដងទៀតប្រឆាំងនឹងការស្រោបដែកនៃការពិតដ៏អាក្រក់នៃសៀរៀល។

លើសពីនេះទៀតនៅកន្លែងខ្លះបុរសទាំងនេះខ្លួនឯងបំពានលើអក្សរសាស្ត្រផ្ទាល់ខ្លួនរបស់ពួកគេ។ ឧទាហរណ៍នៅក្នុង MTProto (ជំពូកបន្ទាប់) ការឆ្លើយតបអាចត្រូវបានបង្ហាប់ដោយ Gzip អ្វីគ្រប់យ៉ាងគឺល្អ - លើកលែងតែស្រទាប់និងសៀគ្វីត្រូវបានរំលោភ។ ជាថ្មីម្តងទៀត វាមិនមែនជា RpcResult ខ្លួនវាដែលត្រូវបានច្រូតកាត់នោះទេ ប៉ុន្តែខ្លឹមសាររបស់វា។ មែនហើយ ហេតុអ្វីធ្វើបែបនេះ?.. ខ្ញុំត្រូវកាត់ឈើច្រត់ ដើម្បីឱ្យការបង្ហាប់អាចដំណើរការបានគ្រប់ទីកន្លែង។

ឬឧទាហរណ៍មួយទៀត យើងបានរកឃើញកំហុសមួយ - វាត្រូវបានផ្ញើ InputPeerUser ជំនួសឱ្យ។ InputUser. ឬផ្ទុយមកវិញ។ ប៉ុន្តែវាដំណើរការ! នោះគឺម៉ាស៊ីនមេមិនខ្វល់អំពីប្រភេទទេ។ តើនេះអាចទៅជាយ៉ាងណា? ចម្លើយអាចត្រូវបានផ្តល់ឱ្យយើងដោយបំណែកកូដពី telegram-cli:

  if (tgl_get_peer_type (E->id) != TGL_PEER_CHANNEL || (C && (C->flags & TGLCHF_MEGAGROUP))) {
    out_int (CODE_messages_get_history);
    out_peer_id (TLS, E->id);
  } else {    
    out_int (CODE_channels_get_important_history);

    out_int (CODE_input_channel);
    out_int (tgl_get_peer_id (E->id));
    out_long (E->id.access_hash);
  }
  out_int (E->max_id);
  out_int (E->offset);
  out_int (E->limit);
  out_int (0);
  out_int (0);

នៅក្នុងពាក្យផ្សេងទៀតនេះគឺជាកន្លែងដែលសៀរៀលត្រូវបានធ្វើ ដោយដៃមិន​បាន​បង្កើត​កូដ! ប្រហែលជាម៉ាស៊ីនមេត្រូវបានអនុវត្តតាមរបៀបស្រដៀងគ្នា?.. ជាគោលការណ៍ វានឹងដំណើរការប្រសិនបើធ្វើម្តង ប៉ុន្តែតើវាអាចត្រូវបានគាំទ្រនៅពេលក្រោយក្នុងអំឡុងពេលធ្វើបច្ចុប្បន្នភាពយ៉ាងដូចម្តេច? តើនេះជាមូលហេតុដែលគ្រោងការណ៍ត្រូវបានបង្កើត? ហើយនៅទីនេះយើងបន្តទៅសំណួរបន្ទាប់។

កំណែ។ ស្រទាប់

ហេតុអ្វីបានជាកំណែ schematic ត្រូវបានគេហៅថាស្រទាប់អាចត្រូវបានប៉ាន់ស្មានដោយផ្អែកលើប្រវត្តិសាស្រ្តនៃការបោះពុម្ព schematics ។ ជាក់ស្តែង ដំបូងឡើយ អ្នកនិពន្ធបានគិតថា អ្វីៗជាមូលដ្ឋានអាចត្រូវបានធ្វើដោយប្រើគ្រោងការណ៍ដែលមិនផ្លាស់ប្តូរ ហើយមានតែក្នុងករណីចាំបាច់សម្រាប់សំណើជាក់លាក់ប៉ុណ្ណោះ ដែលបង្ហាញថាពួកគេកំពុងត្រូវបានធ្វើដោយប្រើកំណែផ្សេង។ ជាគោលការណ៍ បើទោះបីជាវាមិនមែនជាគំនិតអាក្រក់ក៏ដោយ ថ្មីនឹងត្រូវបាន "លាយបញ្ចូលគ្នា" ដូចដែលវាត្រូវបានដាក់នៅលើកំពូលនៃចាស់។ ប៉ុន្តែសូមមើលពីរបៀបដែលវាត្រូវបានធ្វើ។ ពិតហើយ ខ្ញុំមិនអាចមើលវាតាំងពីដើមដំបូងឡើយ - វាគួរឱ្យអស់សំណើច ប៉ុន្តែដ្យាក្រាមនៃស្រទាប់មូលដ្ឋានគឺមិនមានទេ។ ស្រទាប់ចាប់ផ្តើមដោយ 2. ឯកសារប្រាប់យើងអំពីលក្ខណៈពិសេស TL ពិសេស៖

ប្រសិនបើអតិថិជនគាំទ្រស្រទាប់ទី 2 នោះអ្នកសាងសង់ខាងក្រោមត្រូវតែប្រើ៖

invokeWithLayer2#289dd1f6 {X:Type} query:!X = X;

នៅក្នុងការអនុវត្ត នេះមានន័យថា មុនពេលការហៅ API នីមួយៗ int ជាមួយនឹងតម្លៃ 0x289dd1f6 ត្រូវតែបន្ថែមមុនលេខវិធីសាស្ត្រ។

ស្តាប់ទៅធម្មតា។ ប៉ុន្តែតើមានអ្វីកើតឡើងបន្ទាប់? បន្ទាប់មកបានបង្ហាញខ្លួន

invokeWithLayer3#b7475268 query:!X = X;

ដូច្នេះតើមានអ្វីបន្ទាប់? ដូចដែលអ្នកអាចទាយបាន

invokeWithLayer4#dea0d430 query:!X = X;

កំប្លែង? ទេ វាឆាប់ពេកក្នុងការសើច គិតអំពីការពិត គ្នា សំណើពីស្រទាប់មួយទៀតត្រូវតែរុំក្នុងប្រភេទពិសេសបែបនេះ - ប្រសិនបើពួកវាខុសគ្នាសម្រាប់អ្នក តើអ្នកអាចបែងចែកពួកវាដោយរបៀបណា? ហើយការបន្ថែមត្រឹមតែ 4 បៃនៅខាងមុខគឺជាវិធីសាស្ត្រដ៏មានប្រសិទ្ធភាព។ ដូច្នេះ

invokeWithLayer5#417a57ae query:!X = X;

ប៉ុន្តែវាច្បាស់ណាស់ថាបន្ទាប់ពីមួយរយៈនេះនឹងក្លាយជាប្រភេទនៃ bacchanalia មួយចំនួន។ ហើយដំណោះស្រាយបានមកដល់៖

អាប់ដេត៖ ចាប់ផ្តើមជាមួយស្រទាប់ទី 9 វិធីសាស្ត្រជំនួយ invokeWithLayerN អាចប្រើបានតែជាមួយ initConnection

ហ៊ឺយ! បន្ទាប់ពីកំណែ 9 ទីបំផុតយើងបានមកដល់អ្វីដែលបានធ្វើនៅក្នុងពិធីការអ៊ីនធឺណិតត្រឡប់មកវិញនៅក្នុងទសវត្សរ៍ទី 80 - យល់ព្រមលើកំណែម្តងនៅដើមការតភ្ជាប់!

ដូច្នេះតើមានអ្វីបន្ទាប់? ..

invokeWithLayer10#39620c41 query:!X = X;
...
invokeWithLayer18#1c900537 query:!X = X;

ប៉ុន្តែឥឡូវនេះអ្នកនៅតែអាចសើចបាន។ មានតែបន្ទាប់ពីស្រទាប់ 9 ផ្សេងទៀត អ្នកសាងសង់សកលដែលមានលេខកំណែត្រូវបានបន្ថែម ដែលត្រូវការហៅតែម្តងគត់នៅដើមការតភ្ជាប់ ហើយអត្ថន័យនៃស្រទាប់ហាក់ដូចជាបានបាត់ទៅហើយ ឥឡូវនេះវាគ្រាន់តែជាកំណែតាមលក្ខខណ្ឌដូចជា គ្រប់ទីកន្លែង។ បញ្ហាត្រូវបានដោះស្រាយ។

យ៉ាង​ពិតប្រាកដ?..

Vasily, [16.07.18 14:01] សូម្បីតែថ្ងៃសុក្រខ្ញុំបានគិតថា:
teleserver ផ្ញើព្រឹត្តិការណ៍ដោយគ្មានការស្នើសុំ។ សំណើត្រូវតែត្រូវបានរុំក្នុង InvokeWithLayer ។ ម៉ាស៊ីនមេមិនរុំការអាប់ដេតទេ មិនមានរចនាសម្ព័ន្ធសម្រាប់រុំការឆ្លើយតប និងការធ្វើបច្ចុប្បន្នភាពទេ។

ទាំងនោះ។ ម៉ាស៊ីនភ្ញៀវមិនអាចបញ្ជាក់ស្រទាប់ដែលគាត់ចង់ធ្វើបច្ចុប្បន្នភាពបានទេ។

Vadim Goncharov, [16.07.18 14:02] មិនមែនជា InvokeWithLayer ជាគោលការណ៍ទេ?

Vasily, [16.07.18 14:02] នេះជាវិធីតែមួយគត់

Vadim Goncharov, [16.07.18 14:02] ដែលសំខាន់គួរតែមានន័យថាយល់ព្រមលើស្រទាប់នៅដើមសម័យប្រជុំ

ដោយវិធីនេះ វាធ្វើតាមថាការទម្លាក់ចំណាត់ថ្នាក់របស់អតិថិជនមិនត្រូវបានផ្តល់ឱ្យទេ។

អាប់ដេត, i.e. ប្រភេទ Updates នៅក្នុងគ្រោងការណ៍ នេះជាអ្វីដែលម៉ាស៊ីនមេផ្ញើទៅអតិថិជនមិនឆ្លើយតបទៅនឹងសំណើ API ទេ ប៉ុន្តែដោយឯករាជ្យនៅពេលដែលព្រឹត្តិការណ៍កើតឡើង។ នេះគឺជាប្រធានបទដ៏ស្មុគស្មាញមួយដែលនឹងត្រូវបានពិភាក្សានៅក្នុងការប្រកាសមួយផ្សេងទៀត ប៉ុន្តែសម្រាប់ពេលនេះ វាជារឿងសំខាន់ដែលត្រូវដឹងថាម៉ាស៊ីនមេរក្សាទុកការអាប់ដេត បើទោះបីជាម៉ាស៊ីនភ្ញៀវមិនមានអ៊ីនធឺណិតក៏ដោយ។

ដូច្នេះប្រសិនបើអ្នកបដិសេធមិនរុំ នៃគ្នា កញ្ចប់ដើម្បីបង្ហាញពីកំណែរបស់វា ឡូជីខលនេះនាំឱ្យមានបញ្ហាដែលអាចកើតមានដូចខាងក្រោម៖

  • ម៉ាស៊ីនមេ ផ្ញើការអាប់ដេតទៅកាន់ម៉ាស៊ីនភ្ញៀវ សូម្បីតែមុនពេលដែលអតិថិជនបានជូនដំណឹងអំពីកំណែដែលវាគាំទ្រក៏ដោយ។
  • តើខ្ញុំគួរធ្វើដូចម្តេចបន្ទាប់ពីធ្វើបច្ចុប្បន្នភាពអតិថិជន?
  • នរណា ការធានាថាមតិរបស់ម៉ាស៊ីនមេអំពីលេខស្រទាប់នឹងមិនផ្លាស់ប្តូរក្នុងអំឡុងពេលដំណើរការទេ?

តើ​អ្នក​គិត​ថា​នេះ​គឺ​ជា​ការ​ស្មាន​តាម​ទ្រឹស្ដី​សុទ្ធសាធ ហើយ​ក្នុង​ការ​អនុវត្ត​វា​មិន​អាច​កើត​ឡើង​បាន​ទេ ព្រោះ​ម៉ាស៊ីន​បម្រើ​ត្រូវ​បាន​សរសេរ​ត្រឹមត្រូវ (យ៉ាង​ហោច​ណាស់​វា​ត្រូវ​បាន​សាកល្បង​ល្អ)? ហា! មិនថាវាយ៉ាងម៉េចទេ!

នេះ​ជា​អ្វី​ដែល​យើង​បាន​ជួប​ក្នុង​ខែ​សីហា។ នៅថ្ងៃទី 14 ខែសីហា មានសារថាអ្វីមួយកំពុងត្រូវបានធ្វើបច្ចុប្បន្នភាពនៅលើម៉ាស៊ីនមេ Telegram... ហើយបន្ទាប់មកនៅក្នុងកំណត់ហេតុ៖

2019-08-15 09:28:35.880640 MSK warn  main: ANON:87: unknown object type: 0x80d182d1 at TL/Object.pm line 213.
2019-08-15 09:28:35.751899 MSK warn  main: ANON:87: unknown object type: 0xb5223b0f at TL/Object.pm line 213.

ហើយបន្ទាប់មកមានដានជង់ជាច្រើនមេកាបៃ (ល្អនៅពេលជាមួយគ្នាការកាប់ឈើត្រូវបានជួសជុល) ។ យ៉ាងណាមិញ ប្រសិនបើអ្វីមួយមិនត្រូវបានទទួលស្គាល់នៅក្នុង TL របស់អ្នក វាជាប្រព័ន្ធគោលពីរដោយហត្ថលេខា បន្តចុះក្រោម ទាំងអស់។ ទៅ ការឌិកូដនឹងមិនអាចទៅរួចនោះទេ។ តើអ្នកគួរធ្វើអ្វីក្នុងស្ថានភាពបែបនេះ?

ជាការប្រសើរណាស់ រឿងដំបូងដែលចូលមកក្នុងគំនិតរបស់នរណាម្នាក់គឺត្រូវផ្តាច់ទំនាក់ទំនង ហើយព្យាយាមម្តងទៀត។ មិនបានជួយទេ។ យើង Google CRC32 - ទាំងនេះបានប្រែទៅជាវត្ថុពីគ្រោងការណ៍ 73 ទោះបីជាយើងបានធ្វើការលើ 82 ក៏ដោយ។ យើងពិនិត្យមើលដោយប្រុងប្រយ័ត្ននូវកំណត់ហេតុ - មានឧបករណ៍សម្គាល់ពីគ្រោងការណ៍ពីរផ្សេងគ្នា!

ប្រហែលជាបញ្ហាគឺនៅក្នុងអតិថិជនក្រៅផ្លូវការរបស់យើងសុទ្ធសាធ? ទេ យើងបើកដំណើរការ Telegram Desktop 1.2.17 (កំណែដែលបានផ្គត់ផ្គង់នៅក្នុងការចែកចាយលីនុចមួយចំនួន) វាសរសេរទៅកាន់ Exception log: MTP Unexpected type id #b5223b0f read in MTPMessageMedia…

ការរិះគន់លើពិធីសារ និងវិធីសាស្រ្តរៀបចំរបស់ Telegram ។ ផ្នែកទី 1 បច្ចេកទេស៖ បទពិសោធន៍នៃការសរសេរអតិថិជនពីដំបូង - TL, MT

Google បានបង្ហាញថាបញ្ហាស្រដៀងគ្នានេះបានកើតឡើងចំពោះអតិថិជនក្រៅផ្លូវការមួយរួចទៅហើយ ប៉ុន្តែបន្ទាប់មកលេខកំណែ ហើយយោងទៅតាមការសន្មត់គឺខុសគ្នា ...

ដូច្នេះតើយើងគួរធ្វើអ្វី? Vasily និងខ្ញុំបានបែកគ្នា៖ គាត់បានព្យាយាមធ្វើបច្ចុប្បន្នភាពសៀគ្វីទៅលេខ 91 ខ្ញុំបានសម្រេចចិត្តរង់ចាំពីរបីថ្ងៃហើយព្យាយាមនៅលើ 73 ។ វិធីសាស្ត្រទាំងពីរនេះដំណើរការ ប៉ុន្តែដោយសារវាមានលក្ខណៈជាក់ស្តែង វាមិនយល់ថាតើអ្នកត្រូវការកំណែប៉ុន្មានឡើង ឬចុះក្រោមនោះទេ។ ដើម្បីលោត ឬរយៈពេលប៉ុន្មានដែលអ្នកត្រូវរង់ចាំ។

ក្រោយមកខ្ញុំអាចបង្កើតស្ថានភាពឡើងវិញបាន៖ យើងបើកដំណើរការម៉ាស៊ីនភ្ញៀវ បិទវា ចងក្រងសៀគ្វីទៅស្រទាប់មួយទៀត ចាប់ផ្តើមឡើងវិញ ចាប់បញ្ហាម្តងទៀត ត្រឡប់ទៅលេខមុនវិញ - អូ៎ គ្មានចំនួននៃការប្តូរសៀគ្វី ហើយម៉ាស៊ីនភ្ញៀវចាប់ផ្តើមឡើងវិញសម្រាប់ ពីរបីនាទីនឹងជួយ។ អ្នកនឹងទទួលបានរចនាសម្ព័ន្ធទិន្នន័យចម្រុះពីស្រទាប់ផ្សេងៗគ្នា។

ការពន្យល់? ដូចដែលអ្នកអាចទាយពីរោគសញ្ញាដោយប្រយោលផ្សេងៗ ម៉ាស៊ីនមេមានដំណើរការជាច្រើននៃប្រភេទផ្សេងៗគ្នានៅលើម៉ាស៊ីនផ្សេងៗគ្នា។ ភាគច្រើនទំនងជាម៉ាស៊ីនមេដែលទទួលខុសត្រូវចំពោះ "ការបណ្ដោះអាសន្ន" បានដាក់ចូលទៅក្នុងជួរនូវអ្វីដែលថ្នាក់លើបានផ្តល់ឱ្យវា ហើយពួកគេបានផ្តល់ឱ្យវានៅក្នុងគ្រោងការណ៍ដែលបានកើតឡើងនៅជំនាន់។ ហើយរហូតដល់ជួរនេះ "រលួយ" គ្មានអ្វីអាចធ្វើបានអំពីវាទេ។

ប្រហែលជា... ប៉ុន្តែនេះគឺជាឈើច្រត់ដ៏គួរឱ្យភ័យខ្លាច?!.. ទេ មុននឹងគិតអំពីគំនិតឆ្កួតៗ សូមក្រឡេកមើលកូដរបស់អតិថិជនផ្លូវការ។ នៅក្នុងកំណែ Android យើងរកមិនឃើញ TL parser ទេ ប៉ុន្តែយើងរកឃើញឯកសារច្រើន (GitHub បដិសេធមិនប៉ះវា) ជាមួយ (de)serialization។ ខាងក្រោម​នេះ​ជា​បណ្តុំ​កូដ៖

public static class TL_message_layer68 extends TL_message {
    public static int constructor = 0xc09be45f;
//...
//еще пачка подобных
//...
    public static class TL_message_layer47 extends TL_message {
        public static int constructor = 0xc992e15c;
        public static Message TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
            Message result = null;
            switch (constructor) {
                case 0x1d86f70e:
                    result = new TL_messageService_old2();
                    break;
                case 0xa7ab1991:
                    result = new TL_message_old3();
                    break;
                case 0xc3060325:
                    result = new TL_message_old4();
                    break;
                case 0x555555fa:
                    result = new TL_message_secret();
                    break;
                case 0x555555f9:
                    result = new TL_message_secret_layer72();
                    break;
                case 0x90dddc11:
                    result = new TL_message_layer72();
                    break;
                case 0xc09be45f:
                    result = new TL_message_layer68();
                    break;
                case 0xc992e15c:
                    result = new TL_message_layer47();
                    break;
                case 0x5ba66c13:
                    result = new TL_message_old7();
                    break;
                case 0xc06b9607:
                    result = new TL_messageService_layer48();
                    break;
                case 0x83e5de54:
                    result = new TL_messageEmpty();
                    break;
                case 0x2bebfa86:
                    result = new TL_message_old6();
                    break;
                case 0x44f9b43d:
                    result = new TL_message_layer104();
                    break;
                case 0x1c9b1027:
                    result = new TL_message_layer104_2();
                    break;
                case 0xa367e716:
                    result = new TL_messageForwarded_old2(); //custom
                    break;
                case 0x5f46804:
                    result = new TL_messageForwarded_old(); //custom
                    break;
                case 0x567699b3:
                    result = new TL_message_old2(); //custom
                    break;
                case 0x9f8d60bb:
                    result = new TL_messageService_old(); //custom
                    break;
                case 0x22eb6aba:
                    result = new TL_message_old(); //custom
                    break;
                case 0x555555F8:
                    result = new TL_message_secret_old(); //custom
                    break;
                case 0x9789dac4:
                    result = new TL_message_layer104_3();
                    break;

    boolean fixCaption = !TextUtils.isEmpty(message) &&
    (media instanceof TLRPC.TL_messageMediaPhoto_old ||
     media instanceof TLRPC.TL_messageMediaPhoto_layer68 ||
     media instanceof TLRPC.TL_messageMediaPhoto_layer74 ||
     media instanceof TLRPC.TL_messageMediaDocument_old ||
     media instanceof TLRPC.TL_messageMediaDocument_layer68 ||
     media instanceof TLRPC.TL_messageMediaDocument_layer74)
    && message.startsWith("-1");

ហ៊ឺ... មើលទៅព្រៃ។ ប៉ុន្តែ ប្រហែល​ជា​នេះ​ត្រូវ​បាន​បង្កើត​កូដ​ហើយ​មិន​អី​ទេ?.. ប៉ុន្តែ​វា​ប្រាកដ​ជា​គាំទ្រ​គ្រប់​កំណែ​ទាំងអស់! ពិតហើយ វាមិនច្បាស់ទេថាហេតុអ្វីបានជាអ្វីៗទាំងអស់បញ្ចូលគ្នា ការជជែកសម្ងាត់ និងគ្រប់ប្រភេទ _old7 ដូចម្ដេចដែលមើលទៅមិនដូចជំនាន់ម៉ាស៊ីន... ទោះយ៉ាងណាក៏ដោយ ភាគច្រើនខ្ញុំត្រូវបានផ្លុំចេញដោយ

TL_message_layer104
TL_message_layer104_2
TL_message_layer104_3

បុរសៗ អ្នកមិនអាចសម្រេចចិត្តថាមានអ្វីនៅក្នុងស្រទាប់មួយ?! ជាការប្រសើរណាស់, អនុញ្ញាតឱ្យនិយាយថា "ពីរ" ត្រូវបានចេញផ្សាយដោយមានកំហុសមួយ, វាកើតឡើង, ប៉ុន្តែបី? .. ភ្លាម, តុងរួចដូចគ្នាម្តងទៀត? តើនេះជារឿងអាសអាភាសបែបណា សុំទោស..

នៅក្នុងកូដប្រភពនៃ Telegram Desktop ដោយវិធីនេះ រឿងស្រដៀងគ្នានឹងកើតឡើង - បើដូច្នេះ ការប្តេជ្ញាចិត្តជាច្រើនក្នុងមួយជួរចំពោះគ្រោងការណ៍មិនផ្លាស់ប្តូរលេខស្រទាប់របស់វា ប៉ុន្តែជួសជុលអ្វីមួយ។ នៅក្នុងលក្ខខណ្ឌដែលមិនមានប្រភពទិន្នន័យផ្លូវការសម្រាប់គ្រោងការណ៍ តើវាអាចទទួលបានពីណា លើកលែងតែកូដប្រភពរបស់អតិថិជនផ្លូវការ? ហើយប្រសិនបើអ្នកយកវាពីទីនោះ អ្នកមិនអាចប្រាកដថាគ្រោងការណ៍នេះត្រឹមត្រូវទាំងស្រុងនោះទេ រហូតដល់អ្នកសាកល្បងគ្រប់វិធីសាស្រ្តទាំងអស់។

តើនេះអាចសាកល្បងដោយរបៀបណា? ខ្ញុំសង្ឃឹមថាអ្នកគាំទ្រនៃឯកតា មុខងារ និងការធ្វើតេស្តផ្សេងទៀតនឹងចែករំលែកនៅក្នុងមតិយោបល់។

ជាការប្រសើរណាស់ តោះមើលកូដមួយទៀត៖

public static class TL_folders_deleteFolder extends TLObject {
    public static int constructor = 0x1c295881;

    public int folder_id;

    public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
        return Updates.TLdeserialize(stream, constructor, exception);
    }

    public void serializeToStream(AbstractSerializedData stream) {
        stream.writeInt32(constructor);
        stream.writeInt32(folder_id);
    }
}

//manually created

//RichText start
public static abstract class RichText extends TLObject {
    public String url;
    public long webpage_id;
    public String email;
    public ArrayList<RichText> texts = new ArrayList<>();
    public RichText parentRichText;

    public static RichText TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
        RichText result = null;
        switch (constructor) {
            case 0x1ccb966a:
                result = new TL_textPhone();
                break;
            case 0xc7fb5e01:
                result = new TL_textSuperscript();
                break;

មតិយោបល់នេះ "បង្កើតដោយដៃ" បង្ហាញថាមានតែផ្នែកនៃឯកសារនេះត្រូវបានសរសេរដោយដៃ (តើអ្នកអាចស្រមៃមើលសុបិន្តអាក្រក់នៃការថែទាំទាំងមូលបានទេ?) ហើយអ្វីដែលនៅសល់គឺត្រូវបានបង្កើតដោយម៉ាស៊ីន។ ទោះជាយ៉ាងណាក៏ដោយបន្ទាប់មកសំណួរមួយទៀតកើតឡើង - ថាប្រភពអាចរកបាន មិនទាំងស្រុង (a la GPL blobs នៅក្នុងខឺណែលលីនុច) ប៉ុន្តែនេះគឺជាប្រធានបទសម្រាប់ផ្នែកទីពីររួចហើយ។

ប៉ុន្តែគ្រប់គ្រាន់។ ចូរបន្តទៅពិធីការនៅលើកំពូលនៃការដែលសៀរៀលទាំងអស់នេះដំណើរការ។

MT Proto

ដូច្នេះសូមបើក ការពិពណ៌នាទូទៅ и ការពិពណ៌នាលំអិតនៃពិធីការ ហើយរឿងដំបូងដែលយើងជំពប់ដួលគឺវាក្យស័ព្ទ។ ហើយជាមួយនឹងភាពសម្បូរបែបនៃអ្វីគ្រប់យ៉ាង។ ជាទូទៅ វាហាក់ដូចជាលក្ខណៈកម្មសិទ្ធិរបស់ Telegram - ហៅរបស់ផ្សេងគ្នានៅកន្លែងផ្សេងៗគ្នា ឬរបស់ផ្សេងគ្នាដោយប្រើពាក្យមួយ ឬផ្ទុយមកវិញ (ឧទាហរណ៍នៅក្នុង API កម្រិតខ្ពស់ ប្រសិនបើអ្នកឃើញកញ្ចប់ស្ទីគ័រ វាមិនមែនទេ។ អ្វីដែលអ្នកបានគិត) ។

ឧទាហរណ៍ "សារ" និង "វគ្គ" មានន័យខុសគ្នានៅទីនេះជាងចំណុចប្រទាក់អតិថិជន Telegram ធម្មតា។ ជាការប្រសើរណាស់, អ្វីគ្រប់យ៉ាងគឺច្បាស់ជាមួយនឹងសារ, វាអាចត្រូវបានបកស្រាយនៅក្នុងពាក្យ OOP ឬហៅសាមញ្ញថា "កញ្ចប់" - នេះគឺជាកម្រិតទាបនៃការដឹកជញ្ជូន, មិនមានសារដូចគ្នាដូចនៅក្នុងចំណុចប្រទាក់, មានសារសេវាជាច្រើន . ប៉ុន្តែសម័យ ... ប៉ុន្តែរឿងដំបូង។

ស្រទាប់ដឹកជញ្ជូន

រឿងដំបូងគឺការដឹកជញ្ជូន។ ពួកគេនឹងប្រាប់យើងអំពីជម្រើស 5:

  • TCP
  • រន្ធបណ្តាញ
  • Websocket លើ HTTPS
  • របស់ HTTP
  • HTTPS

Vasily, [15.06.18 15:04] ក៏មានការដឹកជញ្ជូន UDP ដែរ ប៉ុន្តែវាមិនមានឯកសារ

និង TCP ជាបីវ៉ារ្យ៉ង់

ទីមួយគឺស្រដៀងនឹង UDP លើ TCP ដែលកញ្ចប់នីមួយៗមានលេខលំដាប់ និង crc
ហេតុ​អ្វី​បាន​ជា​ការ​អាន​ឯកសារ​នៅ​លើ​រទេះ​មាន​ការ​ឈឺចាប់​ម្ល៉េះ?

មែនហើយ វាគឺឥឡូវនេះ TCP មាន 4 វ៉ារ្យ៉ង់:

  • ដាក់បញ្ចូលគ្នា
  • មធ្យម
  • ទ្រនាប់កម្រិតមធ្យម
  • ពេញ

ជាការប្រសើរណាស់, OK, Padded intermediate សម្រាប់ MTProxy, វាត្រូវបានបន្ថែមនៅពេលក្រោយដោយសារតែព្រឹត្តិការណ៍ល្បី។ ប៉ុន្តែហេតុអ្វីបានជាកំណែពីរបន្ថែមទៀត (សរុបបី) នៅពេលដែលអ្នកអាចទទួលបានដោយមួយ? សំខាន់ទាំងបួនខុសគ្នាតែក្នុងរបៀបកំណត់ប្រវែង និងបន្ទុករបស់មេ MTProto ដែលនឹងត្រូវបានពិភាក្សាបន្ថែម៖

  • នៅក្នុង Abridged វាគឺ 1 ឬ 4 បៃ ប៉ុន្តែមិនមែន 0xef បន្ទាប់មករាងកាយ
  • ក្នុងកម្រិតមធ្យម នេះគឺ 4 បៃនៃប្រវែង និងវាលមួយ ហើយជាលើកដំបូងដែលម៉ាស៊ីនភ្ញៀវត្រូវតែផ្ញើ 0xeeeeeeee ដើម្បីបង្ហាញថាវាជាកម្រិតមធ្យម
  • នៅក្នុងការញៀនពេញលេញបំផុតពីចំណុចនៃទិដ្ឋភាពនៃបណ្តាញមួយ: ប្រវែង, លេខលំដាប់, និងមិនមែនជាមួយដែលជាចម្បង MTProto, តួ, CRC32 ។ បាទ ទាំងអស់នេះស្ថិតនៅលើ TCP ។ ដែលផ្តល់ឱ្យយើងនូវការដឹកជញ្ជូនដែលអាចទុកចិត្តបានក្នុងទម្រង់ជាស្ទ្រីមបៃតាមលំដាប់លំដោយ មិនចាំបាច់មានលំដាប់ទេ ជាពិសេសការឆែកឆេរ។ មិនអីទេ ឥឡូវនេះនរណាម្នាក់នឹងជំទាស់ខ្ញុំថា TCP មាន 16-bit checksum ដូច្នេះការខូចទិន្នន័យកើតឡើង។ ល្អណាស់ ប៉ុន្តែយើងពិតជាមានពិធីការគ្រីបគ្រីបដែលមានសញ្ញាហាសវែងជាង 16 បៃ កំហុសទាំងអស់នេះ - និងច្រើនជាងនេះទៅទៀត - នឹងត្រូវបានចាប់បានដោយភាពមិនស៊ីគ្នា SHA នៅកម្រិតខ្ពស់។ មិនមានចំណុចណាមួយនៅក្នុង CRC32 នៅលើនេះទេ។

ចូរយើងប្រៀបធៀប Abridged ដែលក្នុងនោះមួយបៃនៃប្រវែងអាចធ្វើទៅបានជាមួយនឹងកម្រិតមធ្យម ដែលបង្ហាញអំពីភាពត្រឹមត្រូវ "ក្នុងករណីដែលត្រូវការការតម្រឹមទិន្នន័យ 4-byte" ដែលជាការសមហេតុសមផលណាស់។ អ្វី​ដែល​គេ​ជឿ​ថា​អ្នក​សរសេរ​កម្មវិធី Telegram គឺ​អសមត្ថភាព​ខ្លាំង​ណាស់​ដែល​ពួកគេ​មិន​អាច​អាន​ទិន្នន័យ​ពី​រន្ធ​ចូល​ទៅ​ក្នុង​សតិបណ្ដោះ​អាសន្ន​ដែល​បាន​តម្រឹម? អ្នកនៅតែត្រូវធ្វើដូច្នេះ ពីព្រោះការអានអាចត្រឡប់អ្នកនូវចំនួនបៃណាមួយ (ហើយក៏មានម៉ាស៊ីនមេប្រូកស៊ី ឧទាហរណ៍...)។ ឬម៉្យាងវិញទៀត ហេតុអ្វីបានជាប្លុក Abridged ប្រសិនបើយើងនឹងនៅតែមានបន្ទះធំនៅលើកំពូល 16 បៃ - រក្សាទុក 3 បៃ иногда ?

មនុស្សម្នាក់ទទួលបានការចាប់អារម្មណ៍ថា Nikolai Durov ពិតជាចូលចិត្តបង្កើតកង់ឡើងវិញ រួមទាំងពិធីការបណ្តាញ ដោយគ្មានតម្រូវការជាក់ស្តែងណាមួយឡើយ។

ជម្រើសដឹកជញ្ជូនផ្សេងទៀត រួមទាំង។ គេហទំព័រ និង MTProxy យើងនឹងមិនពិចារណាឥឡូវនេះទេ ប្រហែលជានៅក្នុងប្រកាសមួយផ្សេងទៀត ប្រសិនបើមានសំណើ។ អំពី MTProxy ដូចគ្នានេះ អនុញ្ញាតឱ្យយើងចងចាំឥឡូវនេះថា ភ្លាមៗបន្ទាប់ពីការចេញផ្សាយរបស់វានៅឆ្នាំ 2018 អ្នកផ្តល់សេវាបានរៀនយ៉ាងឆាប់រហ័សដើម្បីទប់ស្កាត់វា ដែលមានបំណងសម្រាប់ ឆ្លងកាត់ការទប់ស្កាត់, លើ ទំហំកញ្ចប់! ហើយការពិតដែលថាម៉ាស៊ីនមេ MTProxy សរសេរ (ម្តងទៀតដោយ Waltman) នៅក្នុង C ត្រូវបានចងភ្ជាប់ខ្លាំងពេកទៅនឹងជាក់លាក់នៃលីនុច ទោះបីជាវាមិនត្រូវបានទាមទារទាល់តែសោះ (Phil Kulin នឹងបញ្ជាក់) ហើយថាម៉ាស៊ីនមេស្រដៀងគ្នានៅក្នុង Go ឬ Node.js នឹង សមនឹងបន្ទាត់តិចជាងមួយរយ។

ប៉ុន្តែយើងនឹងធ្វើការសន្និដ្ឋានអំពីអក្ខរកម្មបច្ចេកទេសរបស់មនុស្សទាំងនេះនៅចុងបញ្ចប់នៃផ្នែក បន្ទាប់ពីពិចារណាលើបញ្ហាផ្សេងៗទៀត។ សម្រាប់ពេលនេះ សូមបន្តទៅ OSI ស្រទាប់ទី 5 វគ្គ - ដែលពួកគេបានដាក់សម័យ MTProto ។

គ្រាប់ចុច សារ វគ្គ Diffie-Hellman

ពួកគេដាក់វានៅទីនោះមិនត្រឹមត្រូវទាំងស្រុង... សម័យមួយមិនមែនជាសម័យដូចគ្នាដែលអាចមើលឃើញនៅក្នុងចំណុចប្រទាក់ក្រោម វគ្គសកម្ម។ ប៉ុន្តែតាមលំដាប់។

ការរិះគន់លើពិធីសារ និងវិធីសាស្រ្តរៀបចំរបស់ Telegram ។ ផ្នែកទី 1 បច្ចេកទេស៖ បទពិសោធន៍នៃការសរសេរអតិថិជនពីដំបូង - TL, MT

ដូច្នេះយើងបានទទួលខ្សែអក្សរបៃនៃប្រវែងដែលគេស្គាល់ពីស្រទាប់ដឹកជញ្ជូន។ នេះ​គឺ​ជា​សារ​ដែល​បាន​អ៊ិនគ្រីប ឬ​អត្ថបទ​ធម្មតា ប្រសិនបើ​យើង​នៅ​តែ​ស្ថិត​នៅ​ក្នុង​ដំណាក់​កាល​កិច្ច​ព្រម​ព្រៀង​សំខាន់ ហើយ​ពិត​ជា​កំពុង​ធ្វើ​វា​មែន។ តើគំនិតមួយណាដែលហៅថា "គន្លឹះ" ដែលយើងកំពុងនិយាយអំពី? សូមបញ្ជាក់បញ្ហានេះសម្រាប់ក្រុម Telegram ខ្លួនឯង (ខ្ញុំសុំទោសចំពោះការបកប្រែឯកសារផ្ទាល់ខ្លួនរបស់ខ្ញុំពីភាសាអង់គ្លេសដោយខួរក្បាលហត់នឿយនៅម៉ោង 4 ព្រឹក វាកាន់តែងាយស្រួលក្នុងការទុកឃ្លាមួយចំនួនដូចដែលពួកគេមាន)៖

មានអង្គភាពពីរហៅថា សម័យ - មួយនៅក្នុង UI របស់អតិថិជនផ្លូវការនៅក្រោម "វគ្គបច្ចុប្បន្ន" ដែលវគ្គនីមួយៗត្រូវគ្នាទៅនឹងឧបករណ៍ / OS ទាំងមូល។
ទីពីរ - វគ្គ MTProtoដែលមានលេខលំដាប់នៃសារ (ក្នុងន័យកម្រិតទាប) នៅក្នុងវា និងមួយណា អាចមានរយៈពេលរវាងការតភ្ជាប់ TCP ផ្សេងគ្នា។ វគ្គ MTProto ជាច្រើនអាចត្រូវបានដំឡើងក្នុងពេលតែមួយ ជាឧទាហរណ៍ ដើម្បីបង្កើនល្បឿនការទាញយកឯកសារ។

រវាងទាំងពីរនេះ។ វគ្គ មានគំនិតមួយ។ ការអនុញ្ញាត. នៅក្នុងករណី degenerate យើងអាចនិយាយបានថា សម័យ UI គឺដូចគ្នានឹង ការអនុញ្ញាតប៉ុន្តែ alas អ្វីគ្រប់យ៉ាងគឺស្មុគស្មាញ។ តោះមើល៖

  • អ្នកប្រើប្រាស់នៅលើឧបករណ៍ថ្មីបង្កើតដំបូង auth_key ហើយកំណត់វាទៅក្នុងគណនី ឧទាហរណ៍តាមរយៈសារ SMS - នោះហើយជាមូលហេតុ ការអនុញ្ញាត
  • វាបានកើតឡើងនៅខាងក្នុងទីមួយ វគ្គ MTProto, ដែល​មាន session_id នៅខាងក្នុងខ្លួនអ្នក។
  • នៅជំហាននេះការបញ្ចូលគ្នា ការអនុញ្ញាត и session_id អាចត្រូវបានគេហៅថា អាជ្ញាធរមាន - ពាក្យនេះលេចឡើងក្នុងឯកសារ និងកូដរបស់អតិថិជនមួយចំនួន
  • បន្ទាប់មកអតិថិជនអាចបើក ជាច្រើន វគ្គ MTProto នៅក្រោមដូចគ្នា។ auth_key - ទៅ DC ដូចគ្នា។
  • បន្ទាប់មកថ្ងៃណាមួយ អតិថិជននឹងត្រូវស្នើសុំឯកសារពី DC ផ្សេងទៀត។ - ហើយសម្រាប់ DC នេះ មួយថ្មីនឹងត្រូវបានបង្កើត auth_key !
  • ដើម្បីជូនដំណឹងដល់ប្រព័ន្ធថាវាមិនមែនជាអ្នកប្រើប្រាស់ថ្មីដែលកំពុងចុះឈ្មោះទេ ប៉ុន្តែដូចគ្នា។ ការអនុញ្ញាត (សម័យ UI) អតិថិជនប្រើការហៅ API auth.exportAuthorization នៅផ្ទះ DC auth.importAuthorization នៅក្នុង DC ថ្មី។
  • អ្វីគ្រប់យ៉ាងគឺដូចគ្នា, ជាច្រើនអាចបើកចំហ វគ្គ MTProto (នីមួយៗមានរបស់ខ្លួន។ session_id) ទៅ DC ថ្មីនេះក្រោម របស់គាត់ auth_key.
  • ទីបំផុត អតិថិជនអាចចង់បានការសម្ងាត់ឆ្ពោះទៅមុខដ៏ល្អឥតខ្ចោះ។ រាល់ auth_key គឺ អចិន្ត្រៃយ៍ គ្រាប់ចុច - ក្នុងមួយ DC - ហើយអតិថិជនអាចហៅបាន។ auth.bindTempAuthKey សម្រាប់ការប្រើប្រាស់ បណ្តោះអាសន្ន auth_key - ហើយម្តងទៀតមានតែមួយ។ temp_auth_key សម្រាប់ DC, ជារឿងធម្មតាសម្រាប់ទាំងអស់គ្នា វគ្គ MTProto ទៅ DC នេះ។

បាន​កត់​សម្គាល់​ឃើញ​ថា អំបិល (និងអំបិលនាពេលអនាគត) ក៏មានផងដែរ។ auth_key ទាំងនោះ។ ចែករំលែករវាងមនុស្សគ្រប់គ្នា វគ្គ MTProto ទៅ DC ដូចគ្នា។

តើ "រវាងការតភ្ជាប់ TCP ផ្សេងគ្នា" មានន័យយ៉ាងណា? ដូច្នេះមានន័យថា អ្វីមួយដូចជា ខូគីអនុញ្ញាតនៅលើគេហទំព័រ - វានៅតែបន្ត (រស់រានមានជីវិត) ការតភ្ជាប់ TCP ជាច្រើនទៅកាន់ម៉ាស៊ីនមេដែលបានផ្តល់ឱ្យ ប៉ុន្តែថ្ងៃមួយវាមិនល្អ។ មិនដូច HTTP ទេ នៅក្នុងសារ MTProto ក្នុងវគ្គមួយត្រូវបានបញ្ចូលលេខរៀងៗខ្លួន និងបញ្ជាក់ ប្រសិនបើពួកគេបានចូលទៅក្នុងផ្លូវរូងក្រោមដី ការតភ្ជាប់ត្រូវបានខូច - បន្ទាប់ពីបង្កើតការភ្ជាប់ថ្មី ម៉ាស៊ីនមេនឹងផ្ញើអ្វីៗគ្រប់យ៉ាងក្នុងវគ្គនេះដោយចិត្តល្អ ដែលវាមិនបានបញ្ជូនពីមុនមក។ ការតភ្ជាប់ TCP ។

យ៉ាង​ណា​មិញ ព័ត៌មាន​ខាង​លើ​ត្រូវ​បាន​សង្ខេប​ក្រោយ​ការ​ស៊ើប​អង្កេត​ជា​ច្រើន​ខែ។ ក្នុងពេលនេះ តើយើងកំពុងអនុវត្តអតិថិជនរបស់យើងតាំងពីដំបូងឬ? - តោះត្រឡប់ទៅដើមវិញ។

ដូច្នេះសូមបង្កើត auth_key នៅលើ កំណែ Diffie-Hellman ពី Telegram. តោះព្យាយាមស្វែងយល់ពីឯកសារ...

Vasily, [19.06.18 20:05] data_with_hash := SHA1(data) + data + (bytes ចៃដន្យណាមួយ); ដូច្នេះប្រវែងស្មើនឹង 255 បៃ;
encrypted_data := RSA(data_with_hash, server_public_key); លេខវែង 255 បៃ (big endian) ត្រូវបានលើកឡើងទៅថាមពលចាំបាច់លើម៉ូឌុលដែលត្រូវការ ហើយលទ្ធផលត្រូវបានរក្សាទុកជាលេខ 256 បៃ។

ពួកគេមានសារធាតុ DH មួយចំនួន

មើលទៅមិនដូច DH របស់មនុស្សដែលមានសុខភាពល្អទេ។
មិនមានសោសាធារណៈពីរនៅក្នុង dx ទេ។

ជាការប្រសើរណាស់, នៅទីបញ្ចប់នេះត្រូវបានតម្រៀបចេញ, ប៉ុន្តែនៅសល់មួយ - ភស្តុតាងនៃការងារត្រូវបានធ្វើឡើងដោយអតិថិជនថាគាត់អាចរាប់លេខ។ ប្រភេទនៃការការពារប្រឆាំងនឹងការវាយប្រហារ DoS ។ ហើយគ្រាប់ចុច RSA ត្រូវបានប្រើតែម្តងគត់ក្នុងទិសដៅតែមួយ ជាសំខាន់សម្រាប់ការអ៊ិនគ្រីប new_nonce. ប៉ុន្តែខណៈពេលដែលប្រតិបត្តិការហាក់ដូចជាសាមញ្ញនេះនឹងទទួលបានជោគជ័យ តើអ្នកនឹងត្រូវប្រឈមមុខនឹងអ្វី?

Vasily, [20.06.18/00/26 XNUMX:XNUMX] ខ្ញុំមិនទាន់បានទទួលសំណើររបស់ appid នៅឡើយទេ

ខ្ញុំបានផ្ញើសំណើនេះទៅ DH

ហើយនៅក្នុងការចតដឹកជញ្ជូន វានិយាយថាវាអាចឆ្លើយតបជាមួយនឹង 4 bytes នៃលេខកូដកំហុស។ អស់ហើយ

គាត់បានប្រាប់ខ្ញុំថា -404 ដូច្នេះតើអ្វីទៅ?

ដូច្នេះខ្ញុំបានប្រាប់គាត់ថា "ចាប់ bullshit របស់អ្នកដែលបានអ៊ិនគ្រីបដោយប្រើសោម៉ាស៊ីនមេជាមួយនឹងស្នាមម្រាមដៃដូចនេះខ្ញុំចង់បាន DH" ហើយវាបានឆ្លើយតបដោយឆោតល្ងង់ 404

តើអ្នកគិតយ៉ាងណាចំពោះការឆ្លើយតបរបស់ម៉ាស៊ីនមេនេះ? អ្វី​ដែល​ត្រូវធ្វើ? គ្មាននរណាម្នាក់សួរទេ (ប៉ុន្តែបន្ថែមលើវានៅក្នុងផ្នែកទីពីរ) ។

នៅទីនេះចំណាប់អារម្មណ៍ទាំងអស់ត្រូវបានធ្វើនៅលើចត

ខ្ញុំ​គ្មាន​អ្វី​ត្រូវ​ធ្វើ​ទៀត​ទេ ខ្ញុំ​គ្រាន់​តែ​ស្រមៃ​ចង់​បំប្លែង​លេខ​ទៅ​មុខ

លេខ 32 ប៊ីតពីរ។ ខ្ញុំបានខ្ចប់វាដូចអ្នកផ្សេងដែរ។

ប៉ុន្តែ​អត់​ទេ ទាំង​ពីរ​នេះ​ត្រូវ​បន្ថែម​ទៅ​ក្នុង​ជួរ​មុន​ជា BE

Vadim Goncharov, [20.06.18 15:49] ហើយដោយសារតែ 404 នេះ?

Vasily, [20.06.18 15:49] បាទ!

Vadim Goncharov, [20.06.18 15:50] ដូច្នេះខ្ញុំមិនយល់ពីអ្វីដែលគាត់អាច "រកមិនឃើញ"

Vasily, [20.06.18 15:50] ប្រមាណ

ខ្ញុំ​មិន​អាច​រក​ឃើញ​ការ​ខូច​ខាត​បែប​នេះ​ទៅ​ក្នុង​កត្តា​ចម្បង​ទេ)

យើង​មិន​បាន​គ្រប់​គ្រង​ការ​រាយការណ៍​កំហុស​ផង​ដែរ។

Vasily, [20.06.18 20:18] អូ វាក៏មាន MD5 ផងដែរ។ សញ្ញាបីផ្សេងគ្នារួចទៅហើយ

ស្នាមម្រាមដៃសំខាន់ត្រូវបានគណនាដូចខាងក្រោមៈ

digest = md5(key + iv)
fingerprint = substr(digest, 0, 4) XOR substr(digest, 4, 4)

SHA1 និង sha2

ដូច្នេះសូមដាក់វា auth_key យើងទទួលបានទំហំ 2048 ប៊ីតដោយប្រើ Diffie-Hellman ។ មាន​អ្វី​បន្ទាប់? បន្ទាប់យើងរកឃើញថា 1024 ប៊ីតទាបនៃគន្លឹះនេះមិនត្រូវបានប្រើតាមវិធីណាក៏ដោយ... ប៉ុន្តែសូមគិតអំពីវាសម្រាប់ពេលនេះ។ នៅជំហាននេះ យើងមានការចែករំលែកសម្ងាត់ជាមួយម៉ាស៊ីនមេ។ analogue នៃវគ្គ TLS ត្រូវបានបង្កើតឡើង ដែលជានីតិវិធីថ្លៃណាស់។ ប៉ុន្តែ​ម៉ាស៊ីន​មេ​នៅ​តែ​មិន​ដឹង​ថា​យើង​ជា​នរណា! មិនទាន់ទេ តាមពិតទៅ។ ការអនុញ្ញាត. ទាំងនោះ។ ប្រសិនបើអ្នកគិតក្នុងន័យនៃ "ពាក្យសម្ងាត់ចូល" ដូចដែលអ្នកធ្លាប់បានធ្វើនៅក្នុង ICQ ឬយ៉ាងហោចណាស់ "សោចូល" ដូចជានៅក្នុង SSH (ឧទាហរណ៍នៅលើ gitlab/github មួយចំនួន)។ យើងទទួលបានអនាមិកមួយ។ ចុះប្រសិនបើម៉ាស៊ីនមេប្រាប់យើងថា "លេខទូរស័ព្ទទាំងនេះត្រូវបានផ្តល់សេវាដោយ DC មួយផ្សេងទៀត"? ឬសូម្បីតែ "លេខទូរស័ព្ទរបស់អ្នកត្រូវបានហាមឃាត់"? ល្អបំផុតដែលយើងអាចធ្វើបានគឺរក្សាគន្លឹះដោយសង្ឃឹមថាវានឹងមានប្រយោជន៍ ហើយនឹងមិនរលួយនៅពេលនោះ។

ដោយវិធីនេះ យើង "ទទួលបាន" វាជាមួយនឹងការកក់ទុក។ ឧទាហរណ៍ តើ​យើង​ជឿជាក់​លើ​ម៉ាស៊ីន​មេ​ឬ? ចុះបើក្លែងក្លាយ? ការត្រួតពិនិត្យការគ្រីបនឹងត្រូវបានទាមទារ៖

Vasily, [21.06.18 17:53] ពួកគេផ្តល់ជូនអតិថិជនទូរស័ព្ទដើម្បីពិនិត្យមើលលេខ 2kbit សម្រាប់ primality%)

ប៉ុន្តែវាមិនច្បាស់ទាល់តែសោះ nafeijoa

Vasily, [21.06.18 18:02] ឯកសារមិនបាននិយាយថាអ្វីដែលត្រូវធ្វើប្រសិនបើវាមិនសាមញ្ញ

មិនបាននិយាយ។ ចាំ​មើល​ថា​តើ​កម្មវិធី​ Android ផ្លូវការ​ធ្វើ​អ្វី​ក្នុង​ករណី​នេះ? ក នោះជាអ្វី (ហើយបាទ ឯកសារទាំងមូលគួរឱ្យចាប់អារម្មណ៍) - ដូចដែលពួកគេនិយាយ ខ្ញុំនឹងទុកវានៅទីនេះ៖

278     static const char *goodPrime = "c71caeb9c6b1c9048e6c522f70f13f73980d40238e3e21c14934d037563d930f48198a0aa7c14058229493d22530f4dbfa336f6e0ac925139543aed44cce7c3720fd51f69458705ac68cd4fe6b6b13abdc9746512969328454f18faf8c595f642477fe96bb2a941d5bcd1d4ac8cc49880708fa9b378e3c4f3a9060bee67cf9a4a4a695811051907e162753b56b0f6b410dba74d8a84b2a14b3144e0ef1284754fd17ed950d5965b4b9dd46582db1178d169c6bc465b0d6ff9ca3928fef5b9ae4e418fc15e83ebea0f87fa9ff5eed70050ded2849f47bf959d956850ce929851f0d8115f635b105ee2e4e15d04b2454bf6f4fadf034b10403119cd8e3b92fcc5b";
279   if (!strcasecmp(prime, goodPrime)) {

ទេ ពិតណាស់វានៅតែមាន ខ្លះ មាន​ការ​ធ្វើ​តេ​ស្ត​សម្រាប់​បឋម​នៃ​ចំនួន​មួយ ប៉ុន្តែ​ដោយ​ផ្ទាល់ ខ្ញុំ​លែង​មាន​ចំណេះ​ដឹង​គណិតវិទ្យា​គ្រប់គ្រាន់​ហើយ​។

មិនអីទេ យើងទទួលបានសោមេ។ ដើម្បីចូល, i.e. ផ្ញើសំណើ អ្នកត្រូវអនុវត្តការអ៊ិនគ្រីបបន្ថែមទៀតដោយប្រើ AES ។

សោសារត្រូវបានកំណត់ថាជា 128 ប៊ីតកណ្តាលនៃ SHA256 នៃតួសារ (រួមទាំងវគ្គ លេខសម្គាល់សារ។

Vasily, [22.06.18 14:08] Average, bitch, bits

បានទទួល auth_key. ទាំងអស់។ លើសពីពួកគេ ... វាមិនច្បាស់ពីឯកសារទេ។ មានអារម្មណ៍ដោយឥតគិតថ្លៃដើម្បីសិក្សាកូដប្រភពបើកចំហ។

ចំណាំថា MTProto 2.0 ទាមទារពី 12 ទៅ 1024 បៃនៃ padding នៅតែស្ថិតក្រោមលក្ខខណ្ឌដែលប្រវែងសារលទ្ធផលត្រូវបានបែងចែកដោយ 16 បៃ។

ដូច្នេះ​តើ​អ្នក​គួរ​បន្ថែម​ទ្រនាប់​ប៉ុន្មាន?

ហើយបាទ ក៏មាន 404 ក្នុងករណីមានកំហុសដែរ។

ប្រសិនបើអ្នកណាម្នាក់បានសិក្សាដោយប្រុងប្រយ័ត្ននូវដ្យាក្រាម និងអត្ថបទនៃឯកសារនោះ ពួកគេបានកត់សម្គាល់ថាមិនមាន MAC នៅទីនោះទេ។ ហើយ AES ត្រូវបានប្រើនៅក្នុងរបៀប IGE ជាក់លាក់មួយ ដែលមិនត្រូវបានប្រើនៅកន្លែងផ្សេង។ ជាការពិតណាស់ ពួកគេសរសេរអំពីរឿងនេះនៅក្នុង FAQ របស់ពួកគេ... នៅទីនេះ ដូចជា សោសារខ្លួនវាគឺជាសញ្ញា SHA នៃទិន្នន័យដែលបានឌិគ្រីប ដែលប្រើដើម្បីពិនិត្យមើលភាពត្រឹមត្រូវ ហើយក្នុងករណីមានភាពមិនស៊ីគ្នា ឯកសារសម្រាប់ហេតុផលមួយចំនួន ណែនាំដោយស្ងៀមស្ងាត់មិនអើពើនឹងពួកគេ (ប៉ុន្តែចុះយ៉ាងណាចំពោះសុវត្ថិភាព ចុះបើពួកគេបំបែកពួកយើង?)

ខ្ញុំមិនមែនជាអ្នកសរសេរកូដទេ ប្រហែលជាមិនមានអ្វីខុសជាមួយរបៀបនេះទេ ក្នុងករណីនេះ តាមទស្សនៈទ្រឹស្តី។ ប៉ុន្តែខ្ញុំអាចដាក់ឈ្មោះបញ្ហាជាក់ស្តែងបានយ៉ាងច្បាស់ ដោយប្រើ Telegram Desktop ជាឧទាហរណ៍។ វាអ៊ិនគ្រីបឃ្លាំងសម្ងាត់មូលដ្ឋាន (D877F783D5D3EF8C ទាំងអស់នេះ) តាមរបៀបដូចគ្នានឹងសារនៅក្នុង MTProto (សម្រាប់តែករណីនេះកំណែ 1.0) ពោលគឺឧ។ ទីមួយ គ្រាប់ចុចសារ បន្ទាប់មកទិន្នន័យខ្លួនវា (និងកន្លែងណាមួយក្រៅពីមេធំ auth_key 256 បៃដោយគ្មាន msg_key ឥតប្រយោជន៍) ។ ដូច្នេះបញ្ហានឹងក្លាយទៅជាគួរឱ្យកត់សម្គាល់នៅលើឯកសារធំ។ មានន័យថា អ្នកត្រូវរក្សាច្បាប់ចម្លងទិន្នន័យពីរ - អ៊ិនគ្រីប និងឌិគ្រីប។ ហើយប្រសិនបើមានមេកាបៃ ឬវីដេអូស្ទ្រីម ឧទាហរណ៍?.. គ្រោងការណ៍បុរាណជាមួយ MAC បន្ទាប់ពីអក្សរសម្ងាត់អនុញ្ញាតឱ្យអ្នកអានវាស្ទ្រីម បញ្ជូនវាភ្លាមៗ។ ប៉ុន្តែជាមួយ MTProto អ្នកនឹងត្រូវ ដំបូង។ អ៊ិនគ្រីប ឬឌិគ្រីបសារទាំងមូល បន្ទាប់មកផ្ទេរវាទៅបណ្តាញ ឬទៅថាស។ ដូច្នេះនៅក្នុងកំណែចុងក្រោយបំផុតនៃ Telegram Desktop នៅក្នុងឃ្លាំងសម្ងាត់នៅក្នុង user_data ទម្រង់ផ្សេងទៀតក៏ត្រូវបានគេប្រើផងដែរ - ជាមួយ AES នៅក្នុងរបៀប CTR ។

Vasily, [21.06.18 01:27] អូ ខ្ញុំបានរកឃើញថា IGE ជាអ្វី៖ IGE គឺជាការប៉ុនប៉ងលើកដំបូងនៅ "របៀបការផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវ" ដែលដើមឡើយសម្រាប់ Kerberos ។ វា​ជា​ការ​ប៉ុនប៉ង​ដែល​បរាជ័យ (វា​មិន​ផ្តល់​នូវ​ការ​ការពារ​សុចរិតភាព​ទេ) ហើយ​ត្រូវ​តែ​យក​ចេញ។ នោះគឺជាការចាប់ផ្តើមនៃដំណើរស្វែងរករយៈពេល 20 ឆ្នាំសម្រាប់របៀបអ៊ិនគ្រីបដែលផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវដែលដំណើរការ ដែលថ្មីៗនេះបានឈានដល់របៀបដូចជា OCB និង GCM ។

ហើយឥឡូវនេះអាគុយម៉ង់ពីខាងរទេះ:

ក្រុមដែលនៅពីក្រោយ Telegram ដឹកនាំដោយ Nikolai Durov មានម្ចាស់ជើងឯក ACM ចំនួន 6 នាក់ ដែលពាក់កណ្តាលនៃពួកគេគឺ Ph.Ds ផ្នែកគណិតវិទ្យា។ វា​ត្រូវ​ចំណាយ​ពេល​ប្រហែល​ពីរ​ឆ្នាំ​ដើម្បី​ដាក់​ចេញ​កំណែ​បច្ចុប្បន្ន​របស់ MTProto។

ពិតជា​កំប្លែង​មែន។ ពីរឆ្នាំនៅកម្រិតទាប

ឬអ្នកគ្រាន់តែអាចយក tls

មិនអីទេ ចូរនិយាយថាយើងបានធ្វើការអ៊ិនគ្រីប និងចំណុចសំខាន់ៗផ្សេងទៀត។ តើទីបំផុតវាអាចទៅរួចទេក្នុងការផ្ញើសំណើដែលបានដាក់ជាសៀរៀលក្នុង TL និងធ្វើឱ្យការឆ្លើយតបមិនប្រក្រតី? ដូច្នេះតើអ្នកគួរផ្ញើអ្វី និងរបៀបណា? នៅទីនេះឧបមាថាវិធីសាស្រ្ត initConnectionប្រហែលជានេះជាវា?

Vasily, [25.06.18 18:46] ចាប់ផ្តើមការតភ្ជាប់ និងរក្សាទុកព័ត៌មាននៅលើឧបករណ៍ និងកម្មវិធីរបស់អ្នកប្រើប្រាស់។

វាទទួលយក app_id, device_model, system_version, app_version និង lang_code ។

និងសំណួរមួយចំនួន

ឯកសារដូចរាល់ដង។ មានអារម្មណ៍សេរីដើម្បីសិក្សាប្រភពបើកចំហ

ប្រសិនបើអ្វីៗមានភាពច្បាស់លាស់ជាមួយ invokeWithLayer តើមានអ្វីខុសនៅទីនេះ? វាប្រែចេញ ឧបមាថាយើងមាន - អតិថិជនមានអ្វីដែលត្រូវសួរម៉ាស៊ីនមេរួចហើយ - មានសំណើដែលយើងចង់ផ្ញើ៖

Vasily, [25.06.18 19:13] វិនិច្ឆ័យដោយលេខកូដ ការហៅដំបូងត្រូវបានរុំនៅក្នុង crap នេះហើយ crap ខ្លួនវាត្រូវបានរុំដោយ invokewithlayer

ហេតុអ្វីបានជាមិនអាច initConnection ជាការហៅដាច់ដោយឡែក ប៉ុន្តែត្រូវតែជា wrapper? បាទ ដូចដែលវាបានប្រែក្លាយ វាត្រូវតែធ្វើរាល់ពេលនៅដើមវគ្គនីមួយៗ ហើយមិនមែនតែម្តងទេ ដូចជាគន្លឹះសំខាន់។ តែ! វា​មិន​អាច​ត្រូវ​បាន​ហៅ​ដោយ​អ្នក​ប្រើ​ដែល​គ្មាន​ការ​អនុញ្ញាត​! ឥឡូវ​យើង​បាន​ឈាន​ដល់​ដំណាក់​កាល​ដែល​វា​អាច​អនុវត្ត​បាន។ មួយ​នេះ ទំព័រឯកសារ - ហើយវាប្រាប់យើងថា...

មានតែផ្នែកតូចមួយនៃវិធីសាស្ត្រ API ប៉ុណ្ណោះដែលមានសម្រាប់អ្នកប្រើប្រាស់ដែលគ្មានការអនុញ្ញាត៖

  • auth.sendCode
  • auth.resendCode
  • account.getPassword
  • auth.checkPassword
  • auth.checkPhone
  • auth.ចុះឈ្មោះ
  • auth.signIn
  • auth.import ការអនុញ្ញាត
  • help.getConfig
  • help.getNearestDc
  • help.getAppUpdate
  • help.getCdnConfig
  • langpack.getLangPack
  • langpack.getStrings
  • langpack.getDifference
  • langpack.getLanguages
  • langpack.getLanguage

ដំបូងបំផុតនៃពួកគេ, auth.sendCodeហើយមានសំណើដំបូងដែលគួរឱ្យស្រឡាញ់ដែលយើងផ្ញើ api_id និង api_hash ហើយបន្ទាប់ពីនោះយើងទទួលបានសារ SMS ជាមួយលេខកូដ។ ហើយប្រសិនបើយើងនៅក្នុង DC ខុស (ឧទាហរណ៍លេខទូរស័ព្ទនៅក្នុងប្រទេសនេះត្រូវបានបម្រើដោយមួយផ្សេងទៀត) នោះយើងនឹងទទួលបានកំហុសជាមួយនឹងចំនួននៃ DC ដែលចង់បាន។ ដើម្បីស្វែងយល់ថាតើអាសយដ្ឋាន IP មួយណាតាមលេខ DC ដែលអ្នកត្រូវការភ្ជាប់ សូមជួយពួកយើង help.getConfig. ក្នុងពេលមួយមានត្រឹមតែ 5 ប៉ុណ្ណោះ ប៉ុន្តែបន្ទាប់ពីព្រឹត្តិការណ៍ល្បីៗក្នុងឆ្នាំ 2018 ចំនួននេះបានកើនឡើងយ៉ាងខ្លាំង។

ឥឡូវនេះ សូមចងចាំថា យើងបានឈានដល់ដំណាក់កាលនេះនៅលើម៉ាស៊ីនមេដោយមិនបញ្ចេញឈ្មោះ។ គ្រាន់​តែ​ទទួល​បាន​អាសយដ្ឋាន IP មិន​ថ្លៃ​ពេក​ទេ? ហេតុអ្វីមិនធ្វើដូចនេះ និងប្រតិបត្តិការផ្សេងទៀតនៅក្នុងផ្នែកដែលមិនបានអ៊ិនគ្រីបនៃ MTProto? ខ្ញុំឮការជំទាស់៖ "តើយើងអាចប្រាកដថាវាមិនមែនជា RKN ដែលនឹងឆ្លើយតបដោយអាសយដ្ឋានមិនពិតដោយរបៀបណា?" ចំពោះបញ្ហានេះយើងចងចាំថាជាទូទៅអតិថិជនផ្លូវការ គ្រាប់ចុច RSA ត្រូវបានបង្កប់, i.e. អ្នកគ្រាន់តែអាច សញ្ញា ព័ត៌មាននេះ។ តាមពិត នេះត្រូវបានធ្វើរួចហើយសម្រាប់ព័ត៌មានស្តីពីការឆ្លងកាត់ការទប់ស្កាត់ដែលអតិថិជនទទួលបានតាមរយៈបណ្តាញផ្សេងទៀត (តាមហេតុផល វាមិនអាចធ្វើបាននៅក្នុង MTProto ខ្លួនវាទេ អ្នកក៏ត្រូវដឹងពីកន្លែងដែលត្រូវភ្ជាប់ផងដែរ)។

យល់ព្រម។ នៅដំណាក់កាលនៃការអនុញ្ញាតរបស់អតិថិជននេះ យើងមិនទាន់មានការអនុញ្ញាត និងមិនទាន់បានចុះឈ្មោះកម្មវិធីរបស់យើងទេ។ យើងគ្រាន់តែចង់ឃើញនៅពេលនេះនូវអ្វីដែលម៉ាស៊ីនមេឆ្លើយតបទៅនឹងវិធីសាស្រ្តដែលមានសម្រាប់អ្នកប្រើប្រាស់ដែលគ្មានការអនុញ្ញាត។ ហើយនៅទីនេះ…

Vasily, [10.07.18 14:45] https://core.telegram.org/method/help.getConfig

config#7dae33e0 [...] = Config;
help.getConfig#c4f9186b = Config;

https://core.telegram.org/api/datacenter

config#232d5905 [...] = Config;
help.getConfig#c4f9186b = Config;

នៅក្នុងគ្រោងការណ៍ដំបូងមកទីពីរ

នៅក្នុងគ្រោងការណ៍ tdesktop តម្លៃទីបីគឺ

បាទ ចាប់តាំងពីពេលនោះមក ពិតណាស់ ឯកសារត្រូវបានធ្វើបច្ចុប្បន្នភាព។ ទោះបី​ជា​មិន​យូរ​ប៉ុន្មាន​វា​អាច​នឹង​ក្លាយ​ជា​មិន​ពាក់ព័ន្ធ​ម្តង​ទៀត​។ តើ​អ្នក​បង្កើត​ថ្មី​គួរ​ដឹង​យ៉ាង​ណា? ប្រហែលជាប្រសិនបើអ្នកចុះឈ្មោះកម្មវិធីរបស់អ្នក ពួកគេនឹងជូនដំណឹងដល់អ្នក? Vasily បានធ្វើរឿងនេះ ប៉ុន្តែ alas ពួកគេមិនបានផ្ញើអ្វីមកគាត់ទេ (ម្តងទៀត យើងនឹងនិយាយអំពីរឿងនេះនៅក្នុងផ្នែកទីពីរ)។

...អ្នកបានកត់សម្គាល់ឃើញថា យើងបានផ្លាស់ទីទៅ API រួចហើយ ពោលគឺឧ។ ទៅកម្រិតបន្ទាប់ ហើយខកខានអ្វីមួយនៅក្នុងប្រធានបទ MTProto? គ្មានការភ្ញាក់ផ្អើលទេ៖

Vasily, [28.06.18 02:04] Mm, ពួកគេកំពុងនិយាយតាមរយៈក្បួនដោះស្រាយមួយចំនួននៅលើ e2e

Mtproto កំណត់ក្បួនដោះស្រាយការអ៊ិនគ្រីប និងកូនសោសម្រាប់ដែនទាំងពីរ ក៏ដូចជារចនាសម្ព័ន្ធរុំបន្តិចបន្តួច

ប៉ុន្តែពួកគេតែងតែលាយកម្រិតផ្សេងគ្នានៃជង់ ដូច្នេះវាមិនតែងតែច្បាស់ថា mtproto បញ្ចប់នៅឯណា ហើយកម្រិតបន្ទាប់បានចាប់ផ្តើម

តើពួកគេលាយដោយរបៀបណា? ជាការប្រសើរណាស់, នេះគឺជាគន្លឹះបណ្តោះអាសន្នដូចគ្នាសម្រាប់ PFS ឧទាហរណ៍ (ដោយវិធីនេះ Telegram Desktop មិនអាចធ្វើបានទេ) ។ វាត្រូវបានប្រតិបត្តិដោយសំណើ API auth.bindTempAuthKey, i.e. ពីកម្រិតកំពូល។ ប៉ុន្តែនៅពេលជាមួយគ្នានេះវារំខានដល់ការអ៊ិនគ្រីបនៅកម្រិតទាប - បន្ទាប់ពីវាឧទាហរណ៍អ្នកត្រូវធ្វើវាម្តងទៀត initConnection ល នេះមិនមែនទេ។ គ្រាន់តែ សំណើធម្មតា។ អ្វី​ដែល​ពិសេស​នោះ​គឺ​ថា​អ្នក​អាច​មាន​កូនសោ​បណ្ដោះ​អាសន្ន​មួយ​ប៉ុណ្ណោះ​ក្នុង​មួយ DC ទោះ​បី​ជា​វាល auth_key_id នៅក្នុងសារនីមួយៗអនុញ្ញាតឱ្យអ្នកផ្លាស់ប្តូរសោយ៉ាងហោចណាស់គ្រប់សារ ហើយថាម៉ាស៊ីនមេមានសិទ្ធិ "ភ្លេច" សោបណ្តោះអាសន្ននៅពេលណាក៏បាន - ឯកសារមិនបាននិយាយថាអ្វីដែលត្រូវធ្វើក្នុងករណីនេះ ... អញ្ចឹងហេតុអ្វីបានជាអាច អ្នកមិនមានកូនសោច្រើនទេ ដូចនឹងសំណុំនៃអំបិលនាពេលអនាគត ហើយ?..

មានរឿងមួយចំនួនទៀតដែលគួរកត់សម្គាល់អំពីប្រធានបទ MTProto ។

សារ msg_id, msg_seqno, ការបញ្ជាក់, pings ក្នុងទិសដៅខុស និង idiosyncrasies ផ្សេងទៀត

ហេតុអ្វីបានជាអ្នកត្រូវការដឹងអំពីពួកគេ? ដោយសារតែពួកគេ "លេចធ្លាយ" ទៅកម្រិតខ្ពស់ហើយអ្នកត្រូវដឹងអំពីពួកគេនៅពេលធ្វើការជាមួយ API ។ ឧបមាថាយើងមិនចាប់អារម្មណ៍លើ msg_key កម្រិតទាបបានឌិគ្រីបគ្រប់យ៉ាងសម្រាប់យើង។ ប៉ុន្តែនៅខាងក្នុងទិន្នន័យដែលបានឌិគ្រីប យើងមានវាលខាងក្រោម (ក៏ប្រវែងនៃទិន្នន័យផងដែរ ដូច្នេះយើងដឹងថាកន្លែងណានៃទ្រនាប់ ប៉ុន្តែវាមិនសំខាន់ទេ)៖

  • អំបិល - int64
  • session_id - int64
  • message_id — int64
  • seq_no - int32

ចូរយើងរំលឹកអ្នកថាមានអំបិលតែមួយគត់សម្រាប់ DC ទាំងមូល។ ហេតុអ្វីដឹងអំពីនាង? មិន​មែន​ដោយ​សារ​តែ​មាន​ការ​ស្នើ​សុំ get_future_saltsដែលប្រាប់អ្នកថាចន្លោះពេលណាមួយនឹងមានសុពលភាព ប៉ុន្តែក៏ដោយសារតែប្រសិនបើអំបិលរបស់អ្នក "រលួយ" នោះសារ (សំណើ) នឹងបាត់ទៅវិញ។ ជាការពិតណាស់ ម៉ាស៊ីនមេនឹងរាយការណ៍អំបិលថ្មីដោយការចេញ new_session_created - ប៉ុន្តែជាមួយលេខចាស់ អ្នកនឹងត្រូវបញ្ជូនវាឡើងវិញជាឧទាហរណ៍។ ហើយបញ្ហានេះប៉ះពាល់ដល់ស្ថាបត្យកម្មកម្មវិធី។

ម៉ាស៊ីនមេត្រូវបានអនុញ្ញាតឱ្យទម្លាក់វគ្គទាំងអស់ ហើយឆ្លើយតបតាមរបៀបនេះសម្រាប់ហេតុផលជាច្រើន។ តាមពិត តើវគ្គ MTProto មកពីភាគីអតិថិជនជាអ្វី? នេះគឺជាលេខពីរ session_id и seq_no សារនៅក្នុងវគ្គនេះ។ ជាការប្រសើរណាស់, និងការតភ្ជាប់ TCP មូលដ្ឋាន, ជាការពិតណាស់។ ឧបមាថា អតិថិជនរបស់យើងនៅតែមិនដឹងពីរបៀបធ្វើកិច្ចការជាច្រើន គាត់បានផ្ដាច់ និងភ្ជាប់ឡើងវិញ។ ប្រសិនបើរឿងនេះកើតឡើងយ៉ាងឆាប់រហ័ស - វគ្គចាស់បានបន្តនៅក្នុងការតភ្ជាប់ TCP ថ្មី បង្កើន seq_no បន្ថែមទៀត។ ប្រសិនបើវាចំណាយពេលយូរ ម៉ាស៊ីនមេអាចលុបវាចោល ព្រោះនៅខាងវាក៏ជាជួរដែរ ដូចដែលយើងបានរកឃើញ។

តើវាគួរតែជាអ្វី seq_no? អូ នោះ​ជា​សំណួរ​ពិបាក​ណាស់។ ព្យាយាមយល់ដោយស្មោះត្រង់នូវអត្ថន័យ៖

សារទាក់ទងនឹងខ្លឹមសារ

សារដែលទាមទារការទទួលស្គាល់ច្បាស់លាស់។ ទាំងនេះរួមបញ្ចូលអ្នកប្រើប្រាស់ទាំងអស់ និងសារសេវាកម្មជាច្រើន ស្ទើរតែទាំងអស់លើកលែងតែកុងតឺន័រ និងការទទួលស្គាល់។

លេខលំដាប់សារ (msg_seqno)

លេខ 32 ប៊ីត ស្មើនឹងពីរដងនៃចំនួនសារ "ទាក់ទងនឹងមាតិកា" (ដែលទាមទារការទទួលស្គាល់ និងជាពិសេសអ្នកដែលមិនមែនជាកុងតឺន័រ) ដែលបង្កើតឡើងដោយអ្នកផ្ញើមុនសារនេះ ហើយត្រូវបានបង្កើនជាបន្តបន្ទាប់ដោយមួយ ប្រសិនបើសារបច្ចុប្បន្នជា សារទាក់ទងនឹងខ្លឹមសារ។ ធុងមួយតែងតែត្រូវបានបង្កើតបន្ទាប់ពីមាតិកាទាំងមូលរបស់វា; ដូច្នេះ លេខលំដាប់របស់វាធំជាង ឬស្មើនឹងលេខលំដាប់នៃសារដែលមាននៅក្នុងវា។

តើ​សៀក​ប្រភេទ​នេះ​មាន​ការ​កើន​ឡើង​ដោយ ១ ហើយ​បន្ទាប់​មក​មួយ​ទៀត​ដោយ ២?... ខ្ញុំ​សង្ស័យ​ថា​ពី​ដំបូង​ពួកគេ​មាន​ន័យ​ថា "តិចតួច​បំផុត​សម្រាប់ ACK សល់​គឺ​ជា​លេខ" ប៉ុន្តែ​លទ្ធផល​មិន​ដូច​គ្នា​ទេ - ជាពិសេសវាចេញមកអាចផ្ញើបាន។ ជាច្រើន ការបញ្ជាក់មានដូចគ្នា។ seq_no! យ៉ាងម៉េច? ជាឧទាហរណ៍ ម៉ាស៊ីនមេផ្ញើអ្វីមួយមកយើង ផ្ញើវា ហើយយើងខ្លួនឯងនៅស្ងៀម ដោយគ្រាន់តែឆ្លើយតបជាមួយនឹងសារសេវាកម្មដែលបញ្ជាក់ពីការទទួលសាររបស់វា។ ក្នុងករណីនេះ ការបញ្ជាក់ចេញរបស់យើងនឹងមានលេខចេញដូចគ្នា។ ប្រសិនបើអ្នកធ្លាប់ស្គាល់ TCP ហើយគិតថាវាស្តាប់ទៅដូចជាព្រៃ ប៉ុន្តែវាហាក់បីដូចជាមិនព្រៃផ្សៃទេ ព្រោះនៅក្នុង TCP seq_no មិនផ្លាស់ប្តូរទេប៉ុន្តែការបញ្ជាក់ទៅ seq_no នៅម្ខាងទៀត ខ្ញុំនឹងប្រញាប់ធ្វើឱ្យអ្នកខឹង។ ការបញ្ជាក់ត្រូវបានផ្តល់ជូននៅក្នុង MTProto НЕ នៅលើ seq_noដូចនៅក្នុង TCP ប៉ុន្តែដោយ msg_id !

តើ​នេះ​ជា​អ្វី msg_idសំខាន់បំផុតនៃវិស័យទាំងនេះ? ការកំណត់អត្តសញ្ញាណសារតែមួយគត់ ដូចដែលឈ្មោះបានបង្ហាញ។ វាត្រូវបានកំណត់ថាជាលេខ 64 ប៊ីត ដែលជាប៊ីតទាបបំផុតដែលម្តងទៀតមានវេទមន្ត "server-not-server" ហើយនៅសល់គឺជាត្រាពេលវេលាយូនីក រួមទាំងផ្នែកប្រភាគ ផ្លាស់ប្តូរ 32 ប៊ីតទៅខាងឆ្វេង។ ទាំងនោះ។ timestamp per se (ហើយសារដែលមានពេលវេលាខុសគ្នាខ្លាំងពេកនឹងត្រូវបានបដិសេធដោយម៉ាស៊ីនមេ)។ ពីនេះវាប្រែថាជាទូទៅនេះគឺជាឧបករណ៍កំណត់អត្តសញ្ញាណដែលមានលក្ខណៈសកលសម្រាប់អតិថិជន។ ដែលបានផ្តល់ឱ្យនោះ - ចូរយើងចងចាំ session_id - យើងមានការធានា៖ មិនស្ថិតក្រោមកាលៈទេសៈណាក៏ដោយ សារដែលមានន័យសម្រាប់វគ្គមួយត្រូវបានផ្ញើទៅសម័យផ្សេង. នោះគឺវាប្រែថាមានរួចហើយ បី កម្រិត - សម័យ, លេខសម័យ, លេខសម្គាល់សារ។ ហេតុអ្វីបានជាមានភាពស្មុគស្មាញបែបនេះ អាថ៌កំបាំងនេះគឺអស្ចារ្យណាស់។

ហើយដូច្នេះ, msg_id ត្រូវការសម្រាប់...

RPC: សំណើ, ការឆ្លើយតប, កំហុស។ ការបញ្ជាក់។

ដូចដែលអ្នកប្រហែលជាបានកត់សម្គាល់នោះ មិនមានប្រភេទ "បង្កើតសំណើរ RPC" ពិសេស ឬមុខងារណាមួយនៅក្នុងដ្យាក្រាមនោះទេ ទោះបីជាមានចម្លើយក៏ដោយ។ យ៉ាងណាមិញ យើងមានសារទាក់ទងនឹងខ្លឹមសារ! នោះគឺ ណាមួយ សារអាចជាសំណើមួយ! ឬមិនក្លាយជា។ យ៉ាងណាមិញ នៃគ្នា គឺ msg_id. ប៉ុន្តែមានចម្លើយ៖

rpc_result#f35c6d01 req_msg_id:long result:Object = RpcResult;

នេះគឺជាកន្លែងដែលវាត្រូវបានចង្អុលបង្ហាញថាសារមួយណាជាការឆ្លើយតប។ ដូច្នេះហើយ នៅកម្រិតកំពូលនៃ API អ្នកនឹងត្រូវចងចាំថាតើចំនួនសំណើរបស់អ្នកមានអ្វីខ្លះ - ខ្ញុំគិតថាវាមិនចាំបាច់ពន្យល់ថាការងារនេះគឺអសមកាលទេ ហើយវាអាចមានសំណើជាច្រើនដែលកំពុងដំណើរការក្នុងពេលតែមួយ។ ចម្លើយ​ដែល​អាច​ត្រូវ​បាន​ត្រឡប់​មក​វិញ​ក្នុង​លំដាប់​ណា​មួយ? ជាគោលការណ៍ ពីសារនេះ និងកំហុសដូចជាគ្មានកម្មករ ស្ថាបត្យកម្មនៅពីក្រោយនេះអាចតាមដានបាន៖ ម៉ាស៊ីនមេដែលរក្សាការភ្ជាប់ TCP ជាមួយអ្នកគឺជាឧបករណ៍តុល្យភាពផ្នែកខាងមុខ វាបញ្ជូនបន្តសំណើទៅកាន់ផ្នែកខាងក្រោយ ហើយប្រមូលពួកវាត្រឡប់មកវិញតាមរយៈ message_id. វាហាក់ដូចជាថាអ្វីគ្រប់យ៉ាងនៅទីនេះគឺច្បាស់លាស់ ឡូជីខល និងល្អ។

បាទ?.. ចុះបើគិតទៅ? យ៉ាងណាមិញ ការឆ្លើយតបរបស់ RPC ខ្លួនក៏មានវាលមួយផងដែរ។ msg_id! តើយើងត្រូវស្រែកទៅកាន់ម៉ាស៊ីនមេថា "អ្នកមិនឆ្លើយចម្លើយរបស់ខ្ញុំទេ!"? មែនហើយ តើមានការបញ្ជាក់អ្វីខ្លះ? អំពីទំព័រ សារអំពីសារ ប្រាប់យើងពីអ្វីដែលជាអ្វី

msgs_ack#62d6b459 msg_ids:Vector long = MsgsAck;

ហើយវាត្រូវធ្វើដោយភាគីនីមួយៗ។ ប៉ុន្តែមិនតែងតែ! ប្រសិនបើអ្នកបានទទួល RpcResult វាបម្រើជាការបញ្ជាក់។ នោះគឺម៉ាស៊ីនមេអាចឆ្លើយតបទៅនឹងសំណើរបស់អ្នកជាមួយ MsgsAck ដូចជា "ខ្ញុំបានទទួលវា" ។ RpcResult អាចឆ្លើយតបភ្លាមៗ។ វាអាចជាទាំងពីរ។

ហើយបាទ អ្នកនៅតែត្រូវឆ្លើយចំលើយ! ការបញ្ជាក់។ បើមិនដូច្នេះទេ ម៉ាស៊ីនមេនឹងចាត់ទុកថាវាមិនអាចចែកចាយបាន ហើយផ្ញើវាមកអ្នកម្តងទៀត។ សូម្បីតែបន្ទាប់ពីការភ្ជាប់ឡើងវិញ។ ប៉ុន្តែនៅទីនេះ ពិតណាស់បញ្ហានៃការអស់ពេលកើតឡើង។ សូមក្រឡេកមើលពួកគេបន្តិចក្រោយមក។

ក្នុងពេលនេះ សូមក្រឡេកមើលកំហុសការប្រតិបត្តិសំណួរដែលអាចកើតមាន។

rpc_error#2144ca19 error_code:int error_message:string = RpcError;

អូ នរណាម្នាក់នឹងលាន់មាត់ នេះជាទម្រង់មនុស្សធម៌ជាងនេះ - មានបន្ទាត់មួយ! ចំណាយពេលរបស់អ្នក។ នៅទីនេះ បញ្ជីនៃកំហុសប៉ុន្តែជាការពិតណាស់មិនពេញលេញទេ។ ពីវាយើងរៀនថាកូដគឺ អ្វីមួយដូចជា កំហុស HTTP (ជាការពិតណាស់ អត្ថន័យនៃការឆ្លើយតបមិនត្រូវបានគោរពទេ នៅកន្លែងខ្លះពួកគេត្រូវបានចែកចាយដោយចៃដន្យក្នុងចំណោមកូដ) ហើយបន្ទាត់មើលទៅដូច CAPITAL_LETTERS_AND_NUMBERS. ឧទាហរណ៍ PHONE_NUMBER_OCCUPIED ឬ FILE_PART_Х_MISSING។ មែនហើយ នោះគឺអ្នកនឹងនៅតែត្រូវការបន្ទាត់នេះ។ ញែក។ ឧទាហរណ៍។ FLOOD_WAIT_3600 នឹងមានន័យថាអ្នកត្រូវរង់ចាំមួយម៉ោង PHONE_MIGRATE_5ថាលេខទូរស័ព្ទដែលមានបុព្វបទនេះត្រូវតែចុះឈ្មោះនៅក្នុង DC ទី 5 ។ យើងមានភាសាប្រភេទមែនទេ? យើង​មិន​ត្រូវ​ការ​អាគុយម៉ង់​ពី​ខ្សែ​អក្សរ​ទេ អ្នក​ធម្មតា​នឹង​ធ្វើ​មិន​អី​ទេ។

ជាថ្មីម្តងទៀត នេះមិនមែននៅលើទំព័រសារសេវាកម្មទេ ប៉ុន្តែដូចធម្មតាជាមួយគម្រោងនេះ ព័ត៌មានអាចត្រូវបានរកឃើញ នៅលើទំព័រឯកសារផ្សេងទៀត។។ ឬ ទម្លាក់ការសង្ស័យ. ជាដំបូងមើល ការវាយ/ការបំពានស្រទាប់ - RpcError អាចត្រូវបានដាក់នៅក្នុង RpcResult. ហេតុអ្វីមិននៅខាងក្រៅ? តើ​យើង​មិន​បាន​យក​ចិត្ត​ទុក​ដាក់​នឹង​អ្វី?.. អាស្រ័យ​ហេតុ​នេះ តើ​ការ​ធានា​នោះ​នៅ​ឯណា? RpcError អាច​នឹង​មិន​ត្រូវ​បាន​បង្កប់​ក្នុង​ RpcResultប៉ុន្តែត្រូវបានដោយផ្ទាល់ ឬដាក់នៅក្នុងប្រភេទផ្សេងទៀត?.. ហើយប្រសិនបើវាមិនអាចធ្វើបាន ហេតុអ្វីបានជាវាមិននៅកម្រិតកំពូល ពោលគឺឧ។ វាបាត់ req_msg_id ? ..

ប៉ុន្តែសូមបន្តអំពីសារសេវាកម្ម។ អតិថិជនប្រហែលជាគិតថាម៉ាស៊ីនមេកំពុងគិតយូរហើយធ្វើសំណើដ៏អស្ចារ្យនេះ៖

rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;

មានចំលើយដែលអាចកើតមានចំនួនបីចំពោះសំណួរនេះ ដោយប្រសព្វគ្នាម្តងទៀតជាមួយនឹងយន្តការបញ្ជាក់ ដោយព្យាយាមយល់ពីអ្វីដែលពួកគេគួរតែជា (និងអ្វីដែលបញ្ជីទូទៅនៃប្រភេទដែលមិនតម្រូវឱ្យមានការបញ្ជាក់) ត្រូវបានទុកសម្រាប់អ្នកអានជាកិច្ចការផ្ទះ (ចំណាំ៖ ព័ត៌មាននៅក្នុង កូដប្រភព Telegram Desktop មិនពេញលេញទេ)។

ការញៀនគ្រឿងញៀន៖ ស្ថានភាពសារ

ជាទូទៅ កន្លែងជាច្រើននៅក្នុង TL, MTProto និង Telegram ជាទូទៅទុកនូវអារម្មណ៍រឹងរូស ប៉ុន្តែចេញពីភាពគួរសម កលល្បិច និងអ្នកដទៃ។ ជំនាញទន់ យើង​បាន​រក្សា​ភាព​ស្ងៀមស្ងាត់​អំពី​រឿង​នេះ​ដោយ​គួរសម ហើយ​បាន​ចាប់​ពិរុទ្ធ​ភាព​អាសអាភាស​ក្នុង​ការ​សន្ទនា។ ទោះយ៉ាងណាកន្លែងនេះ។Оទំព័រភាគច្រើនគឺអំពី សារអំពីសារ វាគួរឱ្យភ្ញាក់ផ្អើលសូម្បីតែសម្រាប់ខ្ញុំ ដែលបានធ្វើការជាមួយនឹងពិធីការបណ្តាញអស់រយៈពេលជាយូរ ហើយបានឃើញកង់ដែលមានកម្រិតខុសៗគ្នានៃភាពច្របូកច្របល់។

វាចាប់ផ្តើមដោយមិនដឹងខ្លួន ជាមួយនឹងការបញ្ជាក់។ បន្ទាប់មកពួកគេប្រាប់យើងអំពី

bad_msg_notification#a7eff811 bad_msg_id:long bad_msg_seqno:int error_code:int = BadMsgNotification;
bad_server_salt#edab447b bad_msg_id:long bad_msg_seqno:int error_code:int new_server_salt:long = BadMsgNotification;

ជាការប្រសើរណាស់ អ្នកគ្រប់គ្នាដែលចាប់ផ្តើមធ្វើការជាមួយ MTProto នឹងត្រូវដោះស្រាយជាមួយពួកគេនៅក្នុងវដ្ត "កែតម្រូវ - ចងក្រងឡើងវិញ - បើកដំណើរការ" ការទទួលបានកំហុសលេខ ឬអំបិលដែលបានគ្រប់គ្រងមិនល្អអំឡុងពេលកែសម្រួលគឺជារឿងធម្មតា។ ទោះយ៉ាងណាក៏ដោយ មានចំណុចពីរនៅទីនេះ៖

  1. នេះមានន័យថាសារដើមត្រូវបានបាត់បង់។ យើង​ត្រូវ​បង្កើត​ជួរ​មួយ​ចំនួន យើង​នឹង​មើល​វា​នៅ​ពេល​ក្រោយ។
  2. តើលេខកំហុសចម្លែកទាំងនេះជាអ្វី? 16, 17, 18, 19, 20, 32, 33, 34, 35, 48, 64... តើលេខផ្សេងទៀត ថមមី នៅឯណា?

ឯកសារ​បញ្ជាក់​ថា​៖

ចេតនាគឺថាតម្លៃ error_code ត្រូវបានដាក់ជាក្រុម (error_code >> 4): ឧទាហរណ៍ កូដ 0x40 — 0x4f ត្រូវគ្នាទៅនឹងកំហុសក្នុងការបំបែកកុងតឺន័រ។

ប៉ុន្តែ ទីមួយ ការផ្លាស់ប្តូរក្នុងទិសដៅផ្សេងទៀត ហើយទីពីរវាមិនមានបញ្ហាទេ តើលេខកូដផ្សេងទៀតនៅឯណា? នៅក្នុងក្បាលរបស់អ្នកនិពន្ធ?.. ទោះយ៉ាងណាទាំងនេះគឺជារឿងតូចតាច។

ការញៀនចាប់ផ្តើមនៅក្នុងសារអំពីស្ថានភាពសារ និងការចម្លងសារ៖

  • ស្នើសុំព័ត៌មានស្ថានភាពសារ
    ប្រសិនបើភាគីណាមួយមិនបានទទួលព័ត៌មានអំពីស្ថានភាពនៃសារដែលចេញរបស់ខ្លួនមួយរយៈនោះ វាអាចស្នើសុំយ៉ាងច្បាស់ពីភាគីផ្សេងទៀត៖
    msgs_state_req#da69fb52 msg_ids:Vector long = MsgsStateReq;
  • សារព័ត៌មានទាក់ទងនឹងស្ថានភាពសារ
    msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
    នៅទីនេះ, info គឺជាខ្សែអក្សរដែលមានស្ថានភាពសារមួយបៃយ៉ាងពិតប្រាកដសម្រាប់សារនីមួយៗពីបញ្ជី msg_ids ចូល៖

    • 1 = គ្មានអ្វីត្រូវបានដឹងអំពីសារ (msg_id ទាបពេក ភាគីម្ខាងទៀតប្រហែលជាភ្លេចវា)
    • 2 = សារមិនបានទទួល (msg_id ស្ថិតនៅក្នុងជួរនៃការកំណត់អត្តសញ្ញាណដែលបានរក្សាទុក។ ទោះយ៉ាងណាក៏ដោយ ភាគីម្ខាងទៀតពិតជាមិនបានទទួលសារដូចនោះទេ)
    • 3 = សារ​មិន​បាន​ទទួល (msg_id ខ្ពស់​ពេក; ទោះ​ជា​យ៉ាង​ណា​ភាគី​ផ្សេង​ទៀត​ពិត​ជា​មិន​បាន​ទទួល​វា​នៅ​ឡើយ​ទេ)
    • 4 = សារដែលបានទទួល (ចំណាំថាការឆ្លើយតបនេះក៏ជាការទទួលស្គាល់នៅពេលតែមួយផងដែរ)
    • +8 = សារ​បាន​ទទួល​ស្គាល់​រួច​ហើយ។
    • +16 = សារមិនតម្រូវឱ្យមានការទទួលស្គាល់
    • +32 = សំណួរ RPC ដែលមាននៅក្នុងសារកំពុងដំណើរការ ឬដំណើរការរួចរាល់ហើយ។
    • +64 = ការឆ្លើយតបទាក់ទងនឹងខ្លឹមសារចំពោះសារដែលបានបង្កើតរួចហើយ
    • +128 = ភាគីផ្សេងទៀតដឹងពីការពិតដែលសារត្រូវបានទទួលរួចហើយ
      ការឆ្លើយតបនេះមិនតម្រូវឱ្យមានការទទួលស្គាល់ទេ។ វាគឺជាការទទួលស្គាល់នៃ msgs_state_req ដែលពាក់ព័ន្ធនៅក្នុងខ្លួនវាផ្ទាល់។
      ចំណាំថាប្រសិនបើភ្លាមៗនោះភាគីម្ខាងទៀតមិនមានសារដែលមើលទៅហាក់ដូចជាត្រូវបានផ្ញើទៅវាទេ សារអាចត្រូវបានផ្ញើឡើងវិញ។ ទោះបីជាភាគីម្ខាងទៀតគួរតែទទួលបានសារពីរក្នុងពេលដំណាលគ្នាក៏ដោយ ច្បាប់ចម្លងនឹងមិនត្រូវបានអើពើ។ (ប្រសិនបើពេលវេលាបានកន្លងផុតទៅច្រើនពេក ហើយ msg_id ដើមលែងមានសុពលភាព សារនឹងត្រូវរុំក្នុង msg_copy) ។
  • ការទំនាក់ទំនងស្ម័គ្រចិត្តនៃស្ថានភាពនៃសារ
    ភាគីណាមួយអាចជូនដំណឹងដល់ភាគីម្ខាងទៀតដោយស្ម័គ្រចិត្តអំពីស្ថានភាពនៃសារដែលបានបញ្ជូនដោយភាគីម្ខាងទៀត។
    msgs_all_info#8cc0d131 msg_ids:Vector long info:string = MsgsAllInfo
  • ពង្រីកទំនាក់ទំនងស្ម័គ្រចិត្តនៃស្ថានភាពនៃសារមួយ។
    ...
    msg_detailed_info#276d3ec6 msg_id:long answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
    msg_new_detailed_info#809db6df answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
  • សំណើច្បាស់លាស់ដើម្បីផ្ញើសារឡើងវិញ
    msg_resend_req#7d861a08 msg_ids:Vector long = MsgResendReq;
    ភាគីពីចម្ងាយឆ្លើយតបភ្លាមៗដោយការផ្ញើសារដែលបានស្នើសុំឡើងវិញ […]
  • សំណើច្បាស់លាស់ដើម្បីផ្ញើចម្លើយឡើងវិញ
    msg_resend_ans_req#8610baeb msg_ids:Vector long = MsgResendReq;
    ភាគីពីចម្ងាយឆ្លើយតបភ្លាមៗដោយការផ្ញើឡើងវិញ ចម្លើយ ទៅកាន់សារដែលបានស្នើសុំ […]
  • ច្បាប់ចម្លងសារ
    ក្នុងស្ថានភាពខ្លះ សារចាស់ដែលមាន msg_id ដែលលែងមានសុពលភាពត្រូវផ្ញើឡើងវិញ។ បន្ទាប់មកវាត្រូវបានរុំក្នុងធុងចម្លងមួយ៖
    msg_copy#e06046b2 orig_message:Message = MessageCopy;
    នៅពេលដែលបានទទួល សារត្រូវបានដំណើរការដូចជាប្រសិនបើរុំមិននៅទីនោះ។ ទោះយ៉ាងណាក៏ដោយ ប្រសិនបើគេដឹងច្បាស់ថា សារ orig_message.msg_id ត្រូវបានទទួល នោះសារថ្មីមិនត្រូវបានដំណើរការទេ (ស្របពេលជាមួយគ្នានេះ វា និង orig_message.msg_id ត្រូវបានទទួលស្គាល់)។ តម្លៃនៃ orig_message.msg_id ត្រូវតែទាបជាង msg_id របស់កុងតឺន័រ។

ចូរយើងនៅស្ងៀមអំពីអ្វី msgs_state_info ម្តងទៀត ត្រចៀករបស់ TL ដែលមិនទាន់បានបញ្ចប់កំពុងបិទ (យើងត្រូវការវ៉ិចទ័រនៃបៃហើយនៅខាងក្រោមពីរប៊ីតមាន enum ហើយនៅក្នុងប៊ីតពីរខ្ពស់ជាងនេះមានទង់) ។ ចំណុចគឺខុសគ្នា។ តើ​មាន​នរណា​យល់​ថា​ហេតុ​អ្វី​បាន​ជា​ការ​អនុវត្ត​ទាំង​អស់​នេះ? នៅក្នុងអតិថិជនពិតប្រាកដ ចាំបាច់?.. ជាមួយនឹងការលំបាក ប៉ុន្តែមនុស្សម្នាក់អាចស្រមៃមើលអត្ថប្រយោជន៍មួយចំនួន ប្រសិនបើមនុស្សម្នាក់ត្រូវបានចូលរួមនៅក្នុងការបំបាត់កំហុស ហើយនៅក្នុងរបៀបអន្តរកម្ម - សួរម៉ាស៊ីនមេថាតើអ្វី និងរបៀប។ ប៉ុន្តែនៅទីនេះសំណើត្រូវបានពិពណ៌នា ការ​ធ្វើ​ដំណើរ​ជុំ.

វាធ្វើតាមដែលភាគីនីមួយៗមិនត្រឹមតែត្រូវអ៊ិនគ្រីប និងផ្ញើសារប៉ុណ្ណោះទេ ប៉ុន្តែថែមទាំងរក្សាទុកទិន្នន័យអំពីខ្លួនពួកគេ អំពីការឆ្លើយតបចំពោះពួកគេ សម្រាប់រយៈពេលមិនស្គាល់មួយ។ ឯកសារមិនពិពណ៌នាអំពីពេលវេលា ឬការអនុវត្តជាក់ស្តែងនៃលក្ខណៈពិសេសទាំងនេះទេ។ គ្មានផ្លូវ. អ្វី​ដែល​អស្ចារ្យ​បំផុត​គឺ​ពួកគេ​ត្រូវ​បាន​គេ​ប្រើ​យ៉ាង​ពិត​ប្រាកដ​ក្នុង​កូដ​អតិថិជន​ផ្លូវការ! តាមមើលទៅ ពួកគេត្រូវបានប្រាប់អ្វីមួយដែលមិនត្រូវបានបញ្ចូលក្នុងឯកសារសាធារណៈ។ ស្វែងយល់ពីកូដ ហេតុអ្វីលែងសាមញ្ញដូចករណី TL ទៀតហើយ - វាមិនមែនជាផ្នែកដាច់ដោយឡែក (ទាក់ទងគ្នា) ឡូជីខលទេ ប៉ុន្តែជាបំណែកដែលភ្ជាប់ទៅនឹងស្ថាបត្យកម្មកម្មវិធី ពោលគឺឧ។ នឹងត្រូវការពេលវេលាច្រើន ដើម្បីស្វែងយល់អំពីកូដកម្មវិធី។

Pings និងពេលវេលា។ ជួរ។

ពីអ្វីៗគ្រប់យ៉ាង ប្រសិនបើយើងចងចាំការស្មានអំពីស្ថាបត្យកម្មម៉ាស៊ីនមេ (ការចែកចាយសំណើឆ្លងកាត់ផ្នែកខាងក្រោយ) ជារឿងដ៏សោកសៅមួយកើតឡើង - ទោះបីជាមានការធានាលើការដឹកជញ្ជូនទាំងអស់នៅក្នុង TCP (ទាំងទិន្នន័យត្រូវបានបញ្ជូន ឬអ្នកនឹងត្រូវបានជូនដំណឹងអំពីគម្លាតក៏ដោយ ប៉ុន្តែ ទិន្នន័យនឹងត្រូវបានបញ្ជូនមុនពេលបញ្ហាកើតឡើង) ការបញ្ជាក់នៅក្នុង MTProto ខ្លួនវា - គ្មានការធានា. ម៉ាស៊ីនមេអាចបាត់បង់ ឬបោះចោលសាររបស់អ្នកយ៉ាងងាយស្រួល ហើយគ្មានអ្វីអាចធ្វើបានអំពីវាទេ គ្រាន់តែប្រើឈើច្រត់ប្រភេទផ្សេងៗគ្នា។

ហើយជាដំបូងនៃការទាំងអស់ - ជួរសារ។ ជាការប្រសើរណាស់ ជាមួយនឹងរឿងមួយ អ្វីគ្រប់យ៉ាងគឺជាក់ស្តែងតាំងពីដំបូងមក - សារដែលមិនបានបញ្ជាក់ត្រូវតែត្រូវបានរក្សាទុក និងអន់ចិត្ត។ ហើយបន្ទាប់ពីម៉ោងប៉ុន្មាន? ហើយអ្នកកំប្លែងស្គាល់គាត់។ ប្រហែលជាសារសេវាកម្មញៀនទាំងនោះដោះស្រាយបញ្ហានេះដោយប្រើឈើច្រត់ និយាយថានៅក្នុង Telegram Desktop មានប្រហែល 4 ជួរដែលត្រូវគ្នានឹងពួកគេ (ប្រហែលជាច្រើនជាងនេះ ដូចដែលបានបញ្ជាក់រួចមកហើយ សម្រាប់បញ្ហានេះអ្នកត្រូវស្វែងយល់ពីកូដ និងស្ថាបត្យកម្មរបស់វាឱ្យកាន់តែធ្ងន់ធ្ងរ។ ពេលវេលា យើងដឹងថាវាមិនអាចត្រូវបានយកជាគំរូមួយ ចំនួនជាក់លាក់នៃប្រភេទពីគ្រោងការណ៍ MTProto មិនត្រូវបានប្រើនៅក្នុងវា)។

ហេតុអ្វីបានជារឿងនេះកើតឡើង? ប្រហែលជា អ្នកសរសេរកម្មវិធីរបស់ម៉ាស៊ីនមេមិនអាចធានាបាននូវភាពជឿជាក់នៅក្នុងចង្កោម ឬសូម្បីតែការផ្អាកនៅលើតុល្យភាពផ្នែកខាងមុខ ហើយផ្ទេរបញ្ហានេះទៅម៉ាស៊ីនភ្ញៀវ។ ដោយអស់សង្ឃឹម Vasily បានព្យាយាមអនុវត្តជម្រើសជំនួសដោយមានតែពីរជួរប៉ុណ្ណោះ ដោយប្រើក្បួនដោះស្រាយពី TCP - វាស់ RTT ទៅម៉ាស៊ីនមេ និងកែតម្រូវទំហំនៃ "បង្អួច" (ក្នុងសារ) អាស្រ័យលើចំនួនសំណើដែលមិនបានបញ្ជាក់។ នោះគឺការគិតដ៏លំបាកបែបនេះសម្រាប់ការវាយតម្លៃបន្ទុករបស់ម៉ាស៊ីនមេ គឺជាចំនួនសំណើរបស់យើងដែលវាអាចទំពារក្នុងពេលតែមួយ និងមិនបាត់បង់។

មែនហើយ គឺថាអ្នកយល់ហើយមែនទេ? ប្រសិនបើអ្នកត្រូវអនុវត្ត TCP ម្តងទៀតនៅលើកំពូលនៃពិធីការដែលដំណើរការលើ TCP នេះបង្ហាញពីពិធីការដែលបានរចនាមិនសូវល្អ។

អូ បាទ ហេតុអ្វីបានជាអ្នកត្រូវការជួរច្រើនជាងមួយ ហើយតើនេះមានន័យយ៉ាងណាសម្រាប់មនុស្សម្នាក់ដែលធ្វើការជាមួយ API កម្រិតខ្ពស់? មើល អ្នក​ធ្វើ​ការ​ស្នើ​សុំ ធ្វើ​ស៊េរី​វា ប៉ុន្តែ​ជា​ញឹកញាប់​អ្នក​មិន​អាច​ផ្ញើ​វា​ភ្លាមៗ​បាន​ទេ។ ហេតុអ្វី? ដោយសារតែចម្លើយនឹង msg_idដែលជាបណ្តោះអាសន្នаខ្ញុំជាស្លាក កិច្ចការដែលត្រូវបានពន្យារពេលល្អបំផុតរហូតដល់យឺតពេលតាមដែលអាចធ្វើទៅបាន - ក្នុងករណីដែលម៉ាស៊ីនមេបដិសេធដោយសារតែពេលវេលាមិនស៊ីគ្នារវាងយើង និងគាត់ (ជាការពិតណាស់ យើងអាចបង្កើតឈើច្រត់ដែលផ្លាស់ប្តូរពេលវេលារបស់យើងពីបច្ចុប្បន្ន។ ទៅម៉ាស៊ីនមេដោយបន្ថែមដីសណ្តដែលបានគណនាពីការឆ្លើយតបរបស់ម៉ាស៊ីនមេ - អតិថិជនផ្លូវការធ្វើបែបនេះ ប៉ុន្តែវាឆៅ និងមិនត្រឹមត្រូវដោយសារការបណ្ដោះអាសន្ន)។ ដូច្នេះហើយ នៅពេលដែលអ្នកធ្វើការស្នើសុំជាមួយនឹងការហៅមុខងារក្នុងតំបន់ពីបណ្ណាល័យ សារនោះឆ្លងកាត់ដំណាក់កាលដូចខាងក្រោម៖

  1. វាស្ថិតនៅក្នុងជួរមួយ ហើយរង់ចាំការអ៊ិនគ្រីប។
  2. ត្រូវបានតែងតាំង msg_id ហើយសារបានទៅជួរមួយទៀត - អាចបញ្ជូនបន្ត។ ផ្ញើទៅរន្ធ។
  3. ក) ម៉ាស៊ីនមេបានឆ្លើយតប MsgsAck - សារត្រូវបានបញ្ជូន យើងលុបវាចេញពី "ជួរផ្សេងទៀត" ។
    ខ) ឬផ្ទុយទៅវិញ គាត់មិនចូលចិត្តអ្វីមួយ គាត់បានឆ្លើយថា badmsg - ផ្ញើឡើងវិញពី "ជួរផ្សេងទៀត"
    គ) គ្មានអ្វីត្រូវបានគេដឹងទេ សារចាំបាច់ត្រូវបញ្ជូនពីជួរផ្សេងទៀត ប៉ុន្តែវាមិនត្រូវបានគេដឹងច្បាស់ថានៅពេលណានោះទេ។
  4. ទីបំផុតម៉ាស៊ីនមេបានឆ្លើយតប RpcResult - ការឆ្លើយតបពិតប្រាកដ (ឬកំហុស) - មិនត្រឹមតែត្រូវបានចែកចាយប៉ុណ្ណោះទេប៉ុន្តែថែមទាំងដំណើរការផងដែរ។

ប្រហែលជាការប្រើប្រាស់ធុងអាចដោះស្រាយបញ្ហាបានមួយផ្នែក។ នេះគឺជាពេលដែលសារជាច្រើនត្រូវបានខ្ចប់ចូលទៅក្នុងតែមួយ ហើយម៉ាស៊ីនមេបានឆ្លើយតបជាមួយនឹងការបញ្ជាក់ទៅកាន់ពួកគេទាំងអស់ក្នុងពេលតែមួយ ក្នុងមួយ msg_id. ប៉ុន្តែគាត់ក៏នឹងបដិសេធកញ្ចប់នេះផងដែរ ប្រសិនបើមានអ្វីខុសទាំងស្រុង។

ហើយនៅចំណុចនេះការពិចារណាដែលមិនមែនជាបច្ចេកទេសចូលមកលេង។ តាមបទពិសោធន៍ យើងបានឃើញឈើច្រត់ជាច្រើន ហើយលើសពីនេះទៅទៀត ឥឡូវនេះយើងនឹងឃើញឧទាហរណ៍ជាច្រើនទៀតនៃដំបូន្មាន និងស្ថាបត្យកម្មមិនល្អ - ក្នុងលក្ខខណ្ឌបែបនេះ តើវាគួរឱ្យទុកចិត្ត និងធ្វើការសម្រេចចិត្តបែបនេះទេ? សំណួរគឺវោហាសាស្ត្រ (ពិតណាស់មិនមែនទេ) ។

តើយើងកំពុងនិយាយអំពីអ្វី? ប្រសិនបើនៅលើប្រធានបទនៃ "សារគ្រឿងញៀនអំពីសារ" អ្នកនៅតែអាចប៉ាន់ស្មានជាមួយនឹងការជំទាស់ដូចជា "អ្នកល្ងង់ អ្នកមិនយល់ពីផែនការដ៏អស្ចារ្យរបស់យើងទេ!" (ដូច្នេះសូមសរសេរឯកសារជាមុន ដូចដែលមនុស្សធម្មតាគួរ ដោយមានហេតុផល និងឧទាហរណ៍នៃការផ្លាស់ប្តូរកញ្ចប់ព័ត៌មាន បន្ទាប់មកយើងនឹងនិយាយ) បន្ទាប់មកពេលវេលា/ការអស់ពេលគឺជាសំណួរជាក់ស្តែង និងជាក់លាក់ អ្វីគ្រប់យ៉ាងនៅទីនេះត្រូវបានគេស្គាល់ជាយូរមកហើយ។ តើឯកសារប្រាប់យើងអ្វីខ្លះអំពីការអស់ពេល?

ម៉ាស៊ីនមេជាធម្មតាទទួលស្គាល់ការទទួលសារពីអតិថិជន (ជាធម្មតា សំណួរ RPC) ដោយប្រើការឆ្លើយតប RPC ។ ប្រសិនបើការឆ្លើយតបមានរយៈពេលយូរ នោះម៉ាស៊ីនមេអាចផ្ញើការទទួលស្គាល់បង្កាន់ដៃដំបូង ហើយបន្តិចក្រោយមក ការឆ្លើយតបរបស់ RPC ខ្លួនវាផ្ទាល់។

ជាធម្មតាអតិថិជនទទួលស្គាល់ការទទួលសារពីម៉ាស៊ីនមេ (ជាធម្មតាការឆ្លើយតប RPC) ដោយបន្ថែមការទទួលស្គាល់ទៅសំណួរ RPC បន្ទាប់ប្រសិនបើវាមិនត្រូវបានបញ្ជូនយឺតពេលទេ (ប្រសិនបើវាត្រូវបានបង្កើតសូមនិយាយថា 60-120 វិនាទីបន្ទាប់ពីទទួល។ សារពីម៉ាស៊ីនមេ) ។ ទោះយ៉ាងណាក៏ដោយ ប្រសិនបើរយៈពេលយូរមិនមានហេតុផលក្នុងការផ្ញើសារទៅកាន់ម៉ាស៊ីនមេ ឬប្រសិនបើមានសារមួយចំនួនធំដែលមិនបានទទួលស្គាល់ពីម៉ាស៊ីនមេ (និយាយថាលើសពី 16) ម៉ាស៊ីនភ្ញៀវនឹងបញ្ជូនការទទួលស្គាល់តែម្នាក់ឯង។

... ខ្ញុំបកប្រែ៖ យើងខ្លួនយើងមិនដឹងថាតើយើងត្រូវការវាប៉ុណ្ណាទេ ដូច្នេះសូមសន្មតថាអនុញ្ញាតឱ្យវាដូចនេះ។

ហើយអំពី pings:

សារ Ping (PING/PONG)

ping#7abe77ec ping_id:long = Pong;

ការឆ្លើយតបជាធម្មតាត្រូវបានត្រលប់ទៅការតភ្ជាប់ដូចគ្នា៖

pong#347773c5 msg_id:long ping_id:long = Pong;

សារទាំងនេះមិនតម្រូវឱ្យមានការទទួលស្គាល់ទេ។ ប៉ុងត្រូវបានបញ្ជូនតែក្នុងការឆ្លើយតបទៅនឹង ping ខណៈពេលដែល ping អាចត្រូវបានផ្តួចផ្តើមដោយភាគីណាមួយ។

ការបិទការតភ្ជាប់ពន្យាពេល + PING

ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;

ធ្វើការដូចជា ping ។ លើសពីនេះទៀត បន្ទាប់ពីវាត្រូវបានទទួល នោះម៉ាស៊ីនមេចាប់ផ្តើមកម្មវិធីកំណត់ពេលវេលាដែលនឹងបិទការតភ្ជាប់បច្ចុប្បន្ន disconnect_delay វិនាទីក្រោយ លុះត្រាតែវាទទួលបានសារថ្មីនៃប្រភេទដូចគ្នា ដែលកំណត់កម្មវិធីកំណត់ម៉ោងមុនទាំងអស់ឡើងវិញដោយស្វ័យប្រវត្តិ។ ឧទាហរណ៍ ប្រសិនបើម៉ាស៊ីនភ្ញៀវផ្ញើ ping ទាំងនេះម្តងរៀងរាល់ 60 វិនាទី វាអាចកំណត់ disconnect_delay ស្មើនឹង 75 វិនាទី។

ឆ្កួតទេ?! ក្នុងរយៈពេល 60 វិនាទី រថភ្លើងនឹងចូលស្ថានីយ ទម្លាក់ និងទទួលអ្នកដំណើរ ហើយម្តងទៀតបាត់បង់ទំនាក់ទំនងនៅក្នុងផ្លូវរូងក្រោមដី។ ក្នុងរយៈពេល 120 វិនាទី ខណៈពេលដែលអ្នកឮវា វានឹងមកដល់មួយទៀត ហើយការតភ្ជាប់ទំនងជានឹងដាច់។ ជាការប្រសើរណាស់ វាច្បាស់ថាជើងមកពីណា - "ខ្ញុំបានឮសំឡេងរោទ៍ ប៉ុន្តែមិនដឹងថាវានៅឯណា" មានក្បួនដោះស្រាយរបស់ Nagl និងជម្រើស TCP_NODELAY ដែលមានបំណងសម្រាប់ការងារអន្តរកម្ម។ ប៉ុន្តែសូមអភ័យទោស សង្កត់លើតម្លៃលំនាំដើមរបស់វា - 200 មីលីវិនាទី ប្រសិនបើ​អ្នក​ពិតជា​ចង់​ពណ៌នា​អ្វី​ដែល​ស្រដៀង​គ្នា ហើយ​រក្សាទុក​នៅលើ​កញ្ចប់​ដែល​អាច​ប្រើ​បាន​ពីរ​បី​កញ្ចប់ បន្ទាប់មក​បិទ​វា​រយៈពេល 5 វិនាទី ឬ​អ្វី​ក៏ដោយ​ដែល​សារ "អ្នកប្រើប្រាស់​កំពុង​វាយ..." គឺ​អស់ពេល​ហើយ។ ប៉ុន្តែមិនមានទៀតទេ។

ហើយចុងក្រោយ pings ។ នោះគឺពិនិត្យមើលភាពរស់រវើកនៃការតភ្ជាប់ TCP ។ វាគួរឱ្យអស់សំណើចណាស់ ប៉ុន្តែប្រហែល 10 ឆ្នាំមុនខ្ញុំបានសរសេរអត្ថបទរិះគន់អំពីអ្នកនាំសារនៃបន្ទប់ស្នាក់នៅរបស់មហាវិទ្យាល័យរបស់យើង - អ្នកនិពន្ធនៅទីនោះក៏បានវាយម៉ាស៊ីនមេពីអតិថិជនដែរ ហើយមិនមែនផ្ទុយមកវិញទេ។ ប៉ុន្តែ​និស្សិត​ឆ្នាំ​ទី​៣​ជា​រឿង​មួយ ហើយ​ការិយាល័យ​អន្តរជាតិ​គឺ​មួយ​ទៀត​មែន​ទេ?..

ជាដំបូង កម្មវិធីអប់រំតិចតួច។ ការតភ្ជាប់ TCP ក្នុងករណីដែលគ្មានការផ្លាស់ប្តូរកញ្ចប់ព័ត៌មានអាចរស់នៅបានច្រើនសប្តាហ៍។ នេះ​មាន​ទាំង​ល្អ និង​អាក្រក់ អាស្រ័យ​លើ​គោល​បំណង។ វាល្អប្រសិនបើអ្នកមានការតភ្ជាប់ SSH បើកទៅកាន់ម៉ាស៊ីនមេ អ្នកក្រោកពីកុំព្យូទ័រ ចាប់ផ្ដើមរ៉ោតទ័រឡើងវិញ ត្រឡប់ទៅកន្លែងរបស់អ្នកវិញ - វគ្គតាមរយៈម៉ាស៊ីនមេនេះមិនត្រូវបានរហែកទេ (អ្នកមិនបានវាយអ្វីទាំងអស់ មិនមានកញ្ចប់ព័ត៌មាន) វាជាការងាយស្រួល។ វាជារឿងអាក្រក់ប្រសិនបើមានអតិថិជនរាប់ពាន់នាក់នៅលើម៉ាស៊ីនមេ ម្នាក់ៗទទួលយកធនធាន (ជំរាបសួរ Postgres!) ហើយម៉ាស៊ីនរបស់អតិថិជនប្រហែលជាបានដំណើរការឡើងវិញជាយូរមកហើយ ប៉ុន្តែយើងនឹងមិនដឹងអំពីវាទេ។

ប្រព័ន្ធជជែក/IM ធ្លាក់ចូលទៅក្នុងករណីទីពីរសម្រាប់ហេតុផលបន្ថែមមួយ - ស្ថានភាពអនឡាញ។ ប្រសិនបើអ្នកប្រើ "ដួល" អ្នកត្រូវជូនដំណឹងទៅអន្តរការីរបស់គាត់អំពីរឿងនេះ។ បើមិនដូច្នេះទេ អ្នកនឹងបញ្ចប់ជាមួយនឹងកំហុសដែលអ្នកបង្កើត Jabber បានធ្វើ (និងកែតម្រូវរយៈពេល 20 ឆ្នាំ) - អ្នកប្រើប្រាស់បានផ្តាច់ទំនាក់ទំនង ប៉ុន្តែពួកគេនៅតែបន្តសរសេរសារទៅគាត់ដោយជឿថាគាត់នៅលើអ៊ីនធឺណិត (ដែលត្រូវបានបាត់បង់ទាំងស្រុងផងដែរនៅក្នុងទាំងនេះ។ ពីរបីនាទីមុនពេលការផ្តាច់ទំនាក់ទំនងត្រូវបានរកឃើញ) ។ ទេ ជម្រើស TCP_KEEPALIVE ដែលមនុស្សជាច្រើនដែលមិនយល់ពីរបៀបដែលកម្មវិធីកំណត់ម៉ោង TCP ដំណើរការដោយចៃដន្យ (ដោយការកំណត់តម្លៃព្រៃដូចជារាប់សិបវិនាទី) នឹងមិនជួយនៅទីនេះទេ - អ្នកត្រូវប្រាកដថាមិនត្រឹមតែខឺណែល OS ប៉ុណ្ណោះទេ ម៉ាស៊ីនរបស់អ្នកប្រើគឺនៅរស់ ប៉ុន្តែក៏ដំណើរការជាធម្មតា ដោយអាចឆ្លើយតប និងកម្មវិធីខ្លួនឯង (តើអ្នកគិតថាវាមិនអាចបង្កកបានទេ? Telegram Desktop នៅលើ Ubuntu 18.04 បង្កកសម្រាប់ខ្ញុំច្រើនជាងម្តង)។

នោះហើយជាមូលហេតុដែលអ្នកត្រូវ ping ម៉ាស៊ីនមេ ម៉ាស៊ីនភ្ញៀវ និងមិនផ្ទុយមកវិញ - ប្រសិនបើអតិថិជនធ្វើដូចនេះ ប្រសិនបើការតភ្ជាប់ត្រូវបានខូច ភីងនឹងមិនត្រូវបានបញ្ជូនទេ គោលដៅនឹងមិនត្រូវបានសម្រេចទេ។

តើយើងឃើញអ្វីនៅលើ Telegram? ពិតជាផ្ទុយស្រឡះ! អញ្ចឹង។ ជា​ផ្លូវការ ភាគី​ទាំង​ពីរ​អាច​វាយ​គ្នា​ទៅ​វិញ​ទៅ​មក។ នៅក្នុងការអនុវត្ត អតិថិជនប្រើឈើច្រត់ ping_delay_disconnectដែលកំណត់កម្មវិធីកំណត់ម៉ោងនៅលើម៉ាស៊ីនមេ។ សូមអភ័យទោស វាមិនអាស្រ័យលើអតិថិជនក្នុងការសម្រេចចិត្តរយៈពេលដែលគាត់ចង់រស់នៅទីនោះដោយគ្មាន ping នោះទេ។ ម៉ាស៊ីនមេ ដោយផ្អែកលើបន្ទុករបស់វាដឹងកាន់តែច្បាស់។ ប៉ុន្តែជាការពិតណាស់ ប្រសិនបើអ្នកមិនខ្វល់ពីធនធានទេ នោះអ្នកនឹងក្លាយជា Pinocchio អាក្រក់របស់អ្នក ហើយឈើច្រត់នឹងធ្វើ ...

តើវាគួរត្រូវបានរចនាដោយរបៀបណា?

ខ្ញុំជឿថាការពិតខាងលើបង្ហាញយ៉ាងច្បាស់ថាក្រុម Telegram/VKontakte មិនមានជំនាញខ្លាំងក្នុងវិស័យដឹកជញ្ជូន (និងកម្រិតទាប) នៃបណ្តាញកុំព្យូទ័រ និងគុណវុឌ្ឍិទាបរបស់ពួកគេក្នុងបញ្ហាពាក់ព័ន្ធ។

ហេតុអ្វីបានជាវាប្រែជាស្មុគស្មាញ ហើយតើស្ថាបត្យករ Telegram អាចព្យាយាមជំទាស់ដោយរបៀបណា? ការពិតដែលថាពួកគេបានព្យាយាមបង្កើតវគ្គដែលនៅរស់រានមានជីវិតពីការដាច់ការតភ្ជាប់ TCP ពោលគឺអ្វីដែលមិនត្រូវបានចែកចាយនៅពេលនេះ យើងនឹងចែកចាយនៅពេលក្រោយ។ ពួកគេប្រហែលជាបានព្យាយាមធ្វើការដឹកជញ្ជូន UDP ផងដែរ ប៉ុន្តែពួកគេបានជួបប្រទះការលំបាក ហើយបានបោះបង់ចោលវា (នោះហើយជាមូលហេតុដែលឯកសារគឺទទេ - មិនមានអ្វីត្រូវអួតទេ)។ ប៉ុន្តែដោយសារតែការខ្វះការយល់ដឹងអំពីរបៀបដែលបណ្តាញជាទូទៅ និង TCP ជាពិសេសធ្វើការ ដែលអ្នកអាចពឹងផ្អែកលើវា និងកន្លែងដែលអ្នកត្រូវធ្វើវាដោយខ្លួនឯង (និងរបៀប) និងការប៉ុនប៉ងបញ្ចូលគ្នាជាមួយការគ្រីប "បក្សីពីរជាមួយ ថ្មមួយដុំ” នេះជាលទ្ធផល។

តើវាចាំបាច់យ៉ាងដូចម្តេច? ដោយផ្អែកលើការពិតនោះ។ msg_id គឺជាការបោះត្រាពេលវេលាចាំបាច់ពីចំណុចនៃទិដ្ឋភាពគ្រីប ដើម្បីការពារការវាយប្រហារឡើងវិញ វាជាកំហុសក្នុងការភ្ជាប់មុខងារកំណត់អត្តសញ្ញាណតែមួយគត់ទៅវា។ ដូច្នេះ ដោយគ្មានការផ្លាស់ប្តូរជាមូលដ្ឋាននៃស្ថាបត្យកម្មបច្ចុប្បន្ន (នៅពេលដែលការអាប់ដេតស្ទ្រីមត្រូវបានបង្កើត នោះជាប្រធានបទ API កម្រិតខ្ពស់សម្រាប់ផ្នែកផ្សេងទៀតនៃស៊េរីនៃការបង្ហោះនេះ) អ្នកត្រូវ៖

  1. ម៉ាស៊ីនមេដែលកាន់ការភ្ជាប់ TCP ទៅម៉ាស៊ីនភ្ញៀវទទួលខុសត្រូវ - ប្រសិនបើវាបានអានចេញពីរន្ធ សូមទទួលស្គាល់ ដំណើរការ ឬត្រឡប់កំហុស នឹងមិនបាត់បង់ឡើយ។ បន្ទាប់មកការបញ្ជាក់មិនមែនជាវ៉ិចទ័រនៃលេខសម្គាល់ទេ ប៉ុន្តែគ្រាន់តែ "ទទួលបានចុងក្រោយ seq_no" - គ្រាន់តែជាលេខដូចនៅក្នុង TCP (លេខពីរ - seq របស់អ្នក និងលេខដែលបានបញ្ជាក់)។ យើងតែងតែនៅក្នុងសម័យប្រជុំ មែនទេ?
  2. ត្រាពេលវេលាដើម្បីការពារការវាយប្រហារឡើងវិញ ក្លាយជាវាលដាច់ដោយឡែក។ វាត្រូវបានត្រួតពិនិត្យប៉ុន្តែមិនប៉ះពាល់ដល់អ្វីផ្សេងទៀតទេ។ គ្រប់គ្រាន់ហើយ uint32 - ប្រសិនបើអំបិលរបស់យើងផ្លាស់ប្តូរយ៉ាងហោចណាស់រៀងរាល់កន្លះថ្ងៃម្តង យើងអាចបែងចែក 16 ប៊ីតទៅជាប៊ីតលំដាប់ទាបនៃផ្នែកចំនួនគត់នៃពេលវេលាបច្ចុប្បន្ន នៅសល់ - ទៅផ្នែកប្រភាគនៃវិនាទី (ដូចពេលនេះ)។
  3. បានដកចេញ msg_id ទាំងអស់ - តាមទស្សនៈនៃការបែងចែកសំណើនៅលើ backends មាន ទីមួយ លេខសម្គាល់អតិថិជន និងទីពីរ លេខសម្គាល់សម័យ ភ្ជាប់ពួកវា។ ដូច្នោះហើយ មានតែរឿងមួយគត់គឺគ្រប់គ្រាន់ជាការកំណត់អត្តសញ្ញាណសំណើ seq_no.

នេះក៏មិនមែនជាជម្រើសជោគជ័យបំផុតដែរ ចៃដន្យពេញលេញអាចដើរតួជាអ្នកកំណត់អត្តសញ្ញាណ - នេះត្រូវបានធ្វើរួចហើយនៅក្នុង API កម្រិតខ្ពស់នៅពេលផ្ញើសារ។ វាជាការប្រសើរក្នុងការរៀបចំឡើងវិញទាំងស្រុងនូវស្ថាបត្យកម្មពីទំនាក់ទំនងទៅដាច់ខាត ប៉ុន្តែនេះគឺជាប្រធានបទសម្រាប់ផ្នែកមួយផ្សេងទៀត មិនមែនជាការបង្ហោះនេះទេ។

API?

តាដាម! ដូច្នេះ ដោយបានតស៊ូឆ្លងកាត់ផ្លូវដែលពោរពេញដោយការឈឺចាប់ និងឈើច្រត់ ទីបំផុតយើងអាចផ្ញើសំណើណាមួយទៅកាន់ម៉ាស៊ីនមេ និងទទួលបានចម្លើយណាមួយទៅកាន់ពួកគេ ក៏ដូចជាទទួលបានព័ត៌មានថ្មីៗពីម៉ាស៊ីនមេ (មិនមែនឆ្លើយតបទៅនឹងសំណើនោះទេ ប៉ុន្តែវាផ្ទាល់ ផ្ញើមកយើងដូចជា PUSH បើអ្នកណាម្នាក់ច្បាស់ជាងនេះ)។

យកចិត្តទុកដាក់ ឥឡូវនេះនឹងមានឧទាហរណ៍តែមួយគត់នៅក្នុង Perl នៅក្នុងអត្ថបទ! (សម្រាប់អ្នកដែលមិនស៊ាំនឹងវាក្យសម្ព័ន្ធ អាគុយម៉ង់ទីមួយនៃពរគឺជារចនាសម្ព័ន្ធទិន្នន័យរបស់វត្ថុ ទីពីរគឺជាថ្នាក់របស់វា)៖

2019.10.24 12:00:51 $1 = {
'cb' => 'TeleUpd::__ANON__',
'out' => bless( {
'filter' => bless( {}, 'Telegram::ChannelMessagesFilterEmpty' ),
'channel' => bless( {
'access_hash' => '-6698103710539760874',
'channel_id' => '1380524958'
}, 'Telegram::InputPeerChannel' ),
'pts' => '158503',
'flags' => 0,
'limit' => 0
}, 'Telegram::Updates::GetChannelDifference' ),
'req_id' => '6751291954012037292'
};
2019.10.24 12:00:51 $1 = {
'in' => bless( {
'req_msg_id' => '6751291954012037292',
'result' => bless( {
'pts' => 158508,
'flags' => 3,
'final' => 1,
'new_messages' => [],
'users' => [],
'chats' => [
bless( {
'title' => 'Хулиномика',
'username' => 'hoolinomics',
'flags' => 8288,
'id' => 1380524958,
'access_hash' => '-6698103710539760874',
'broadcast' => 1,
'version' => 0,
'photo' => bless( {
'photo_small' => bless( {
'volume_id' => 246933270,
'file_reference' => '
'secret' => '1854156056801727328',
'local_id' => 228648,
'dc_id' => 2
}, 'Telegram::FileLocation' ),
'photo_big' => bless( {
'dc_id' => 2,
'local_id' => 228650,
'file_reference' => '
'secret' => '1275570353387113110',
'volume_id' => 246933270
}, 'Telegram::FileLocation' )
}, 'Telegram::ChatPhoto' ),
'date' => 1531221081
}, 'Telegram::Channel' )
],
'timeout' => 300,
'other_updates' => [
bless( {
'pts_count' => 0,
'message' => bless( {
'post' => 1,
'id' => 852,
'flags' => 50368,
'views' => 8013,
'entities' => [
bless( {
'length' => 20,
'offset' => 0
}, 'Telegram::MessageEntityBold' ),
bless( {
'length' => 18,
'offset' => 480,
'url' => 'https://alexeymarkov.livejournal.com/[url_вырезан].html'
}, 'Telegram::MessageEntityTextUrl' )
],
'reply_markup' => bless( {
'rows' => [
bless( {
'buttons' => [
bless( {
'text' => '???? 165',
'data' => 'send_reaction_0'
}, 'Telegram::KeyboardButtonCallback' ),
bless( {
'data' => 'send_reaction_1',
'text' => '???? 9'
}, 'Telegram::KeyboardButtonCallback' )
]
}, 'Telegram::KeyboardButtonRow' )
]
}, 'Telegram::ReplyInlineMarkup' ),
'message' => 'А вот и новая книга! 
// [текст сообщения вырезан чтоб не нарушать правил Хабра о рекламе]
напечатаю.',
'to_id' => bless( {
'channel_id' => 1380524958
}, 'Telegram::PeerChannel' ),
'date' => 1571724559,
'edit_date' => 1571907562
}, 'Telegram::Message' ),
'pts' => 158508
}, 'Telegram::UpdateEditChannelMessage' ),
bless( {
'pts' => 158508,
'message' => bless( {
'edit_date' => 1571907589,
'to_id' => bless( {
'channel_id' => 1380524958
}, 'Telegram::PeerChannel' ),
'date' => 1571807301,
'message' => 'Почему Вы считаете Facebook плохой компанией? Можете прокомментировать? По-моему, это шикарная компания. Без долгов, с хорошей прибылью, а если решат дивы платить, то и еще могут нехило подорожать.
Для меня ответ совершенно очевиден: потому что Facebook делает ужасный по качеству продукт. Да, у него монопольное положение и да, им пользуется огромное количество людей. Но мир не стоит на месте. Когда-то владельцам Нокии было смешно от первого Айфона. Они думали, что лучше Нокии ничего быть не может и она навсегда останется самым удобным, красивым и твёрдым телефоном - и доля рынка это красноречиво демонстрировала. Теперь им не смешно.
Конечно, рептилоиды сопротивляются напору молодых гениев: так Цукербергом был пожран Whatsapp, потом Instagram. Но всё им не пожрать, Паша Дуров не продаётся!
Так будет и с Фейсбуком. Нельзя всё время делать говно. Кто-то когда-то сделает хороший продукт, куда всё и уйдут.
#соцсети #facebook #акции #рептилоиды',
'reply_markup' => bless( {
'rows' => [
bless( {
'buttons' => [
bless( {
'data' => 'send_reaction_0',
'text' => '???? 452'
}, 'Telegram::KeyboardButtonCallback' ),
bless( {
'text' => '???? 21',
'data' => 'send_reaction_1'
}, 'Telegram::KeyboardButtonCallback' )
]
}, 'Telegram::KeyboardButtonRow' )
]
}, 'Telegram::ReplyInlineMarkup' ),
'entities' => [
bless( {
'length' => 199,
'offset' => 0
}, 'Telegram::MessageEntityBold' ),
bless( {
'length' => 8,
'offset' => 919
}, 'Telegram::MessageEntityHashtag' ),
bless( {
'offset' => 928,
'length' => 9
}, 'Telegram::MessageEntityHashtag' ),
bless( {
'length' => 6,
'offset' => 938
}, 'Telegram::MessageEntityHashtag' ),
bless( {
'length' => 11,
'offset' => 945
}, 'Telegram::MessageEntityHashtag' )
],
'views' => 6964,
'flags' => 50368,
'id' => 854,
'post' => 1
}, 'Telegram::Message' ),
'pts_count' => 0
}, 'Telegram::UpdateEditChannelMessage' ),
bless( {
'message' => bless( {
'reply_markup' => bless( {
'rows' => [
bless( {
'buttons' => [
bless( {
'data' => 'send_reaction_0',
'text' => '???? 213'
}, 'Telegram::KeyboardButtonCallback' ),
bless( {
'data' => 'send_reaction_1',
'text' => '???? 8'
}, 'Telegram::KeyboardButtonCallback' )
]
}, 'Telegram::KeyboardButtonRow' )
]
}, 'Telegram::ReplyInlineMarkup' ),
'views' => 2940,
'entities' => [
bless( {
'length' => 609,
'offset' => 348
}, 'Telegram::MessageEntityItalic' )
],
'flags' => 50368,
'post' => 1,
'id' => 857,
'edit_date' => 1571907636,
'date' => 1571902479,
'to_id' => bless( {
'channel_id' => 1380524958
}, 'Telegram::PeerChannel' ),
'message' => 'Пост про 1С вызвал бурную полемику. Человек 10 (видимо, 1с-программистов) единодушно написали:
// [текст сообщения вырезан чтоб не нарушать правил Хабра о рекламе]
Я бы добавил, что блестящая у 1С дистрибуция, а маркетинг... ну, такое.'
}, 'Telegram::Message' ),
'pts_count' => 0,
'pts' => 158508
}, 'Telegram::UpdateEditChannelMessage' ),
bless( {
'pts' => 158508,
'pts_count' => 0,
'message' => bless( {
'message' => 'Здравствуйте, расскажите, пожалуйста, чем вредит экономике 1С?
// [текст сообщения вырезан чтоб не нарушать правил Хабра о рекламе]
#софт #it #экономика',
'edit_date' => 1571907650,
'date' => 1571893707,
'to_id' => bless( {
'channel_id' => 1380524958
}, 'Telegram::PeerChannel' ),
'flags' => 50368,
'post' => 1,
'id' => 856,
'reply_markup' => bless( {
'rows' => [
bless( {
'buttons' => [
bless( {
'data' => 'send_reaction_0',
'text' => '???? 360'
}, 'Telegram::KeyboardButtonCallback' ),
bless( {
'data' => 'send_reaction_1',
'text' => '???? 32'
}, 'Telegram::KeyboardButtonCallback' )
]
}, 'Telegram::KeyboardButtonRow' )
]
}, 'Telegram::ReplyInlineMarkup' ),
'views' => 4416,
'entities' => [
bless( {
'offset' => 0,
'length' => 64
}, 'Telegram::MessageEntityBold' ),
bless( {
'offset' => 1551,
'length' => 5
}, 'Telegram::MessageEntityHashtag' ),
bless( {
'length' => 3,
'offset' => 1557
}, 'Telegram::MessageEntityHashtag' ),
bless( {
'offset' => 1561,
'length' => 10
}, 'Telegram::MessageEntityHashtag' )
]
}, 'Telegram::Message' )
}, 'Telegram::UpdateEditChannelMessage' )
]
}, 'Telegram::Updates::ChannelDifference' )
}, 'MTProto::RpcResult' )
};
2019.10.24 12:00:51 $1 = {
'in' => bless( {
'update' => bless( {
'user_id' => 2507460,
'status' => bless( {
'was_online' => 1571907651
}, 'Telegram::UserStatusOffline' )
}, 'Telegram::UpdateUserStatus' ),
'date' => 1571907650
}, 'Telegram::UpdateShort' )
};
2019.10.24 12:05:46 $1 = {
'in' => bless( {
'chats' => [],
'date' => 1571907946,
'seq' => 0,
'updates' => [
bless( {
'max_id' => 141719,
'channel_id' => 1295963795
}, 'Telegram::UpdateReadChannelInbox' )
],
'users' => []
}, 'Telegram::Updates' )
};
2019.10.24 13:01:23 $1 = {
'in' => bless( {
'server_salt' => '4914425622822907323',
'unique_id' => '5297282355827493819',
'first_msg_id' => '6751307555044380692'
}, 'MTProto::NewSessionCreated' )
};
2019.10.24 13:24:21 $1 = {
'in' => bless( {
'chats' => [
bless( {
'username' => 'freebsd_ru',
'version' => 0,
'flags' => 5440,
'title' => 'freebsd_ru',
'min' => 1,
'photo' => bless( {
'photo_small' => bless( {
'local_id' => 328733,
'volume_id' => 235140688,
'dc_id' => 2,
'file_reference' => '
'secret' => '4426006807282303416'
}, 'Telegram::FileLocation' ),
'photo_big' => bless( {
'dc_id' => 2,
'file_reference' => '
'volume_id' => 235140688,
'local_id' => 328735,
'secret' => '71251192991540083'
}, 'Telegram::FileLocation' )
}, 'Telegram::ChatPhoto' ),
'date' => 1461248502,
'id' => 1038300508,
'democracy' => 1,
'megagroup' => 1
}, 'Telegram::Channel' )
],
'users' => [
bless( {
'last_name' => 'Panov',
'flags' => 1048646,
'min' => 1,
'id' => 82234609,
'status' => bless( {}, 'Telegram::UserStatusRecently' ),
'first_name' => 'Dima'
}, 'Telegram::User' )
],
'seq' => 0,
'date' => 1571912647,
'updates' => [
bless( {
'pts' => 137596,
'message' => bless( {
'flags' => 256,
'message' => 'Создать джейл с именем покороче ??',
'to_id' => bless( {
'channel_id' => 1038300508
}, 'Telegram::PeerChannel' ),
'id' => 119634,
'date' => 1571912647,
'from_id' => 82234609
}, 'Telegram::Message' ),
'pts_count' => 1
}, 'Telegram::UpdateNewChannelMessage' )
]
}, 'Telegram::Updates' )
};

បាទ មិនមែនជាការបំភ្លៃតាមគោលបំណងទេ - ប្រសិនបើអ្នកមិនទាន់បានអានវាទេ សូមបន្តធ្វើវាទៅ!

អូយ~~... មើលទៅដូចអ្វី? អ្វីមួយដែលធ្លាប់ស្គាល់... ប្រហែលជានេះគឺជារចនាសម្ព័ន្ធទិន្នន័យនៃ Web API ធម្មតានៅក្នុង JSON លើកលែងតែថ្នាក់ត្រូវបានភ្ជាប់ជាមួយវត្ថុដែរ?..

ដូច្នេះនេះជារបៀបដែលវាប្រែចេញ ... តើវានិយាយអំពីអ្វី? សមមិត្ត? .. ការខិតខំប្រឹងប្រែងយ៉ាងខ្លាំង - ហើយយើងបានឈប់សម្រាកដែលជាកន្លែងដែលអ្នកសរសេរកម្មវិធីគេហទំព័រ ទើបតែចាប់ផ្តើម?... មិនមែនគ្រាន់តែ JSON លើ HTTPS កាន់តែសាមញ្ញទេ?! តើយើងទទួលបានអ្វីជាថ្នូរនឹង? តើ​ការ​ខិត​ខំ​នោះ​មាន​តម្លៃ​ទេ?

ចូរយើងវាយតម្លៃនូវអ្វីដែល TL+MTProto ផ្តល់ឱ្យយើង និងជម្រើសផ្សេងទៀតដែលអាចធ្វើទៅបាន។ ជាការប្រសើរណាស់ HTTP ដែលផ្តោតលើគំរូឆ្លើយតបការស្នើសុំគឺសមល្អ ប៉ុន្តែយ៉ាងហោចណាស់មានអ្វីមួយនៅលើ TLS?

បង្រួមសៀរៀល។ ដោយមើលឃើញរចនាសម្ព័ន្ធទិន្នន័យនេះ ស្រដៀងទៅនឹង JSON ខ្ញុំចាំថាមានកំណែគោលពីររបស់វា។ ចូរសម្គាល់ MsgPack ថាមិនអាចពង្រីកបានគ្រប់គ្រាន់ ប៉ុន្តែមានឧទាហរណ៍ CBOR - ដោយវិធីនេះ ស្តង់ដារដែលបានពិពណ៌នានៅក្នុង RFC 7049. វាគួរឱ្យកត់សម្គាល់សម្រាប់ការពិតដែលថាវាកំណត់ ស្លាកជាយន្តការពង្រីក និងក្នុងចំណោម ស្តង់ដាររួចហើយ អាចប្រើបាន៖

  • 25 + 256 - ជំនួសបន្ទាត់ម្តងហើយម្តងទៀតដោយយោងទៅលេខបន្ទាត់ វិធីសាស្ត្របង្ហាប់ថោកបែបនេះ
  • 26 - វត្ថុ Perl ស៊េរីដែលមានឈ្មោះថ្នាក់ និងអាគុយម៉ង់អ្នកសាងសង់
  • 27 - វត្ថុឯករាជ្យនៃភាសាដែលមានសៀរៀលជាមួយឈ្មោះប្រភេទ និងអាគុយម៉ង់អ្នកសាងសង់

ជាការប្រសើរណាស់, ខ្ញុំបានព្យាយាមធ្វើសៀរៀលទិន្នន័យដូចគ្នានៅក្នុង TL និងនៅក្នុង CBOR ជាមួយនឹងខ្សែអក្សរ និងការវេចខ្ចប់វត្ថុដែលបានបើក។ លទ្ធផលបានចាប់ផ្តើមប្រែប្រួលនៅក្នុងការពេញចិត្ត CBOR នៅកន្លែងណាមួយពីមេកាបៃ៖

cborlen=1039673 tl_len=1095092

ហើយដូច្នេះ, ការសន្និដ្ឋាន៖ មានទម្រង់សាមញ្ញជាងច្រើន ដែលមិនមែនជាប្រធានបទនៃបញ្ហានៃការបរាជ័យក្នុងការធ្វើសមកាលកម្ម ឬមិនស្គាល់អត្តសញ្ញាណ ដោយប្រសិទ្ធភាពអាចប្រៀបធៀបបាន។

ការបង្កើតការតភ្ជាប់រហ័ស. នេះមានន័យថាសូន្យ RTT បន្ទាប់ពីការភ្ជាប់ឡើងវិញ (នៅពេលដែលសោត្រូវបានបង្កើតម្តងរួចហើយ) - អាចអនុវត្តបានពីសារ MTProto ដំបូង ប៉ុន្តែជាមួយនឹងការកក់មួយចំនួន - បុកអំបិលដូចគ្នា វគ្គមិនរលួយ។ល។ តើ TLS ផ្តល់ឱ្យយើងនូវអ្វីជំនួសវិញ? សម្រង់លើប្រធានបទ៖

នៅពេលប្រើ PFS ក្នុង TLS សំបុត្រវគ្គ TLS (RFC 5077) ដើម្បីបន្តវគ្គដែលបានអ៊ិនគ្រីបដោយមិនចាំបាច់ចរចាឡើងវិញនូវសោរ និងដោយមិនរក្សាទុកព័ត៌មានសំខាន់ៗនៅលើម៉ាស៊ីនមេ។ នៅពេលបើកការតភ្ជាប់ដំបូង និងបង្កើតកូនសោ នោះម៉ាស៊ីនមេនឹងអ៊ិនគ្រីបស្ថានភាពនៃការតភ្ជាប់ ហើយបញ្ជូនវាទៅអតិថិជន (ក្នុងទម្រង់ជាសំបុត្រសម័យ)។ ដូច្នោះហើយ នៅពេលដែលការតភ្ជាប់ត្រូវបានបន្ត អតិថិជនផ្ញើសំបុត្រវគ្គ រួមទាំងសោវគ្គ ត្រឡប់ទៅម៉ាស៊ីនមេវិញ។ សំបុត្រខ្លួនវាត្រូវបានអ៊ិនគ្រីបដោយប្រើសោបណ្តោះអាសន្ន (សោសំបុត្រវគ្គ) ដែលត្រូវបានរក្សាទុកនៅលើម៉ាស៊ីនមេ ហើយត្រូវតែចែកចាយក្នុងចំណោមម៉ាស៊ីនមេផ្នែកខាងមុខទាំងអស់ដែលកំពុងដំណើរការ SSL នៅក្នុងដំណោះស្រាយជាក្រុម។[10]។ ដូច្នេះ ការណែនាំនៃសំបុត្រសម័យអាចបំពាន PFS ប្រសិនបើសោម៉ាស៊ីនមេបណ្តោះអាសន្នត្រូវបានសម្របសម្រួល ឧទាហរណ៍ នៅពេលដែលពួកវាត្រូវបានរក្សាទុកក្នុងរយៈពេលយូរ (OpenSSL, nginx, Apache រក្សាទុកពួកវាតាមលំនាំដើមសម្រាប់រយៈពេលទាំងមូលនៃកម្មវិធី។ គេហទំព័រពេញនិយមប្រើ គន្លឹះជាច្រើនម៉ោងរហូតដល់ថ្ងៃ) ។

នៅទីនេះ RTT មិនមែនសូន្យទេ អ្នកត្រូវផ្លាស់ប្តូរយ៉ាងហោចណាស់ ClientHello និង ServerHello បន្ទាប់ពីនោះអតិថិជនអាចផ្ញើទិន្នន័យរួមជាមួយនឹង Finished ។ ប៉ុន្តែនៅទីនេះ យើងគួរចងចាំថា យើងមិនមានបណ្តាញទេ ជាមួយនឹងបណ្តុំនៃការតភ្ជាប់ដែលទើបនឹងបើកថ្មី ប៉ុន្តែអ្នកនាំសារ ការតភ្ជាប់ដែលច្រើនតែមានមួយ ឬច្រើន ឬតិចជាងរយៈពេលវែង សំណើខ្លីទាក់ទងទៅទំព័របណ្តាញ - អ្វីគ្រប់យ៉ាងត្រូវបានពហុគុណ។ ខាងក្នុង។ នោះ​គឺ​ជា​ការ​ទទួល​យក​បាន​ណាស់​ប្រសិន​បើ​យើង​មិន​បាន​ជួប​ផ្នែក​ផ្លូវ​ក្រោម​ដី​ដ៏​អាក្រក់។

ភ្លេចអ្វីផ្សេងទៀត? សរសេរនៅក្នុងមតិយោបល់។

នៅ​មាន​ជា​បន្ត​ទៀត!

នៅក្នុងផ្នែកទីពីរនៃស៊េរីនៃការប្រកាសនេះ យើងនឹងពិចារណាមិនមែនជាបញ្ហាបច្ចេកទេស ប៉ុន្តែបញ្ហារបស់ស្ថាប័ន - វិធីសាស្រ្ត មនោគមវិជ្ជា ចំណុចប្រទាក់ អាកប្បកិរិយាចំពោះអ្នកប្រើប្រាស់។ល។ យ៉ាង​ណា​ក៏​ដោយ ផ្អែក​លើ​ព័ត៌មាន​បច្ចេកទេស​ដែល​ត្រូវ​បាន​បង្ហាញ​នៅ​ទីនេះ។

ផ្នែកទីបីនឹងបន្តវិភាគសមាសភាគបច្ចេកទេស / បទពិសោធន៍អភិវឌ្ឍន៍។ អ្នកនឹងរៀនជាពិសេស៖

  • ការបន្តនៃ pandemonium ជាមួយនឹងភាពខុសគ្នានៃប្រភេទ TL
  • អ្វីដែលមិនស្គាល់អំពីប៉ុស្តិ៍ និងក្រុមជាន់ខ្ពស់
  • ហេតុអ្វីបានជាប្រអប់គឺអាក្រក់ជាងបញ្ជីឈ្មោះ
  • អំពី absolute vs relative message addressing
  • តើអ្វីជាភាពខុសគ្នារវាងរូបថតនិងរូបភាព
  • របៀបដែល emoji ជ្រៀតជ្រែកជាមួយអក្សរទ្រេត

និងឈើច្រត់ផ្សេងទៀត! ចាំមើល!

ប្រភព: www.habr.com

បន្ថែមមតិយោបល់