Lena wrote:- Code: Select all
void __fastcall TUpdateRichEdit::DoNotify()
{
if (sText.IsEmpty()) return;
FormPrint->Memo1->Lines->Clear();
FormPrint->Memo1->Text = sText;
}
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.
- Code: Select all
void __fastcall TUpdateRichEdit::DoNotify()
{
FormPrint->Memo1->Text = sText;
}
Lena wrote:- Code: Select all
String Sdata = AContext->Connection->IOHandler->AllData(IndyTextEncoding_UTF8());
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:
- IOHandler->Write(TStrings) and IOHandler->ReadStrings():
- Code: Select all
IdTCPClient1->IOHandler->Write(Memo1->Lines, true);
- Code: Select all
TStringList *Sdata = new TStringList;
AContext->Connection->IOHandler->ReadStrings(strs);
...
delete Sdata;
- IOHandler->Write() and IOHandler->ReadString(), preceding the string with its byte length:
- Code: Select all
TIdBytes bytes = IndyTextEncoding_UTF8()->GetBytes(Memo1->Lines->Text);
IdTCPClient1->IOHandler->Write(Int32(bytes.Length));
IdTCPClient1->IOHandler->Write(bytes);
- Code: Select all
int len = AContext->Connection->IOHandler->ReadInt32();
String Sdata = AContext->Connection->IOHandler->ReadString(len);
Lena wrote:- Code: Select all
catch (const Exception &E)
{
String mis = L"Error class: " + E.ClassName() + L" Error message: " + E.Message;
ZapisVRichEditWindow(mis);
}
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:
- Code: Select all
catch (const Exception &E)
{
...
if (dynamic_cast<const EIdException*>(&E) != NULL)
throw;
}
Otherwise, get rid of your try/catch in OnExecute and use the OnException event instead:
- Code: Select all
void __fastcall TFormPrint::IdTCPServer1Connect(TIdContext *AContext)
{
AContext->Connection->IOHandler->DefStringEncoding = IndyTextEncoding_UTF8();
}
void __fastcall TFormPrint::IdTCPServer1Execute(TIdContext *AContext)
{
String Sdata = AContext->Connection->IOHandler->AllData();
if (!Sdata.IsEmpty()) ZapisVRichEditWindow(Sdata);
}
void __fastcall TFormPrint::IdTCPServer1Exception(TIdContext *AContext, Exception *AException)
{
if (!dynamic_cast<EIdConnClosedGracefully*>(AException))
{
String mis = _D("Error class: ") + AException->ClassName() + _D(" Error message: ") + AException->Message;
ZapisVRichEditWindow(mis);
}
}
Lena wrote:- Code: Select all
IdTCPClient1->IOHandler->WriteLn(Memo1->Lines->Text);
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:
- passing IndyTextEncoding_UTF8 directly to WriteLn() (or Write(TStrings)):
- Code: Select all
IdTCPClient1->IOHandler->WriteLn(Memo1->Lines->Text, IndyTextEncoding_UTF8());
- Code: Select all
IdTCPClient1->IOHandler->Write(Memo1->Lines, true, IndyTextEncoding_UTF8());
- setting IdTCPClient1->IOHandler->DefStringEncoding to IndyTextEncoding_UTF8 after calling Connect() and before calling WriteLn() (or Write(TStrings)):
- Code: Select all
IdTCPClient1->Connect();
IdTCPClient1->IOHandler->DefStringEncoding = IndyTextEncoding_UTF8();
IdTCPClient1->IOHandler->WriteLn(Memo1->Lines->Text);
//IdTCPClient1->IOHandler->Write(Memo1->Lines, true);
- setting GIdDefaultTextEncoding to encUTF8, such as at program startup:
- Code: Select all
GIdDefaultTextEncoding = encUTF8;
...
IdTCPClient1->IOHandler->WriteLn(Memo1->Lines->Text);
//IdTCPClient1->IOHandler->Write(Memo1->Lines, true);