Delphi XE - SendText через ServerSocket возвращает китайские или вьетнамские символы на другом конце

Я написал простую программу для передачи файлов, которая работает в Windows 7. Я запускаю эту программу как сервер на одном компьютере и как клиент на другом. Клиент отправляет запрос на передачу файла, а затем сервер сначала отправляет имя файла. Затем клиент подтверждает, что он получил имя файла и отправляет содержимое файла.

Эта программа безупречно работала на XP. Теперь мы пытаемся запустить его на компьютерах с Windows 7, и у него есть проблема. Проблема заключается в том, что всякий раз, когда сервер отвечает клиенту с именем файла.

Сервер отправляет текст, вызывая ServerSocket1.SendText('File1.dat').

То, что получает клиент, выглядит как китайские или вьетнамские иероглифы. Итак, моя программа не работает. Моя клиентская программа должна знать имя файла. Таким образом, он знает, где сохранить его в определенном месте на жестком диске.

Я думаю, что функция SendText принимает AnsiString, а я отправляю строковые данные. Как вы думаете, это причина?

ОБНОВЛЕНИЕ

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
begin
   Socket.SendText(AnsiString('calibrate.log'));
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
   Buffer:array[0..999] of char;
begin
   Socket.ReceiveBuf(Buffer,Socket.ReceiveLength);
end;

person ThN    schedule 28.09.2011    source источник
comment
Покажите нам код. Вы используете один и тот же exe на XP и Win7? И да, отправка текста в кодировке ANSI в канал, ожидающего текста в кодировке UTF-16, приводит к получению текста на китайском языке!   -  person David Heffernan    schedule 28.09.2011
comment
@ Дэвид, да, я запускаю один и тот же exe-файл только в системах Windows 7.   -  person ThN    schedule 28.09.2011
comment
@ Дэвид Хеффернан, понятно. При компиляции он выдает мне предупреждения для метода sendtext, что для него требуется AnsiString и что из-за неявного преобразования я могу потерять данные. Итак, я явно привожу его к AnsiString, как показано выше.   -  person ThN    schedule 28.09.2011
comment
Вы отправляете текст в кодировке ANSI, но ваш получатель интерпретирует его как UTF-16. Что делает ваш ресивер?   -  person David Heffernan    schedule 28.09.2011
comment
Он получает что-то из сокета и отображает китайские иероглифы.   -  person ThN    schedule 28.09.2011
comment
ясно, что он интерпретирует поток как UTF16   -  person David Heffernan    schedule 28.09.2011
comment
@digitalanalog: покажите код клиента, который получает имя файла. Обратите внимание, что TClientSocket и TServerSocket НЕ реализуют поддержку UnicodeString правильно, поэтому вам лучше кодировать строковые данные, скажем, в UTF-8, а затем вместо этого использовать SendBuf() и ReceiveBuf().   -  person Remy Lebeau    schedule 28.09.2011
comment
@RemyLebeau-Team, просто я использовал SendText и ReceiveBuf, которые, вероятно, запутались. Итак, я отправляю текст и получаю текст. Это прекрасно работает.   -  person ThN    schedule 28.09.2011
comment
@digitalanalog: SendText() и ReceiveText() работают с AnsiString, а не с UnicodeString или даже с RawByteString. AnsiString поддерживает кодовую страницу в D2009+, что означает, что при вызове SendText() произойдет неявное преобразование данных, а ReceiveText() может вернуть неверный AnsiString, чьи данные не соответствуют его кодовой странице правильно.   -  person Remy Lebeau    schedule 29.09.2011


Ответы (3)


Ну, ваши проблемы связаны с тем, что вы отправляете свои данные как AnsiString и читаете их с помощью WideChars (Char - это псевдоним WideChar в Delphi XE).

Изменение вашего кода для этого, скорее всего, решит вашу проблему.

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var    
  Buffer:array[0..999] of Ansichar; 
begin    
  Socket.ReceiveBuf(Buffer,Socket.ReceiveLength); 
end; 
person Ken Bourassa    schedule 29.09.2011
comment
@ Кен, это была моя ошибка. - person ThN; 29.09.2011

TClientSocket устарел, начиная с Delphi 6 (см. Является ли Delphi TClientSocket (все еще) устаревшим?), поэтому Я бы ожидал проблем с данными Unicode и в других областях. Как написано в одном из ответов, TClientSocket и TServerSocket также используют неэффективный дизайн, основанный на сообщениях Windows. Так что я бы попробовал вместо этого использовать Indy или Synapse. Это также сделало бы его готовым к кросс-платформенному использованию (очевидно, что сообщения Windows недоступны в OSX).

person mjn    schedule 29.09.2011
comment
@mjn Интересно. Мне придется реализовать ваше предложение в моем следующем пересмотре. Спасибо. - person ThN; 29.09.2011

Я решил свой вопрос. Я не уверен, почему это работает безупречно на Windows XP.

В любом случае, я отправляю и получаю тексты следующим образом. Первоначально я читал текст в массив символов с помощью метода ReceiveBuf.

Socket.SendText('File.log');

theStr:String;
theStr := Socket.ReceiveText;

Спасибо, что помогли мне понять мою собственную проблему программирования.

person ThN    schedule 28.09.2011