Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.10.23;
Скачать: CL | DM;

Вниз

Помогите найти компоненты для TCP... :)   Найти похожие ветки 

 
Terminus ©   (2003-08-25 16:39) [0]

Господа! Сможет ли кто-нибудь посоветовать хорошие компоненты/модули для реализации TCP клиента/сервера? Сие необходимо для создания мультиплеера в игрухе... :)
Только, плз, не предлагать 2 варианта:
1. Писать самому.
2. THxTcpIpcUdp. Хороший модуль, но то, что код, перенесенный из стандартного примера в игру, перестал работать (невозможно добиться пересылки record) окончательно вывело меня из себя. :) Жаль...

Еще буду благодарен, если кто объяснит принципиальное отличие сервера синхронного и асинхронного. Литературу в INet"е почитал, но практической разницы так и не понял. :)

Заранее благодарен.


 
Reindeer Moss Eater ©   (2003-08-25 16:46) [1]

Хороший модуль, но то, что код, перенесенный из стандартного примера в игру, перестал работать

А если перенести не в игру?


 
Dimka Maslov ©   (2003-08-25 16:47) [2]

Лучше писать самому при помощи WinSock. Особых сложностей нет.

Синхронный сервер обрабатывает запросы клиентов последовательно в одном потоке, что уменьшает скорость и увеличивает надёжность, поскольку нет проблем с доступом к ресурсам, разделяемым между потоками. Асинхронный сервер при получении запроса клиента создаёт новый поток, который этот запрос и обрабатывает при увеличении скорости работы (клиент не ждёт завершения обработки других запросов) возникает серьёзная проблема доступа к разделяемым ресурсам при плохом решении которой программа часто получает конфликты доступа, которые не могут отловлены.


 
Terminus ©   (2003-08-25 16:49) [3]

Попробую, но ... смешно. Код простой, инициализация и можно отправлять... Самое смешное, что отдельные переменные перекидываются (хотя бы та же SendString), а вот с record... В общем, вопрос остается в силе. :)


 
Polevi ©   (2003-08-25 16:49) [4]

>что уменьшает скорость
это кто тебе такое сказал


 
Reindeer Moss Eater ©   (2003-08-25 16:51) [5]

Самое смешное, что отдельные переменные перекидываются (хотя бы та же SendString), а вот с record... В общем, вопрос остается в силе. :)

Тебе наверное попалась какая-то особо интеллектуальная библиотека, которая распознает что с помощью ее пытаются передать. Строки или записи. Она видимо байты внимательно разглядывает и находит 10 отличий.


 
Terminus ©   (2003-08-25 17:09) [6]

Тем, кто юзает HxTcpIpcUdp (поскольку альтернатив пока никто не предложил :)

Мда... Короче, видоизменил стандартный пример для отправки record, в составе которого есть PChar. Клиент запись отправляет, сервер принимает и отображает строку. Все нормально.

Переношу код, разделяя клиента и сервера в отдельные программы. Переменные svrTCP и clntTCP объявляю как отдельные переменные, вне TForm1. Сообщение отсылает теперь сервер клиенту. В результате, после получение записи клиентом вместо строки бред. Т.е. не бред, конечно, не явно содержимое некой другой области памяти, в которой моей строки нет. :) Вот такие пироги... :[


 
Terminus ©   (2003-08-25 17:11) [7]

To Dimka Maslov

Я так понимаю, синхронный сервер нужен тогда, когда мне важно, чтобы запросы обрабатывались в той последовательности, в какой были отправлены?


 
Reindeer Moss Eater ©   (2003-08-25 17:22) [8]

Переношу код, ....
....
Вот такие пироги... :[


Ты не объясняй, что ты делаешь, ты код покажи.


 
Terminus ©   (2003-08-25 17:48) [9]

unit Common;
{$DEFINE CLIENT}
{DEFINE SERVER}

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
HxTcpIpcUdp;

type
TForm1 = class(TForm)
procedure FormShow(Sender: TObject);
{$IFDEF SERVER}
procedure OnNewClient(iDescr: Integer);
{$ENDIF}
private
{ Private declarations }
public
{ Public declarations }
{$IFDEF CLIENT}
procedure HandleClientDataAvailable(ptr: pointer; iSize: integer);
{$ENDIF}
end;

THeroInfo = record
RecordType: Byte;
Name: PChar;
end;
TDecorateInfo = record
RecordType: Byte;
Empty: Integer;
Name: PChar;
end;

var
Form1: TForm1;
svrTCP: THxTcpServer;
clntTCP: THxTcpClient;
Hero: THeroInfo;
Decorate: TDecorateInfo;
PHero: ^THeroInfo;
PDecorate: ^TDecorateInfo;

implementation

{$R *.DFM}
{$IFDEF CLIENT}
procedure TForm1.HandleClientDataAvailable(ptr: pointer; iSize: integer);
var
s: string;
z,i,j: Integer;
oRecordType: Byte;
begin
Move(ptr^,oRecordType,1);
case oRecordType of
1: begin
Move(ptr^,Hero,isize);
ShowMessage(StrPas(Hero.Name));
end;
2: begin
Move(ptr^,Decorate,isize);
ShowMessage(StrPas(Decorate.Name));
end;
end;
end;
{$ENDIF}
procedure TForm1.FormShow(Sender: TObject);
begin
{$IFDEF SERVER}
svrTCP := THxTcpServer.Create;
svrTCP.Port := "2003";
svrTCP.OnNewClient := OnNewClient;
svrTCP.Listen;
{$ENDIF}
{$IFDEF CLIENT}
clntTcp := THxTcpClient.Create;
clntTcp.ServerAddress := "localhost";
clntTcp.Port := "2003";
clntTcp.OnDataAvailable := HandleClientDataAvailable;
clntTcp.Connect;
{$ENDIF}
end;

{$IFDEF SERVER}
procedure TForm1.OnNewClient(iDescr: Integer);
begin
PHero:=@Hero;
PDecorate:=@Decorate;
PHero.RecordType:=1;
PDecorate.RecordType:=2;
PHero.Name:=PChar("Герой");
PDecorate.Name:=PChar("Декоративный объект");
SvrTcp.SendData(PDecorate,SizeOf(Decorate),0);
end;
{$ENDIF}
end.


Вот полный код неработующего модуля. Соответственно, для клиента компилируется один код, для сервера другой, но это неважно...

Суть в том, чт клиент по певому байту должен определить тип записи (и в видоизмененном стандартном примере исправно это делает) и вывести имя объекта. Разумеется, код тестовый, так что обращать внимание только на суть проблемы. :)


 
Reindeer Moss Eater ©   (2003-08-25 18:26) [10]

TDecorateInfo = record
RecordType: Byte;
Empty: Integer;
Name: PChar;
end;

SvrTcp.SendData(PDecorate,SizeOf(Decorate),0);

При выполнении этого кода, поле Name из TDecorateInfo никуда не посылается. Вместо этого посылается значение указателя, который на приемном конце лишен всяческого смысла ибо указывает в космос.


 
Terminus ©   (2003-08-25 18:37) [11]

И? Выход то где в этом случае? :)

Характерно, что если и сервер и клиент размещаются в одном модуле (в пресловутом стандартном примере), этот же код работает. Я вижу две причины, обе из которых мне не нравятся. :)
1. Две копии программы, запущенные паралельно, используют одну и ту же область памяти (что невозможно)
2. Причина бага в другом.

Так все таки, как организовать пересылку record структур? Можно, конечно, перед пересылкой запихивать содержимое record в текий буфер, и кидать уже его, а на другом конце опять заносить в record, но это уже извращение... :(


 
Dimka Maslov ©   (2003-08-25 18:39) [12]

>Polevi
Скорость работы клиента при множественном подключении клиентов к серверу меньше если сервер работает в синхронном режиме именно за счёт ожидания, особенно если запрос приводит к передаче больших массивов данных. При небольшом объёме отправляемых пакетов замедление работы клиента не столь существенно.

>Terminus
TDecoreateInfo = record
RecordType: Byte;
RecordSize: LongInt;
Empty: LongInt;
NameLen: LongInt;
Name: array[0..0] of Char;
end;


 
Reindeer Moss Eater ©   (2003-08-25 18:41) [13]

Характерно, что если и сервер и клиент размещаются в одном модуле (в пресловутом стандартном примере), этот же код работает. Я вижу две причины, обе из которых мне не нравятся. :)

Указатель переданный клиенту, продолжает указывать на то место в памяти, куда он указывал до своего путешествия к клиенту.
Вот и все "характерно"


 
Reindeer Moss Eater ©   (2003-08-25 18:42) [14]

Так все таки, как организовать пересылку record структур? Можно, конечно, перед пересылкой запихивать содержимое record в текий буфер, и кидать уже его, а на другом конце опять заносить в record, но это уже извращение... :(

Почему извращение? Потому что требует дополнительного программирования нескольких строк?


 
Dimka Maslov ©   (2003-08-25 18:45) [15]

>Terminus
Зайди на http://icq2000cc.hobi.ru/ там подробно описано как организовать пересылку записей со строками переменной длины.


 
Reindeer Moss Eater ©   (2003-08-25 18:47) [16]

Так все таки, как организовать пересылку record структур?

Не в самих Record"ах проблема, а в Record"ах, имеющих указатели.


 
Terminus ©   (2003-08-25 18:59) [17]

[i]To Dimka Maslov[/i]
Спасибо, посмотрю, буду пробовать...

[i]To Reindeer Moss Eater
Почему извращение? Потому что требует дополнительного программирования нескольких строк?[/i]
В общем, хотелось бы не утяжелять прогу всем этим, но, похоже, иного выхода нет. :) Ладно, спасибо всем за помощь, пойду эксперементировать...


 
Reindeer Moss Eater ©   (2003-08-25 19:36) [18]

В общем, хотелось бы не утяжелять прогу всем этим

Надо очень сильно попотеть, что бы утяжелить свою прогу кодом (именно кодом).


 
Terminus ©   (2003-08-25 20:50) [19]

Еще раз спасибо. :) Помещаю теперь в TByteArray и после доставки собираю обратно в record...

Еще. Предполагается, что пакеты, по большей части, будут небольшими (несколько десятков байт), но серверу прийдется рассылать все это десяткам клиентов (как минимум) и весьма часто... Поэтому и хотелось ускорить процедуры пересылки... Хотя может, зря все это, мелочи...



Страницы: 1 вся ветка

Текущий архив: 2003.10.23;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.024 c
4-74541
Michael Makushev
2003-08-18 13:30
2003.10.23
TThread - и совместное использование данных


1-74235
GreySerg
2003-10-08 20:12
2003.10.23
Как определить процедуру на определённое событие у дина...


3-74028
alex25
2003-10-03 13:18
2003.10.23
множественное like


1-74299
Nucl
2003-10-12 11:10
2003.10.23
Чистилка кода


1-74291
Qwerr
2003-10-08 10:44
2003.10.23
Rave Reports