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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> tcpserver и tcpclient. ЧАТ 
:(
    Опции темы
boobie
Дата 13.6.2013, 08:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Здравствуйте! Экспериментирую с сетью. Написал программу, отдаленно напоминающую чат: 2 поля ввода (memo1 и memo2), 1 кнопка (button1), TcpServer1, Tcpclient1.
TcpServer1.Localport поставил 7000. Такой же порт поставил в TcpClient1.RemotePort. TcpClient1.Remotehost выставил 127.0.0.1
Код программы:
Код

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Web.Win.Sockets, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Memo2: TMemo;
    Button1: TButton;
    TcpServer1: TTcpServer;
    TcpClient1: TTcpClient;
    procedure FormCreate(Sender: TObject);
    procedure TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
  for i:=0 to memo1.Lines.Count-1 do
  begin
    tcpclient1.Sendln(memo1.Lines[i]);
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
tcpserver1.Close;
tcpclient1.Disconnect;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
tcpserver1.BlockMode:=bmthreadblocking;
tcpserver1.Open;
tcpclient1.Open;
end;

procedure TForm1.TcpServer1Accept(Sender: TObject;
  ClientSocket: TCustomIpClient);
var s:string;
begin
  s:=ClientSocket.Receiveln;
  memo2.Lines.Add(s);
end;

end.

При создании формы все открываем, при закрытии - рассоединяем, при нажатии на кнопку - отсылаем все строки из memo1 с помощью цикла и tcpclient1.Sendln(memo1.Lines[i]);. Сервер прослушивает, если что-нибудь придет, то эту строку добавляем в memo2.
И вот вопросы:
1. Не работает! Приходит только одна строка, только один раз. Потом сообщения не приходят. Каким образом запускается событие TcpServer1Accept? Я думал, что для каждой приходящей строки, отосланной с помощью Sendln, оно генерируется заново. 
Почему вот так:
Код

procedure TForm1.TcpServer1Accept(Sender: TObject;
  ClientSocket: TCustomIpClient);
var s:string;
begin
  s:=ClientSocket.Receiveln;
  while s <> '' do
  begin              
    memo2.Lines.Add(s);
    s:=ClientSocket.Receiveln;
  end;
end;

работает как надо?
2. В книжках после каждой отправки сообщения авторы разрывают связь, перед отправкой сообщения устанавливают заново. Стоит ли это делать при создании реальных приложений? Т.е. есть ли смысл перед каждой отправкой сообщений коннектится, а потом разрывать связь?
PM   Вверх
Poseidon
Дата 13.6.2013, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

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



Оно поэтому и Receiveln, что получает только одну строчку (line). Почему-то такие функции как Readln и Writeln подобных вопросов не вызывают...


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Akella
Дата 13.6.2013, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


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

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



Я помню, в примерах с дельфи поставлялся готовый проект чата.
PM MAIL   Вверх
boobie
Дата 13.6.2013, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Akella, да не нужен мне готовый чат, я с сетью разбираюсь  smile 

Poseidon, все равно не пойму - отправляется 3 строки, например, а почему метод TcpServer1Accept вызывается всего 1 раз, принимает одну строку (это логично - ReciveLN)... А при последующих нажатиях - ВООБЩЕ ничего не принимает. Почему так?



Это сообщение отредактировал(а) boobie - 13.6.2013, 13:11
PM   Вверх
Akella
Дата 13.6.2013, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


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

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



Цитата(boobie @  13.6.2013,  13:02 Найти цитируемый пост)
Akella, да не нужен мне готовый чат, я с сетью разбираюсь  smile 

вот и разбирайся на основе готового рабочего примера ;)
PM MAIL   Вверх
boobie
Дата 13.6.2013, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Ну, Akella, твой 18000-ый пост мог быть и лучше!  smile 
Я не случайно привел код, который я взял из работающего примера:
Код

procedure TForm1.TcpServer1Accept(Sender: TObject;
  ClientSocket: TCustomIpClient);
var s:string;
begin
  s:=ClientSocket.Receiveln;
  while s <> '' do
  begin              
    memo2.Lines.Add(s);
    s:=ClientSocket.Receiveln;
  end;
end;

он работает... А я не понимаю почему... Почему так работает, а в "моем" случае - нет. Сам механизм не понятен
PM   Вверх
Poseidon
Дата 13.6.2013, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

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



boobie, ты посылаешь в цикле
Код

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
  for i:=0 to memo1.Lines.Count-1 do
  begin
    tcpclient1.Sendln(memo1.Lines[i]);
  end;
end;

т.е. выполняешь Sendln несколько раз. Почему ты думаешь, что прочитать это нужно за один Receiveln?


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Akella
Дата 13.6.2013, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


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

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



ну так трассируй, посмотри что и как выполняется с циклом и без
PM MAIL   Вверх
boobie
Дата 13.6.2013, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Т.е. процедура TcpServer1Accept запускается один раз и не выходит из процедуры, пока все данные не будут считаны? Так?
PM   Вверх
Akella
Дата 13.6.2013, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


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

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



А что, F1 выламана?
PM MAIL   Вверх
boobie
Дата 13.6.2013, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Эмм... Получается, что данная процедура вызывается сразу после подключения клиента... Создается очередь для хранения клиентских запросов. Эта очередь обслуживается в данной процедуре. Это я понял из справки, бат ай донт спик инглиш. Так? А что происходит с очередью, если ее не обработать в этой процедуре?
PM   Вверх
Akella
Дата 14.6.2013, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


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

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



ничего не происходит, наверное )))
PM MAIL   Вверх
boobie
Дата 14.6.2013, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Дело в том, что если не убрать эту очередь из строк, то в следующий раз захода в процедуру не будет...
PM   Вверх
Akella
Дата 14.6.2013, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


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

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



PM MAIL   Вверх
boobie
Дата 14.6.2013, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Да, там цикл вставлен... Ничего особенного. Пока есть очередь - получай строку и закидывай в мемо. Проблемы начинаются, если очередь большая и с полученными данными надо что-то делать. Без многопотока тогда не обойтись. Да и поведение TcpServer1Accept  неадекватное.
PM   Вверх
Akella
Дата 14.6.2013, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


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

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



тебе нужно много текста передавать?
PM MAIL   Вверх
northener
Дата 14.6.2013, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

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



Цитата(boobie @  13.6.2013,  08:53 Найти цитируемый пост)
Здравствуйте! Экспериментирую с сетью.

Тогда плюнь на эти недоделанные компоненты. 
И экспериментируй с библиотекой ICS
Она была бы в Дельфи основой для работы с сетью, если бы её автор не отказал бы Борланду.
А все примеры для TTCPServer сделаны на основе примера, который поставлялся с ранними версиями Дельфи. И которые только сбивают новичков с толку, заставляя их думать что читать получаемую информацию сервер обязан в событии OnAccept.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
boobie
Дата 14.6.2013, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Akella, ну... По сети не только текст передают... Не текста, но много.

northener, а Indy? С ней что не так? Да и стандартные TTCPServer\Client настолько плохи?

Это сообщение отредактировал(а) boobie - 14.6.2013, 13:40
PM   Вверх
northener
Дата 14.6.2013, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

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



Цитата(boobie @  14.6.2013,  13:39 Найти цитируемый пост)
northener, а Indy? С ней что не так? Да и стандартные TTCPServer\Client настолько плохи?

Разработчики Indy изначально пошли не совсем верным путём. Поэтому они до сих пор делают все новые и новые версии, которые плохо совместимы друг с другом. Да и глюков у них судя по сообщениям на разных форумах многовато.
А стандартные.. Я не говорил что они плохие. Они просто недоделаны. Такое впечатление что их начали делать и бросили почти в самом начале работы. Их базовый класс TBaseSocket выглядит довольно продуманным. А вот его наследники...


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
boobie
Дата 14.6.2013, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



northener, хорошо. Но что делать с событием OnAccept в TCPServer? В каком случае оно возникает и как с ним вообще управляться? Что происходит с очередью, если ее не принять в нем? Вообще, есть ли какие-нибудь хорошие книги по работе с сетями в Delphi? Нашел книгу про Инди, но решил пока разобраться со стандартной вкладкой Internet.
PM   Вверх
northener
Дата 14.6.2013, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

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



Цитата(boobie @  14.6.2013,  14:10 Найти цитируемый пост)
 Но что делать с событием OnAccept в TCPServer? В каком случае оно возникает и как с ним вообще управляться? 

Событие OnAccept, если его правильно воспринимать, возбуждается тогда, когда сервер узнаёт что какой-то новый клиент хочет с ним соединиться. В этом случае сервер должен проверить клиента на его "валидность", оценить свои собственные возможности принять еще одного клиента и с учетом вышесказанного разрешить подключение или отказать в нем. В случае согласия на подключение сервер должен создать новый экземпляр своего "специального клиента", который и будет общаться с вновь подключенным клиентом.
Принимать какую-либо информацию, кроме IP адреса клиента и номера физического порта, по которому с ним будет создано соединение в событии OnAccept не есть правильно.

Это сообщение отредактировал(а) northener - 14.6.2013, 15:09


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
boobie
Дата 14.6.2013, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



А с помощью чего тогда принимать? OnGetThread?
PM   Вверх
northener
Дата 14.6.2013, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

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



Цитата(boobie @  14.6.2013,  14:28 Найти цитируемый пост)
А с помощью чего тогда принимать? 

А вот это (как и многое другое) в классе TTCPServer как раз и не реализовано :(
Если хочешь использовать этот класс доделывай его сам.

Это сообщение отредактировал(а) northener - 14.6.2013, 14:33


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
boobie
Дата 14.6.2013, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Пичалька... 
PM   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

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

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

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

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

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


 




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


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

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