{"id":325564,"date":"2021-06-27T15:00:29","date_gmt":"2021-06-27T15:00:29","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=325564"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=325564","title":{"rendered":"gRPC + Dart, \u0421\u0435\u0440\u0432\u0438\u0441 + \u041a\u043b\u0438\u0435\u043d\u0442, \u043d\u0430\u043f\u0438\u0448\u0435\u043c? \u0427\u0430\u0441\u0442\u044c 3"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/563518\/\" rel=\"noopener noreferrer nofollow\">\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/563986\/\" rel=\"noopener noreferrer nofollow\">\u0412\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u044f \u0410\u043d\u0434\u0440\u0435\u0439, \u0440\u0430\u0431\u043e\u0442\u0430\u044e Flutter \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0424\u0438\u043d\u0430\u043c.<\/p>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 Umka. <\/p>\n<h3>\u042d\u043a\u0437\u0430\u043c\u0435\u043d<\/h3>\n<p>\u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f &#171;\u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430&#187; \u043c\u044b \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 gRPC \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0442\u043e\u043a\u0430 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<p>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430 \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c: <\/p>\n<ul>\n<li>\n<p>\u0423\u0447\u0435\u043d\u0438\u043a \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 &#171;\u042d\u043a\u0437\u0430\u043c\u0435\u043d&#187;, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0438\u0437 \u0441\u0435\u0431\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0447\u0435\u043d\u0438\u043a \u043f\u043e\u043e\u0447\u0435\u0440\u0451\u0434\u043d\u043e, \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441, \u0432\u0432\u043e\u0434\u0438\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u043e\u0442\u0432\u0435\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0443\u0442 \u0436\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043e\u0442\u0432\u0435\u0442 \u0432\u0435\u0440\u0435\u043d, \u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441 \u043a \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u043e\u0446\u0435\u043d\u043a\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 1.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u0446\u0435\u043d\u043a\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u0430, \u0441\u0435\u0440\u0432\u0438\u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0447\u0435\u043d\u0438\u043a\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/h4>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043e\u0434\u043d\u0438\u043c \u0442\u0438\u043f\u043e\u043c <code>Exam<\/code> \u0438 \u0434\u0432\u0443\u043c\u044f \u0432\u044b\u0437\u043e\u0432\u0430\u043c\u0438 <code>getExam<\/code>, <code>takeExam<\/code>:<\/p>\n<pre><code>syntax=\"proto3\";  message Student {   int32 id = 1;   string name = 2; }  message Question {   int32 id = 1;   string text = 2; }  message Answer {   int32 id = 1;   Student student = 2;   Question question = 3;   string text = 4; }  message Evaluation {   int32 id = 1;   int32 answerId = 2;   int32 mark = 3; }  message AnsweredQuestion {   Question question = 1;   string answer = 2; }  message Exam {   int32 id = 1;   repeated Question questions = 2; }  service Umka {   rpc getQuestion(Student) returns(Question) {}    rpc sendAnswer(Answer) returns(Evaluation) {}    rpc getTutorial(Student) returns (stream AnsweredQuestion) {}    rpc getExam(Student) returns (Exam) {}    rpc takeExam(stream Answer) returns(Evaluation) {} } <\/code><\/pre>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e <strong>repeated<\/strong> \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u0435 <code>questions<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043f\u0438\u0441\u043e\u043a. \u0414\u043b\u044f \u044f\u0437\u044b\u043a\u0430 Dart \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 <code>List&lt;Question&gt;<\/code>.<\/p>\n<p>\u0412 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 <code>rpc takeExam(stream Answer) returns(Evaluation) {}<\/code> \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f <strong>stream<\/strong> \u043f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u043c \u0442\u0438\u043f\u043e\u043c <code>Answer<\/code> \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443 <strong>protoc<\/strong>, \u0447\u0442\u043e \u043a\u043e\u0434 \u043d\u0443\u0436\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0441\u0435\u0440\u0432\u0438\u0441 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u043e\u0442\u0432\u0435\u0442\u044b \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0442\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c &#171;\u0440\u0435\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e&#187; \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e Dart \u043a\u043e\u0434\u0430:<\/p>\n<p><code>protoc -I protos\/ protos\/umka.proto --dart_out=grpc:lib\/generated<\/code><\/p>\n<h4>\u0414\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/h4>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441 <code>UmkaService<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>getExam<\/code> \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430 \u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u0430:<\/p>\n<pre><code>  @override   Future&lt;Exam&gt; getExam(ServiceCall call, Student request) async {     final exam = Exam()..id = 1;     exam.questions.addAll(questionsDb);     return exam;   } <\/code><\/pre>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438\u0437 \u043d\u0430\u0448\u0435\u0439 &#171;\u0431\u0430\u0437\u044b&#187;.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u0430 <code>takeExam<\/code> \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u0434\u0430:<\/p>\n<pre><code>  @override   Future&lt;Evaluation&gt; takeExam(ServiceCall call, Stream&lt;Answer&gt; asnswers) async {        var score = 0;          await for (var answer in asnswers) {       final isCorrect = getCorrectAnswerById(answer.question.id) == answer.text;              print('Received an answer from ${answer.student.name}\\n'           'for a question: ${answer.question.text}'           'answer: ${answer.text} is correct: $isCorrect');                  if (isCorrect) {         score++;       }     }      print('The student: ${call.clientMetadata?['student_name']}'         ' finished exam with the score: $score');              return Evaluation()       ..id = 1       ..mark = score;   } } <\/code><\/pre>\n<ul>\n<li>\n<p>\u0412 <code>await for<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043e\u0442\u0432\u0435\u0442\u044b \u0438\u0437 \u043f\u043e\u0442\u043e\u043a\u0430, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>var score = 0;<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0431\u0430\u043b\u043b \u0437\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430, &#171;\u043a\u043b\u0438\u0435\u043d\u0442&#187; \u0437\u0430\u043a\u0440\u043e\u0435\u0442 \u0441\u0442\u0440\u0438\u043c, \u0430 \u043c\u044b (\u0441\u0435\u0440\u0432\u0438\u0441) \u0432\u0435\u0440\u043d\u0451\u043c \u0435\u043c\u0443 \u043e\u0446\u0435\u043d\u043a\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e \u0445\u043e\u0434\u0443 &#171;\u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430&#187;.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0443\u0441\u043e\u0447\u0435\u043a \u043a\u043e\u0434\u0430 <code>call.clientMetadata?['student_name']<\/code> \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c. \u041f\u043e \u0441\u0432\u043e\u0435\u0439 \u0441\u0443\u0442\u0438, &#171;\u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c&#187;, \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 HTTP\/2 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<h4>\u0414\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/h4>\n<p>\u0412 <code>UmkaTerminalClient<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 <code>takeExam<\/code>:<\/p>\n<pre><code>  Future&lt;Evaluation&gt; takeExam(Student student) async {     final exam = await stub.getExam(student);      final questions = exam.questions;      final answersStream = StreamController&lt;Answer&gt;();      final evaluationFuture = stub.takeExam(answersStream.stream,         options: CallOptions(metadata: {'student_name': '${student.name}'}));      for (var question in questions) {       final answer = Answer()         ..question = question         ..student = student;        print('Enter the answer for the question: ${question.text}');              answer.text = stdin.readLineSync()!;        answersStream.add(answer);        await Future.delayed(Duration(milliseconds: 1));     }     unawaited(answersStream.close());      return evaluationFuture;   } <\/code><\/pre>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u043e\u043f\u0440\u043e\u0441\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u043e\u0442\u043e\u043a \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043e\u0442\u0432\u0435\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u043d\u0430 \u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 &#171;\u0441\u0442\u0440\u0438\u043c&#187; \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435: <code>'student_name'<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441, \u043f\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u0438, \u0443\u0447\u0435\u043d\u0438\u043a \u0432\u0432\u043e\u0434\u0438\u0442 \u043e\u0442\u0432\u0435\u0442 \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u0442\u043e\u043a: <code>answersStream.add(answer);<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043e\u0442\u0432\u0435\u0442, \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445: <code>unawaited(answersStream.close());<\/code><\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c Future \u0441 \u043e\u0446\u0435\u043d\u043a\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>unawated<\/code> \u043d\u0443\u0436\u043d\u0430 \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443, \u0447\u0442\u043e \u043c\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b \u0432 \u0441\u0432\u043e\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u0445 \u0438 \u043e\u043d \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u043b &#171;\u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435&#187;.<\/p>\n<p>\u041e\u043d\u0430 \u043f\u043e\u043a\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <strong>pedantic<\/strong>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0435 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c19\/5ab\/9b9\/c195ab9b96276ca64d70836a4c9d92fe.png\" width=\"648\" height=\"424\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <code>dart pub get<\/code>.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0430\u043a:<\/p>\n<pre><code>  Future&lt;void&gt; callService(Student student) async {     final evaluation = await takeExam(student);     print('${student.name}, your exam score is: ${evaluation.mark}');     await channel.shutdown();   } <\/code><\/pre>\n<ul>\n<li>\n<p>\u0414\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0441\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f &#171;\u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430&#187;, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0446\u0435\u043d\u043a\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/768\/078\/210\/768078210436a44349353e4f261a33b1.png\" width=\"2276\" height=\"1608\"><figcaption><\/figcaption><\/figure>\n<h4>\u0417\u0430\u043f\u0443\u0441\u043a \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430<\/h4>\n<p>\u0412 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u043a\u043d\u0430\u0445 \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<ul>\n<li>\n<p>\u0421\u0435\u0440\u0432\u0438\u0441: <code>dart lib\/service.dart<\/code><\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435: <code>dart lib\/client.dart<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f &#171;\u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430&#187;:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/633\/08d\/a27\/63308da27ba21681856084f22e194ccb.gif\" width=\"515\" height=\"488\"><figcaption><\/figcaption><\/figure>\n<p>&#171;\u0421\u0442\u0443\u0434\u0435\u043d\u0442&#187; \u0412\u0430\u043d\u044f \u043e\u043f\u0435\u0447\u0430\u0442\u0430\u043b\u0441\u044f \u043f\u0440\u0438 \u043e\u0442\u0432\u0435\u0442\u0435 \u043d\u0430 \u0442\u0440\u0435\u0442\u0438\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b &#171;\u0447\u0435\u0442\u0432\u0451\u0440\u043a\u0443&#187;.<\/p>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e<\/h3>\n<p>\u041c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443. \u041f\u0430\u0440\u043e\u0439-\u0442\u0440\u043e\u0439\u043a\u043e\u0439 \u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432 \u0441\u0442\u0440\u043e\u0447\u0435\u043a \u043a\u043e\u0434\u0430 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0447\u0430\u0442, \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c gRPC \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043a \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e HTTP\/2 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0438\u043f:<\/p>\n<pre><code>message InterviewMessage {   string name = 1;   string body = 2; } <\/code><\/pre>\n<p>\u0418 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432:<\/p>\n<pre><code>rpc techInterview(stream InterviewMessage) returns(stream InterviewMessage) {} <\/code><\/pre>\n<p>\u0412\u043d\u043e\u0432\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c &#171;\u0440\u0435\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e&#187; \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0432 \u0432 \u043f\u0430\u043f\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<p><code>protoc -I protos\/ protos\/umka.proto --dart_out=grpc:lib\/generated<\/code><\/p>\n<h4>\u041a\u043e\u0434 \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/h4>\n<p>\u041d\u0430 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0444\u0430\u0439\u043b\u0430 <strong>lib\/service.dart<\/strong> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u0441 \u0442\u0438\u043f\u0447\u043d\u044b\u043c\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438 &#171;\u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f&#187;:<\/p>\n<pre><code>const interviewQuestions = [   'What was wrong in your previous job place?',   'Why do you want to work for Us?',   'Who do you see yourself in 5 years?',   'We will inform you about the decision. Bye!', ]; <\/code><\/pre>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441 <code>UmkaService<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<pre><code>  InterviewMessage _createMessage(String text, {String name = 'Interviewer'}) =&gt;       InterviewMessage()         ..name = name         ..body = text; <\/code><\/pre>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>techInterview<\/code>:<\/p>\n<pre><code>  @override   Stream&lt;InterviewMessage&gt; techInterview(       ServiceCall call, Stream&lt;InterviewMessage&gt; interviewStream) async* {     var count = 0;      await for (var message in interviewStream) {       print('Candidate ${message.name} message: ${message.body}');       if (count &gt;= interviewQuestions.length) {         return;       } else {         yield _createMessage(interviewQuestions[count++]);       }     }   } <\/code><\/pre>\n<ul>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430, \u0447\u0442\u043e \u043e\u043d \u0433\u043e\u0442\u043e\u0432 \u043a \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u043c\u0443 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0434\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0441\u044f \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0432\u043e\u043f\u0440\u043e\u0441, &#171;\u0432\u044b\u0445\u043e\u0434\u0438\u043c&#187; \u2014 \u0441\u0442\u0440\u0438\u043c <code>interviewStream<\/code> \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043a\u0440\u044b\u0442.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/481\/de1\/8ee\/481de18ee0e473875ae0c57d7e2bdf4b.png\" width=\"1712\" height=\"1656\"><figcaption><\/figcaption><\/figure>\n<h4>\u041a\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>&#171;\u041d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435&#187; \u043a\u043e\u0434 \u043c\u0435\u0442\u043e\u0434\u0430 <code>techInterview<\/code> \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<pre><code>  Future&lt;void&gt; techInterview(String candidateName) async {     final candidateStream = StreamController&lt;InterviewMessage&gt;();     final interviewerStream = stub.techInterview(candidateStream.stream);      candidateStream.add(InterviewMessage()       ..name = candidateName       ..body = 'I am ready!');      await for (var message in interviewerStream) {       print('\\nMessage from the ${message.name}:\\n${message.body}\\n');        print('Enter your answer:');        final answer = stdin.readLineSync();        candidateStream.add(InterviewMessage()..body = answer!);     }      unawaited(candidateStream.close());   } <\/code><\/pre>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0442\u0440\u0438\u043c <code>final candidateStream = StreamController&lt;InterviewMessage&gt;();<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c <code>candidateStream<\/code> \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u0432\u044b\u0437\u043e\u0432\u0443, \u043f\u043e\u043b\u0443\u0447\u0430\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e <code>interviewerStream<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0447\u0442\u043e \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u0433\u043e\u0442\u043e\u0432 \u043a \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u044f\u0437\u0430\u0442\u044c &#171;\u0434\u0438\u0430\u043b\u043e\u0433&#187;.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043b\u0435\u0434\u0438\u043c \u0437\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u043c\u0438 \u0432 <code>interviewerStream<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0432\u0435\u0442\u044b \u0432\u0432\u043e\u0434\u0438\u043c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b.<\/p>\n<\/li>\n<li>\n<p>\u0427\u0438\u0442\u0430\u0435\u043c \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435. <\/p>\n<\/li>\n<\/ul>\n<p>\u041a \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0442\u0430\u043a:<\/p>\n<pre><code>  Future&lt;void&gt; callService(Student student) async {     await techInterview(student.name);     await channel.shutdown();   } <\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/13f\/2b6\/13c\/13f2b613cd4ac0c840eab3c204ff6f2a.png\" width=\"1584\" height=\"1608\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u043e\u0442 \u0433\u0438\u0444\u043a\u0430 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0449\u0430\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441 &#171;\u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e&#187;. \u0412 \u043d\u0438\u0436\u043d\u0435\u043c \u043e\u043a\u043d\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e\u0435\u0440, \u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u044b.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2da\/5b8\/cfd\/2da5b8cfd3eca3ce5e77474db36af643.gif\" width=\"463\" height=\"673\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043c \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u0433\u0434\u0435 \u043c\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0432 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u0432\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0435\u0449\u0451 \u0434\u0432\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439 gRPC:<\/p>\n<ul>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0442\u043e\u043a\u0430 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0414\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0436\u0434\u0443 &#171;\u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c&#187; \u0438 &#171;\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c&#187; \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e HTTP\/2 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u043c\u044b \u0443\u0441\u043f\u0435\u043b\u0438 \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 gRPC.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0440\u044b\u0432\u0430, \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0441\u044f\u0446-\u0434\u0440\u0443\u0433\u043e\u0439, \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0435\u0440\u0438\u044e. \u0412 \u043f\u043b\u0430\u043d\u0430\u0445 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u043e\u0433\u043e \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e Flutter \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c Umka, &#171;\u0434\u0435\u043f\u043b\u043e\u0439&#187; \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440, &#8230; .<\/p>\n<p>\u0414\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0438 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438!<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/564910\/\"> https:\/\/habr.com\/ru\/post\/564910\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/563518\/\" rel=\"noopener noreferrer nofollow\">\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/563986\/\" rel=\"noopener noreferrer nofollow\">\u0412\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u044f \u0410\u043d\u0434\u0440\u0435\u0439, \u0440\u0430\u0431\u043e\u0442\u0430\u044e Flutter \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0424\u0438\u043d\u0430\u043c.<\/p>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 Umka. <\/p>\n<h3>\u042d\u043a\u0437\u0430\u043c\u0435\u043d<\/h3>\n<p>\u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f &#171;\u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430&#187; \u043c\u044b \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 gRPC \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0442\u043e\u043a\u0430 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<p>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430 \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c: <\/p>\n<ul>\n<li>\n<p>\u0423\u0447\u0435\u043d\u0438\u043a \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 &#171;\u042d\u043a\u0437\u0430\u043c\u0435\u043d&#187;, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0438\u0437 \u0441\u0435\u0431\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0447\u0435\u043d\u0438\u043a \u043f\u043e\u043e\u0447\u0435\u0440\u0451\u0434\u043d\u043e, \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441, \u0432\u0432\u043e\u0434\u0438\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u043e\u0442\u0432\u0435\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0443\u0442 \u0436\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043e\u0442\u0432\u0435\u0442 \u0432\u0435\u0440\u0435\u043d, \u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441 \u043a \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u043e\u0446\u0435\u043d\u043a\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 1.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u0446\u0435\u043d\u043a\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u0430, \u0441\u0435\u0440\u0432\u0438\u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0447\u0435\u043d\u0438\u043a\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/h4>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043e\u0434\u043d\u0438\u043c \u0442\u0438\u043f\u043e\u043c <code>Exam<\/code> \u0438 \u0434\u0432\u0443\u043c\u044f \u0432\u044b\u0437\u043e\u0432\u0430\u043c\u0438 <code>getExam<\/code>, <code>takeExam<\/code>:<\/p>\n<pre><code>syntax=\"proto3\";  message Student {   int32 id = 1;   string name = 2; }  message Question {   int32 id = 1;   string text = 2; }  message Answer {   int32 id = 1;   Student student = 2;   Question question = 3;   string text = 4; }  message Evaluation {   int32 id = 1;   int32 answerId = 2;   int32 mark = 3; }  message AnsweredQuestion {   Question question = 1;   string answer = 2; }  message Exam {   int32 id = 1;   repeated Question questions = 2; }  service Umka {   rpc getQuestion(Student) returns(Question) {}    rpc sendAnswer(Answer) returns(Evaluation) {}    rpc getTutorial(Student) returns (stream AnsweredQuestion) {}    rpc getExam(Student) returns (Exam) {}    rpc takeExam(stream Answer) returns(Evaluation) {} } <\/code><\/pre>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e <strong>repeated<\/strong> \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u0435 <code>questions<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043f\u0438\u0441\u043e\u043a. \u0414\u043b\u044f \u044f\u0437\u044b\u043a\u0430 Dart \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 <code>List&lt;Question&gt;<\/code>.<\/p>\n<p>\u0412 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 <code>rpc takeExam(stream Answer) returns(Evaluation) {}<\/code> \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f <strong>stream<\/strong> \u043f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u043c \u0442\u0438\u043f\u043e\u043c <code>Answer<\/code> \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443 <strong>protoc<\/strong>, \u0447\u0442\u043e \u043a\u043e\u0434 \u043d\u0443\u0436\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0441\u0435\u0440\u0432\u0438\u0441 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u043e\u0442\u0432\u0435\u0442\u044b \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0442\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c &#171;\u0440\u0435\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e&#187; \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e Dart \u043a\u043e\u0434\u0430:<\/p>\n<p><code>protoc -I protos\/ protos\/umka.proto --dart_out=grpc:lib\/generated<\/code><\/p>\n<h4>\u0414\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/h4>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441 <code>UmkaService<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>getExam<\/code> \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430 \u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u0430:<\/p>\n<pre><code>  @override   Future&lt;Exam&gt; getExam(ServiceCall call, Student request) async {     final exam = Exam()..id = 1;     exam.questions.addAll(questionsDb);     return exam;   } <\/code><\/pre>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438\u0437 \u043d\u0430\u0448\u0435\u0439 &#171;\u0431\u0430\u0437\u044b&#187;.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u0430 <code>takeExam<\/code> \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u0434\u0430:<\/p>\n<pre><code>  @override   Future&lt;Evaluation&gt; takeExam(ServiceCall call, Stream&lt;Answer&gt; asnswers) async {        var score = 0;          await for (var answer in asnswers) {       final isCorrect = getCorrectAnswerById(answer.question.id) == answer.text;              print('Received an answer from ${answer.student.name}\\n'           'for a question: ${answer.question.text}'           'answer: ${answer.text} is correct: $isCorrect');                  if (isCorrect) {         score++;       }     }      print('The student: ${call.clientMetadata?['student_name']}'         ' finished exam with the score: $score');              return Evaluation()       ..id = 1       ..mark = score;   } } <\/code><\/pre>\n<ul>\n<li>\n<p>\u0412 <code>await for<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043e\u0442\u0432\u0435\u0442\u044b \u0438\u0437 \u043f\u043e\u0442\u043e\u043a\u0430, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>var score = 0;<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0431\u0430\u043b\u043b \u0437\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430, &#171;\u043a\u043b\u0438\u0435\u043d\u0442&#187; \u0437\u0430\u043a\u0440\u043e\u0435\u0442 \u0441\u0442\u0440\u0438\u043c, \u0430 \u043c\u044b (\u0441\u0435\u0440\u0432\u0438\u0441) \u0432\u0435\u0440\u043d\u0451\u043c \u0435\u043c\u0443 \u043e\u0446\u0435\u043d\u043a\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e \u0445\u043e\u0434\u0443 &#171;\u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430&#187;.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0443\u0441\u043e\u0447\u0435\u043a \u043a\u043e\u0434\u0430 <code>call.clientMetadata?['student_name']<\/code> \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c. \u041f\u043e \u0441\u0432\u043e\u0435\u0439 \u0441\u0443\u0442\u0438, &#171;\u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c&#187;, \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 HTTP\/2 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<h4>\u0414\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/h4>\n<p>\u0412 <code>UmkaTerminalClient<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 <code>takeExam<\/code>:<\/p>\n<pre><code>  Future&lt;Evaluation&gt; takeExam(Student student) async {     final exam = await stub.getExam(student);      final questions = exam.questions;      final answersStream = StreamController&lt;Answer&gt;();      final evaluationFuture = stub.takeExam(answersStream.stream,         options: CallOptions(metadata: {'student_name': '${student.name}'}));      for (var question in questions) {       final answer = Answer()         ..question = question         ..student = student;        print('Enter the answer for the question: ${question.text}');              answer.text = stdin.readLineSync()!;        answersStream.add(answer);        await Future.delayed(Duration(milliseconds: 1));     }     unawaited(answersStream.close());      return evaluationFuture;   } <\/code><\/pre>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u043e\u043f\u0440\u043e\u0441\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u043e\u0442\u043e\u043a \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043e\u0442\u0432\u0435\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u043d\u0430 \u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 &#171;\u0441\u0442\u0440\u0438\u043c&#187; \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435: <code>'student_name'<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441, \u043f\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u0438, \u0443\u0447\u0435\u043d\u0438\u043a \u0432\u0432\u043e\u0434\u0438\u0442 \u043e\u0442\u0432\u0435\u0442 \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u0442\u043e\u043a: <code>answersStream.add(answer);<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043e\u0442\u0432\u0435\u0442, \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445: <code>unawaited(answersStream.close());<\/code><\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c Future \u0441 \u043e\u0446\u0435\u043d\u043a\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>unawated<\/code> \u043d\u0443\u0436\u043d\u0430 \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443, \u0447\u0442\u043e \u043c\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b \u0432 \u0441\u0432\u043e\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u0445 \u0438 \u043e\u043d \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u043b &#171;\u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435&#187;.<\/p>\n<p>\u041e\u043d\u0430 \u043f\u043e\u043a\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <strong>pedantic<\/strong>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0435 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <code>dart pub get<\/code>.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0430\u043a:<\/p>\n<pre><code>  Future&lt;void&gt; callService(Student student) async {     final evaluation = await takeExam(student);     print('${student.name}, your exam score is: ${evaluation.mark}');     await channel.shutdown();   } <\/code><\/pre>\n<ul>\n<li>\n<p>\u0414\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0441\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f &#171;\u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430&#187;, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0446\u0435\u043d\u043a\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h4>\u0417\u0430\u043f\u0443\u0441\u043a \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430<\/h4>\n<p>\u0412 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u043a\u043d\u0430\u0445 \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<ul>\n<li>\n<p>\u0421\u0435\u0440\u0432\u0438\u0441: <code>dart lib\/service.dart<\/code><\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435: <code>dart lib\/client.dart<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f &#171;\u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430&#187;:<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>&#171;\u0421\u0442\u0443\u0434\u0435\u043d\u0442&#187; \u0412\u0430\u043d\u044f \u043e\u043f\u0435\u0447\u0430\u0442\u0430\u043b\u0441\u044f \u043f\u0440\u0438 \u043e\u0442\u0432\u0435\u0442\u0435 \u043d\u0430 \u0442\u0440\u0435\u0442\u0438\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b &#171;\u0447\u0435\u0442\u0432\u0451\u0440\u043a\u0443&#187;.<\/p>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e<\/h3>\n<p>\u041c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443. \u041f\u0430\u0440\u043e\u0439-\u0442\u0440\u043e\u0439\u043a\u043e\u0439 \u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432 \u0441\u0442\u0440\u043e\u0447\u0435\u043a \u043a\u043e\u0434\u0430 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0447\u0430\u0442, \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c gRPC \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043a \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e HTTP\/2 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0438\u043f:<\/p>\n<pre><code>message InterviewMessage {   string name = 1;   string body = 2; } <\/code><\/pre>\n<p>\u0418 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432:<\/p>\n<pre><code>rpc techInterview(stream InterviewMessage) returns(stream InterviewMessage) {} <\/code><\/pre>\n<p>\u0412\u043d\u043e\u0432\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c &#171;\u0440\u0435\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e&#187; \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0432 \u0432 \u043f\u0430\u043f\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<p><code>protoc -I protos\/ protos\/umka.proto --dart_out=grpc:lib\/generated<\/code><\/p>\n<h4>\u041a\u043e\u0434 \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/h4>\n<p>\u041d\u0430 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0444\u0430\u0439\u043b\u0430 <strong>lib\/service.dart<\/strong> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u0441 \u0442\u0438\u043f\u0447\u043d\u044b\u043c\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438 &#171;\u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f&#187;:<\/p>\n<pre><code>const interviewQuestions = [   'What was wrong in your previous job place?',   'Why do you want to work for Us?',   'Who do you see yourself in 5 years?',   'We will inform you about the decision. Bye!', ]; <\/code><\/pre>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441 <code>UmkaService<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<pre><code>  InterviewMessage _createMessage(String text, {String name = 'Interviewer'}) =&gt;       InterviewMessage()         ..name = name         ..body = text; <\/code><\/pre>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>techInterview<\/code>:<\/p>\n<pre><code>  @override   Stream&lt;InterviewMessage&gt; techInterview(       ServiceCall call, Stream&lt;InterviewMessage&gt; interviewStream) async* {     var count = 0;      await for (var message in interviewStream) {       print('Candidate ${message.name} message: ${message.body}');       if (count &gt;= interviewQuestions.length) {         return;       } else {         yield _createMessage(interviewQuestions[count++]);       }     }   } <\/code><\/pre>\n<ul>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430, \u0447\u0442\u043e \u043e\u043d \u0433\u043e\u0442\u043e\u0432 \u043a \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u043c\u0443 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u0434\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0441\u044f \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0432\u043e\u043f\u0440\u043e\u0441, &#171;\u0432\u044b\u0445\u043e\u0434\u0438\u043c&#187; \u2014 \u0441\u0442\u0440\u0438\u043c <code>interviewStream<\/code> \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043a\u0440\u044b\u0442.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h4>\u041a\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>&#171;\u041d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435&#187; \u043a\u043e\u0434 \u043c\u0435\u0442\u043e\u0434\u0430 <code>techInterview<\/code> \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<pre><code>  Future&lt;void&gt; techInterview(String candidateName) async {     final candidateStream = StreamController&lt;InterviewMessage&gt;();     final interviewerStream = stub.techInterview(candidateStream.stream);      candidateStream.add(InterviewMessage()       ..name = candidateName       ..body = 'I am ready!');      await for (var message in interviewerStream) {       print('\\nMessage from the ${message.name}:\\n${message.body}\\n');        print('Enter your answer:');        final answer = stdin.readLineSync();        candidateStream.add(InterviewMessage()..body = answer!);     }      unawaited(candidateStream.close());   } <\/code><\/pre>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0442\u0440\u0438\u043c <code>final candidateStream = StreamController&lt;InterviewMessage&gt;();<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c <code>candidateStream<\/code> \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u0432\u044b\u0437\u043e\u0432\u0443, \u043f\u043e\u043b\u0443\u0447\u0430\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e <code>interviewerStream<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0447\u0442\u043e \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u0433\u043e\u0442\u043e\u0432 \u043a \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u044f\u0437\u0430\u0442\u044c &#171;\u0434\u0438\u0430\u043b\u043e\u0433&#187;.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043b\u0435\u0434\u0438\u043c \u0437\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u043c\u0438 \u0432 <code>interviewerStream<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0432\u0435\u0442\u044b \u0432\u0432\u043e\u0434\u0438\u043c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b.<\/p>\n<\/li>\n<li>\n<p>\u0427\u0438\u0442\u0430\u0435\u043c \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435. <\/p>\n<\/li>\n<\/ul>\n<p>\u041a \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0442\u0430\u043a:<\/p>\n<pre><code>  Future&lt;void&gt; callService(Student student) async {     await techInterview(student.name);     await channel.shutdown();   } <\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u043e\u0442 \u0433\u0438\u0444\u043a\u0430 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0449\u0430\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441 &#171;\u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e&#187;. \u0412 \u043d\u0438\u0436\u043d\u0435\u043c \u043e\u043a\u043d\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e\u0435\u0440, \u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u044b.<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043c \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u0433\u0434\u0435 \u043c\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0432 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u0432\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u044d\u043a\u0437\u0430\u043c\u0435\u043d\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0435\u0449\u0451 \u0434\u0432\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439 gRPC:<\/p>\n<ul>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0442\u043e\u043a\u0430 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0414\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0436\u0434\u0443 &#171;\u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c&#187; \u0438 &#171;\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c&#187; \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e HTTP\/2 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u043c\u044b \u0443\u0441\u043f\u0435\u043b\u0438 \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 gRPC.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0440\u044b\u0432\u0430, \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0441\u044f\u0446-\u0434\u0440\u0443\u0433\u043e\u0439, \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0435\u0440\u0438\u044e. \u0412 \u043f\u043b\u0430\u043d\u0430\u0445 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u043e\u0433\u043e \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e Flutter \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c Umka, &#171;\u0434\u0435\u043f\u043b\u043e\u0439&#187; \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440, &#8230; .<\/p>\n<p>\u0414\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0438 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438!<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/564910\/\"> https:\/\/habr.com\/ru\/post\/564910\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-325564","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/325564","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=325564"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/325564\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=325564"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=325564"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=325564"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}