You do not need to Clear() the Memo before assigning new Text to it. And why would you ignore a blank string if that is what was actually transmitted? Besides, you are not passing a blank string to ZapisVRichEditWindow() anyway, so TUpdateRichEdit doesn't need to check for a blank string.

AllData() does not exit until the client disconnects. Is that what you really want? For that matter, your client is using IOHandler->WriteLn() when it could just use IOHandler->Write() instead.

Unless your clients send data very infrequently, requiring clients to reconnect just to send 1 string is not a very good idea. At the very least, don't disconnect a client unless it has been idle for awhile, say 5-10 minutes. That way, clients that send data frequently benefit from reusing a persistent connection. A simple way to handle that on the server side is to set the IOHandler's ReadTimeout method, and let Indy throw an exception that TIdTCPServer handles if a read operation times out.

Also, instead of using IOHandler->WriteLn() and IOHandler->AllData(), I would suggest using either:

Your OnExecute handler is catching ALL exceptions and discarding them. DO NOT do that. TIdTCPServer relies on being able to handle exceptions for its connection management. At the very least, you should re-throw any EIdException-derived exception you catch:

Your server is expecting clients to send text in UTF-8, but your client code is not specifying any encoding at all, so it will use Indy's default of ASCII instead (see the global GIdDefaultTextEncoding variable in IdGlobal.hpp). That is why you are losing your Russian characters.

You need to specify UTF-8 when sending strings to the server, either by:

That is a perfectly normal exception to get, especially on the server side. You are just not ignoring it. And calling IOHandler->Close() does not prevent that exception from being thrown earlier if the client disconnect prematurely before the server is finished reading (besides, you shouldn't be calling IOHandler->Close() directly anyway, use AContext->Connection->Disconnect() instead).

Also, ShowMessage() is not thread-safe, so DO NOT be using it outside of the main UI thread. Either synchronize it, or use the Win32 API MessageBox() instead.

Lena wrote:I made small changes and now the printer has printed five times everything is normal...

2. If the Windows computer is turned off, the Android application does not respond for a long time. I set IdTCPClient1->ConnectTimeout in 5 seconds. Now everything looks good.3. I replaced nullptr to NUII ([bcc32 Error] UnitPrint.cpp(133): E2451 Undefined symbol 'nullptr'). C++ Builder Berlin. Print Server application create for Win32.4. Will there be thread safe when doing so?

If you absolutely require the client to disconnect after just 1 string is sent, then you could add it, yes. Or just let the server throw an exception when the client disconnects. But, if possible, I would suggest changing the client to not disconnect after each string, reuse a connection as much as feasible. There is overhead in (re)connecting TCP connections.

That is fine, provided that the code which accesses the file is thread-safe, such as wrapping it with a critical section or mutex.

Lena wrote:5. Will I be able In the future to make the client application without code changes for IOS?

Firemonkey and Indy work (roughly) the same way in iOS as they do in Android. So there will be little code change needed.

But, even in Android, you shouldn't be making TCP connections in the main UI thread at all. That is a good way to get your app killed by a mobile OS. Move the TCP connection to a worker thread instead. That will also better facilitate you being able to reuse the connection for sending multiple strings without disconnecting in between.

Lena wrote:6. Files like: #include <Vcl.Printers.hpp> #include <memory>...where it is better to insert before or after #pragma hdrstop or without a difference?

No. Even if the FormMenu object is not freed when it is closed, you are still calling Connect() every time you want to send a new string. Call Connect() only if you are NOT ALREADY connected. Once connected, STAY connected.

I would suggest moving the TIdTCPClient to a background thread (which you have to do anyway if the client app is running on a mobile OS) and then have TFormMenu::Button2Click() delegate to that thread when sending, don't send in the main UI thread.

Sorry I do not quite understand your code please be more detailed:1. Thread = new TMyThread;For this File->New->Other->C++ Builder Files->Thead Object name=TMyThread2. How is the declaration ClearQueue(); CopyAndAddToQueue(Text); GetTextFromQueue();?Thank You very much.

void TMyThread::Send(TStrings *Text){ // make a copy of the strings and add the copy to the main Queue ... std::unique_ptr<TStringList> Copy(new TStringList); Copy->Assign(Text); Send(std::move(Copy));}

void TMyThread::Send(std::unique_ptr<TStringList> &&Text){ // take ownership of the strings and add them to the main Queue ... std::unique_lock<std::mutex> lk(QueueLock); Queue.push_back(Text); QueueEvent.notify_one();}

void __fastcall TMyThread::TerminatedSet(){ // signal the conditional variable in case the thread is still waiting on it ... QueueEvent.notify_one();}