Модераторы: Snowy, Poseidon, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TSocketServer\TSocketClient и интернет, не коннектится 
:(
    Опции темы
OXOTHUK
Дата 7.6.2007, 20:29 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 21.9.2005

Репутация: нет
Всего: 6



Как подсоединить сервера и клиента через интернет(У сервера фиксированный IP). У мня чтобы я ни писал в поле Adress, какой бы IP не вводил, всё равно не хочет коннектится.

ЗЫ если есть более удобные/легко осваиваемые способы прередачи record'а через интернет, то скажите, желательно с примером.
PM MAIL   Вверх
Snowy
Дата 7.6.2007, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Отладь сначала на одной машине.
Если там будет работать, значит проблемы на другом уровне.
PM MAIL   Вверх
OXOTHUK
Дата 7.6.2007, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 21.9.2005

Репутация: нет
Всего: 6



на одной машине работает, даже если вводить бурду в адрес.

А какие могут быть проблемы?
PM MAIL   Вверх
Snowy
Дата 7.6.2007, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Цитата(OXOTHUK @  7.6.2007,  20:58 Найти цитируемый пост)
на одной машине работает, даже если вводить бурду в адрес.
Значит ты что-то напутал с адресом.
Не может запрос пойти на "бурду".

Добавлено через 24 секунды
Цитата(OXOTHUK @  7.6.2007,  20:58 Найти цитируемый пост)
А какие могут быть проблемы?
Обычные. Файрволы, закрытые порты...
PM MAIL   Вверх
OXOTHUK
Дата 7.6.2007, 21:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 21.9.2005

Репутация: нет
Всего: 6



Цитата(Snowy @  7.6.2007,  21:20 Найти цитируемый пост)
Значит ты что-то напутал с адресом.Не может запрос пойти на "бурду".

Но работает. Запускаю сервер, клиенту пишу адрес "asdfga", нажимаю актив и сенд, и у сервера появляется. (на одной машине, подозреваю, что если он не может найти адрес, то ищет на 127.0.0.1).
А вот через интернет не работает, файрволы пускают прогу. А может это быть если порт занят другой прогой?

ЗЫ а как надо называть Host-свойство у клиента? а то у мня не всегда подключается, иногда говорит, что еррор сокет 10060.(хотя я не этим сокетом пользуюсь) Но если изменить имя хоста, то всё нормально.
PM MAIL   Вверх
Snowy
Дата 7.6.2007, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Цитата(OXOTHUK @  7.6.2007,  21:28 Найти цитируемый пост)
подозреваю, что если он не может найти адрес, то ищет на 127.0.0.1
Неправильно подозреваешь.
Если ты прописал asdfga, а законнетилось на локальный, значит нифига ты не прописал.
Значит где-то ошибка, и твоё asdfga не играет никакой роли.

Цитата(OXOTHUK @  7.6.2007,  21:28 Найти цитируемый пост)
хотя я не этим сокетом пользуюсь
Это не сокет, а код ошибки.
Вбей его в гугль - сразу найдёшь, что она значит.
PM MAIL   Вверх
OXOTHUK
Дата 7.6.2007, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 21.9.2005

Репутация: нет
Всего: 6



Цитата(Snowy @  7.6.2007,  22:58 Найти цитируемый пост)
Если ты прописал asdfga, а законнетилось на локальный, значит нифига ты не прописал.Значит где-то ошибка, и твоё asdfga не играет никакой роли.

Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ScktComp, ExtCtrls;

type
  ITCMessage=record
    str: string[50];
    t: integer;
  end;

  TForm1 = class(TForm)
    cs1: TClientSocket;
    BitBtn1: TBitBtn;
    Button1: TButton;
    le1: TLabeledEdit;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
cs1.Active:=false;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
cs1.Active:=false;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
cs1.Address:=le1.Text;
cs1.Active:=true;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  msg: ITCMessage;
  ms: TMemoryStream;
begin
  msg.str:='string';
  msg.t:=0;
  cs1.Socket.SendBuf(msg, sizeof(msg));
end;

end.

Ну что тут может быть не так?
PM MAIL   Вверх
misha_mike
Дата 8.6.2007, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 1.6.2007

Репутация: 1
Всего: 1



Во-первых я что-то не вижу чтобы ты порт указал. А во-вторых используй свойство Host.

А вот это излишество:
Код

procedure TForm1.FormClose(Sender: TObject);
begin
cs1.Active:=false;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
cs1.Active:=false;
end;

Достаточно только FormDestroy.

И тут поосторожней:
Код

var
  msg: ITCMessage;
  ms: TMemoryStream;
begin
  msg.str:='string';
  msg.t:=0;
  cs1.Socket.SendBuf(msg, sizeof(msg));
end

Никто не гарантирует что на приемной стороне твоя структура прийдет целиком а не парой-тройкой кусочков последовательно (и чем больше твоя структура и чем медленнее канал тем больше вероятность ее разрыва, а начиная с нескольких килобайт размера разрываться она будет гарантированно). Также никто не гарантирует что два (или больше) последовательных SendBuf(...) небольшого размера приведут к генерации соответствующего количества событий OnRead на приемной стороне, а не слипнуться в один кусок.

Это сообщение отредактировал(а) misha_mike - 8.6.2007, 16:15
PM MAIL   Вверх
OXOTHUK
Дата 8.6.2007, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 21.9.2005

Репутация: нет
Всего: 6



misha_mike, 
порт указан в изначальных настройках, которые на обжект инспекторе.

АПД:
Сам допёр, спосебо всем.

Это сообщение отредактировал(а) OXOTHUK - 8.6.2007, 16:14
PM MAIL   Вверх
OXOTHUK
Дата 10.6.2007, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 21.9.2005

Репутация: нет
Всего: 6



Нозникла новая проблема: как передать такую струкруру:
Код

TEMessage = record
  names: array [1..30] of string[15];
  health: array [1..30] of integer;
  stats: array [1..30] of string[20];
  atack: array [1..30] of array [1..10] of string [15];
  namer: array [1..30] of integer;
  count: integer;
end;

Через SendBuf естесна не передаётся, но я попробывал сохранить в файл, а потом SendStream. Но получать приходится через RecieveBuf. И опять не доходит или что ещё. Есть какие-нибудь способы?

ЗЫ на одной машине всё нормально передаётся
PM MAIL   Вверх
misha_mike
Дата 10.6.2007, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 1.6.2007

Репутация: 1
Всего: 1



Как не передается? Какую ошибку возвращает? Вообще для передачи больших блоков (более 2 килобайт) надо их нарезать на кусочки по одному-два килобайта, и передвать по кусочку пока не возникнет ошибка WSAEWOULDBLOCK. Потом ждать события OnWrite и повторять с места остановки до следующей ошибки. И так далее до конца буфера. Приходить она тоже будет кусками, причем совсем не обязательно такими, которыми ты ее нарезал при передаче, поэтому о сборе в единое целое тоже нужно позаботиться на приемной стороне.

P.S. А связь с localhost всегда более дубовая чем с удаленной машиной, много подобных ньюансов не вылазят потому что при связи с самим собой стек TCP/IP может работать далеко не на всю свою глубину....

P.P.S. А вообще такие вещи по сети лучше не гонять, и вместо крайне избыточной структуры с COUNT-ом перегони сначала COUNT, а потом соотвествующее количество неизбыточных структур такого вида (и обрати внимание на слово packed):
Код

TSMessage = packed record
  names: string[15];
  health: integer;
  stats: string[20];
  atack: array [1..10] of string [15];
  namer: integer;
end;

А не то тебя юзера проклянут.

Это сообщение отредактировал(а) misha_mike - 10.6.2007, 16:34
PM MAIL   Вверх
OXOTHUK
Дата 10.6.2007, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 21.9.2005

Репутация: нет
Всего: 6



Цитата(misha_mike @  10.6.2007,  16:21 Найти цитируемый пост)
Как не передается? Какую ошибку возвращает?

никакую, там просто не возникает события OnRead.
Цитата(misha_mike @  10.6.2007,  16:21 Найти цитируемый пост)
и обрати внимание на слово packed

а чем отличается packed record от record?  :lamo:

Но вроде работает.

АПД только не всегда доходит.
вот серверная:
Код

...
Socket.SendText(inttostr(count_msg));
for i:=1 to count_msg do
  Socket.SendBuf(msg[i], sizeof(TSMessage));
...

вот клиентская:
Код

procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  i, count: integer;
  msg: array [1..30] of TSMessage;
begin
  count:=strtoint(Socket.ReceiveText);
  for i:=1 to count do
    begin
      Socket.ReceiveBuf(msg[i], sizeof(TSMessage));
    end;
...
end;

или можно как-то лучше реализовать? :lamo: я с сетями никогда не работал

Это сообщение отредактировал(а) OXOTHUK - 10.6.2007, 18:47
PM MAIL   Вверх
misha_mike
Дата 10.6.2007, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 1.6.2007

Репутация: 1
Всего: 1



Цитата
Цитата(misha_mike @  10.6.2007,  16:21 Найти цитируемый пост)
Как не передается? Какую ошибку возвращает?

никакую, там просто не возникает события OnRead.

И OnError не возникает? Не может этого быть...

Цитата
Цитата(misha_mike @  10.6.2007,  16:21 Найти цитируемый пост)
и обрати внимание на слово packed

а чем отличается packed record от record?  :lamo:

Тем что выравнивания нет и структура имеет именно такой размер, который имеют в сумме ее члены. В прочем об этом написано в любом учебнике и к сетям отношения не имеет.

Цитата
АПД только не всегда доходит.

Что такое АПД?

Цитата
вот серверная:
Код

...
Socket.SendText(inttostr(count_msg));
for i:=1 to count_msg do
  Socket.SendBuf(msg[i], sizeof(TSMessage));
...

Не передавай без крайней необходимости числа в виде текста, это кроме того что избыточно, в случае вещественных чисел обязательно приведет к проблемам. Пиши Socket.Send(count_msg, SizeOf(count_msg)), а на приемной стороне соответственно Socket.ReceiveBuf(count_msg, SizeOf(count_msg)), но ты про это пока забудь и читай дальше.

Цитата
вот клиентская:
Код

procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  i, count: integer;
  msg: array [1..30] of TSMessage;
begin
  count:=strtoint(Socket.ReceiveText);
  for i:=1 to count do
    begin
      Socket.ReceiveBuf(msg[i], sizeof(TSMessage));
    end;
...
end;


Я же предупреждал, что так делать нельзя никогда. Никто не гарантирует что все что ты передал с одной стороны прийдет на другую именно так как ты ожидаешь. Во-первых рано или поздно случится так что в твой ClientRead прийдет count и три с половиной msg, а оставшиеся пять с половиной -- в следующем ClientRead, который совершенно не готов к такому повороту (не разобравшись в том что пришло, сразу читает Count и что-то там принимает). Во вторых очень бысто случится так, что в одном ClientRead прийдет то что ты передал в два или три захода! В первом случае ты получишь ошибку, а во втором просто проворонишь один или несколько пакетов.

Еще раз поясняю, прочитай очень внимательно. Со стопроцентной вероятностью ты столкнешся с такими ситуациями:

1. Разрезание.
ПЕРЕДАТЧИК: 
Вызываешь Socket.SendBuf(Data, 6000);
ПРИЕМНИК: 
Возникает событие ClientRead, в котором Socket.ReceiveLength = 4096, и через некоторое время опять возникает событие ClientRead, в котором Socket.ReceiveLength = 1904.
РЕЗЮМЕ:
То что ты передал одним куском, пришло несколькими.

2. Склеивание.
ПЕРЕДАТЧИК:
Вызываешь Socket.SendText('текст'), и через некоторое время Socket.SendBuf(Data, 8).
ПРИЕМНИК:
Возникает одно единственное событие ClientRead, в котором Socket.ReceiveLength = 13 (сумма длин текста и данных).
РЕЗЮМЕ:
То что ты передал несколькими Send-ами пришло одним куском.

3. Смешивание.
ПЕРЕДАТЧИК:
Вызываешь Socket.SendText('текст'), и через некоторое время Socket.SendBuf(Data, 6000).
ПРИЕМНИК:
Возникает событие ClientRead, в котором Socket.ReceiveLength = 4096 и в этот размер входит переданный первым Send-ом 'текст' и первые 4091 байт из буфера Data, переданного вторым Send-ом, и через некоторое время опять возникает событие ClientRead с оставшимися 1909 байтами из буфера Data, переданного вторым Send-ом.
РЕЗЮМЕ:
То, как ты передаешь данные никак не связанно с тем, как они прийдут. Сохраняется только последовательность, но никак не блочность.

4. Переполнение буфера передачи WinSock.
ПЕРЕДАТЧИК:
Вызываешь Socket.SendBuf(Data, 100000), тут же возникает OnError, в котором ErrorEvent = eeSend.
ПРИЕМНИК:
Ничего не приходит.
РЕЗЮМЕ:
Передавать в один присет более нескольких килобайт нельзя, нужно разрезать большой пакет на тесколько маленьких (не более пары килобайт) и передвать их до тех пор пока не возникнет OnError (при этом ErrorEvent должен быть равен eeSend, иначе прерываем передачу и генерируем ошибку разрыва канала связи). После этого нужно остановиться, дождаться события OnWrite и только тогда продолжить до следующего OnError. И так пока не закончатся данные для передачи.

Цитата
или можно как-то лучше реализовать? :lamo: я с сетями никогда не работал

Первый вариант -- реализовываешь свой протокол верхнего уровня, в котором на предающей стороне перед полезными данными помещается некоторая структура-заголовок, включающая размер передаваемого блока, а потом все это будет передаваться по кускам согласно п. 4. На приемной стороне эта структура анализируется и производится накопление пришедших данных до тех пор пока их объем не достигнет указанной в заголовке длины. Также если объем принятых данных превышает размер остатка текущего блока, нужно инициализировать начало приема следующего блока.

Второй вариант -- воспользоваться оним из существующих протоколов верхнего уровня, например IRC. Благо соответствующих компонент достаточно.

Это сообщение отредактировал(а) misha_mike - 10.6.2007, 20:15
PM MAIL   Вверх
OXOTHUK
Дата 11.6.2007, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 21.9.2005

Репутация: нет
Всего: 6



Цитата(misha_mike @  10.6.2007,  20:14 Найти цитируемый пост)
И OnError не возникает? Не может этого быть...

сам вызов функции не проверял, но видимых ошибок нет никаких.

Цитата(misha_mike @  10.6.2007,  20:14 Найти цитируемый пост)
Что такое АПД?

UPD - updated, т.е. исправил пост и дописал.

Цитата(misha_mike @  10.6.2007,  20:14 Найти цитируемый пост)
Первый вариант -- реализовываешь свой протокол верхнего уровня...

тут мня возникает несколько вопросов: 1) чем принимать, т.е. каким типом? array of byte? 2) как склеивать\разрезать получившиеся части?

Цитата(misha_mike @  10.6.2007,  20:14 Найти цитируемый пост)
Второй вариант -- воспользоваться оним из существующих протоколов верхнего уровня, например IRC. Благо соответствующих компонент достаточно.

TInIRCServer/TInIRC подойдёт с вкладки Indy? Или есть что-то лучше? А есть какой-нибудь мануал как или пользоваться, а то они не похожи на сокеты. Желательно с примерами.
ЗЫ. Дельфийская справка у меня не работает.
PM MAIL   Вверх
misha_mike
Дата 11.6.2007, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 1.6.2007

Репутация: 1
Всего: 1



Цитата
Цитата(misha_mike @  10.6.2007,  20:14 Найти цитируемый пост)
Первый вариант -- реализовываешь свой протокол верхнего уровня...

тут мня возникает несколько вопросов: 1) чем принимать, т.е. каким типом? array of byte? 2) как склеивать\разрезать получившиеся части?

Блин, это же основы работы с "сырыми" данными. Без этого ничего сложнее калькулятора не написать, а ты сразу игрушки с мультиплеером ваять собрался... Принимать надо указателем на динамический блок, передавать им же. Динамические массивы конечно тоже сгодятся, но ты не на джаве и не в дотнете пишешь чтобы на них выезжать в любой ситуации. Как производится работа с динамической памятью написано в ЛЮБОМ учебнике по Паскалю. Указательную арифметику для нарезки/склейки пакетов имеет смысл показывать только поле того как подобные отквоченному вопросы возникать перестанут в принципе. А спрашивать об тривиальных операциях по извлечению подмассива и склеиванию нескольких динамических массивов вовсе должно быть стыдно!

Цитата
Цитата(misha_mike @  10.6.2007,  20:14 Найти цитируемый пост)
Второй вариант -- воспользоваться оним из существующих протоколов верхнего уровня, например IRC. Благо соответствующих компонент достаточно.

TInIRCServer/TInIRC подойдёт с вкладки Indy? Или есть что-то лучше? А есть какой-нибудь мануал как или пользоваться, а то они не похожи на сокеты. Желательно с примерами.

Там примитив полнейший, да и не единственные это компоненты (и не единственный подходящий протокол).

Цитата
ЗЫ. Дельфийская справка у меня не работает.

Это не оправдание, либо чини либо вызывай ее руками. А основы языка (изложенные в любой книжке) рассказывать думаю тут желающих не много наберется.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0729 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.