![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
ClientSocket
Profik © (2005-07-22 15:32:00)Нада простенький пример пересылки стринги через сокеты
Alexander Panov (2005-07-23 18:49:00) [1]Atrion © (22.07.05 20:38) [24]
...не далеко мы уходим от кодов Borland...
Эта фраза что означает?
Atrion (2005-07-22 20:38:00) [2]Как мы не стараемся а как у битлз все равно не получается...
...не далеко мы уходим от кодов Borland...
Alexander Panov (2005-07-22 20:09:00) [3]Вот. Написал в качестве разминки. Это наметки для чата точка-точка.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ToolWin, ComCtrls, ScktComp, Buttons;
type
TForm1 = class(TForm)
cs: TClientSocket;
ss: TServerSocket;
ToolBar1: TToolBar;
Panel1: TPanel;
edText: TEdit;
paOK: TPanel;
re: TRichEdit;
sbConnect: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure edTextKeyPress(Sender: TObject; var Key: Char);
procedure csConnect(Sender: TObject; Socket: TCustomWinSocket);
procedure sbConnectClick(Sender: TObject);
procedure csDisconnect(Sender: TObject; Socket: TCustomWinSocket);
procedure csError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure AppException(Sender: TObject; E: Exception);
procedure csRead(Sender: TObject; Socket: TCustomWinSocket);
procedure ssClientConnect(Sender: TObject; Socket: TCustomWinSocket);
procedure ssClientRead(Sender: TObject; Socket: TCustomWinSocket);
procedure paOKMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure paOKMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
FBuf: String;
procedure SetButtonEnabled;
public
procedure Disp(S: String);
end;
const
CRLF=#13#10;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnException := AppException;
edText.Align := alClient;
edText.Text := '';
edText.Color := clBtnFace;
re.Lines.Text := '';
FBuf := '';
ss.Port := 5555;
ss.Open;
end;
procedure TForm1.edTextKeyPress(Sender: TObject; var Key: Char);
begin
if Key=#13 then
begin
if Length(edText.Text)>0 then cs.Socket.SendText(edText.Text+CRLF);
Key := #0;
edText.Text := '';
end;
end;
procedure TForm1.csConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
Disp('Connected to '+Socket.RemoteAddress);
SetButtonEnabled;
end;
procedure TForm1.sbConnectClick(Sender: TObject);
begin
sbConnect.Enabled := False;
cs.Active := not cs.Active;
end;
procedure TForm1.SetButtonEnabled;
begin
case cs.Active of
True:
begin
sbConnect.Caption := 'Disconnect';
edText.Color := clWindow;
end;
False:
begin
sbConnect.Caption := 'Connect';
edText.Color := clBtnFace;
end;
end;
edText.Enabled := cs.Active;
sbConnect.Enabled := True;
end;
procedure TForm1.csDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
SetButtonEnabled;
Disp('Disconnected');
end;
procedure TForm1.csError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
SetButtonEnabled;
end;
procedure TForm1.Disp(S: String);
var
n: Integer;
begin
n := Length(Re.Lines.Text);//-re.Lines.Count*2;
re.Lines.Add(FormatDateTime('hh:nn:ss ',now)+s);
re.SelStart := n;
re.SelLength := 8;
re.SelAttributes.Style := re.SelAttributes.Style+[fsBold];
re.SelLength := 0;
re.SelAttributes.Style := re.SelAttributes.Style-[fsBold];
if re.Lines.Count>500 then re.Lines.Delete(0);
end;
procedure TForm1.AppException(Sender: TObject; E: Exception);
begin
if E is ESocketError then
begin
Disp('Error. '+ E.Message);
Exit;
end;
Application.ShowException(E);
end;
procedure TForm1.csRead(Sender: TObject; Socket: TCustomWinSocket);
var
pz: integer;
Str: String;
begin
repeat
Str := Socket.ReceiveText;
FBuf := FBuf+Str;
until Str='';
FBuf := FBuf;
repeat
pz := Pos(CRLF,FBuf);
if pz>0 then
begin
Disp('Принято:'+Copy(FBuf,1,pz-1));
Delete(FBuf,1,pz+1);
end;
until pz=0;
end;
procedure TForm1.ssClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Socket.SendText('Welcome to server'+CRLF);
end;
procedure TForm1.ssClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
EchoStr: String;
begin
EchoStr := Socket.ReceiveText;
Socket.SendText(EchoStr);
end;
procedure TForm1.paOKMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
paOk.BevelOuter := bvLowered;
end;
procedure TForm1.paOKMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
Key: Char;
begin
Key := #13;
edTextKeyPress(edText,Key);
paOk.BevelOuter := bvRaised;
end;
end.
Проект лежит здесь:
ftp://ftp.almar.net.ru/pub/chat/chat.zip
Wm.DIGGER (2005-07-22 18:54:00) [4]Digitman © (22.07.05 18:42) [20]
procedure TForm1.Button1Click(Sender: TObject);
begin
вообще было бы уместнее здесь ещё, чтобы гарантировать, что
перед соединением сокет свободен ...
Form1.ClientSocket1.Port := 65000;
Form1.ClientSocket1.Host := '127.0.0.1';
Form1.ClientSocket1.Active := true;
//<-здесь
end
Wm.DIGGER (2005-07-22 18:52:00) [5]Digitman © (22.07.05 18:42) [20]
> "империческая область" и есть та самая твоя отсебячина.
Ну, возможно, в этом случае, да. Но это работает! И нормально работает. Поэтому ни чего предосудительного в этом нет.
какого ж тогда лешего ты не делаешь то же самое
ну, да, был бы и там уместен. я же говорю, за 5 мин. писал, человек в чате просил ... пропустил просто.
Почему бы тебе на написать самому, по всем правилам, как это должно выглядеть? Это было бы только хорошо. А чего ругаться-то? Вопрос, чётко сформулирован. Сделай доброе дело, напиши, как нужно.
Digitman (2005-07-22 18:42:00) [6]
> Этот «шедевр» из имперической области
" имп ерическая область" и есть та самая твоя отсебячина.
> "шедевр" позволяет дождаться пока
> не произойдёт disconnect и только после этого продолжать
> выполнение программы
какого ж тогда лешего ты не делаешь то же самое в
procedure TForm1.Button1Click(Sender: TObject);
begin
Form1.ClientSocket1.Port := 65000;
Form1.ClientSocket1.Host := '127.0.0.1';
Form1.ClientSocket1.Active := true;
//<-здесь
end
??
если уж на то пошло, то "шедевр" был бы уместен именно при ожидании коннекта, а не дисконнекта !
Wm.DIGGER (2005-07-22 18:37:00) [7]Digitman © (22.07.05 18:22) [16]
Я вот не понимаю! Любой, кто запустит этот код убедиться, что он рабочий. Почему ты даже не запустив его говоришь о нём всякую хрень. Ну, проверь, ну ведь работает. Неужели так трудно признать свою ошибку.
В общем, не хочу я больше с тобой спорить. Я понял, что ты из тех людей, которые не признают свои ошибки, и будут доказывать свою, пусть и ложную, правоту любой ценой. Я устал от этого, любой, кто воспользуется этим кодом, поймёт кто прав. Всего доброго. Удачи!
Wm.DIGGER (2005-07-22 18:31:00) [8]> Прежде чем постить заведомо дерьмовые примеры ...
ЭТОТ ПРИМЕР РАБОЧИЙ!!!!! И НЕ ОТКУДА НЕ СОДРАН, СКОЛЬКО РАЗ ПОВТОРЯТЬ!!!!!!!!!!!!!!!!!!!!!!!!!!!! ГЛУХОЙ ТЫ, ЧТО ЛИ? (слепой в смысле)
Wm.DIGGER (2005-07-22 18:29:00) [9]Digitman © (22.07.05 18:17) [15]
и ничерта ты там, в этих статьях, не понял, коль в неблокирующем режиме игнорируешь результат вызова send-метода
Ну, сколько же раз объяснять, это ПРОСТЕЙШИЙ ПРИМЕР, а с обработкой, это уже будет НЕ ПРОСТЕЙШИЙ.
while Form1.ClientSocket1.Active do Form1.ClientSocket1.Active := false;
Не нужно ругаться! Да, это выдумка, но этот "шедевр" позволяет дождаться пока не произойдёт disconnect и только после этого продолжать выполнение программы. А без этого если потом (сразу, допустим) опять вызвать соединение (active := true), то прога тут же ошибку выдаст, поскольку сокет ещё занят! Только, там ещё Application.ProcessMessages в цикле нужно, а то повиснет это дело тут же. Этот «шедевр» из имперической области, в теории конечно этого нет.
Digitman (2005-07-22 18:22:00) [10]
> Wm.DIGGER © (22.07.05 18:00) [14]
Прежде чем постить заведомо дерьмовые примеры (тщательно скрывая, что содраны они чуть ли не один к одному из не самых удачных демо-перлов от Борланда), открой scktcomp.pas, Winsock.pas и изучи, олух, от корки до корки ! Сопоставляя штудируемое с теорией/механикой работы гнезд Беркли и stream-oriented транспортного протокола !
Digitman (2005-07-22 18:17:00) [11]
> все эти дурные статьи, которые ты так ценишь, я ещё лет
> 5-7 назад все перечитал
.. и ничерта ты там, в этих статьях, не понял, коль в неблокирующем режиме игнорируешь результат вызова send-метода
а это вот
while Form1.ClientSocket1.Active do Form1.ClientSocket1.Active := false;
просто шедевр.
Wm.DIGGER (2005-07-22 18:00:00) [12]Digitman © (22.07.05 17:30) [12]
P.S. Надеюсь, ты понял, почему ЕГО, а не ЭГО :-))))))))
Wm.DIGGER (2005-07-22 17:58:00) [13]Digitman © (22.07.05 17:30) [12]
Я русский, в отличие от тебя, знаю хорошо.
Просто пишу быстро, вот и опечатки идут.
Ты придираешься к словам, т.к. больше не к чему.
Ты наверняка всё же проверил код и узнал, что ты не прав! И что всё именно так, как я говорю. (А если нет, то ты ещё глупее, чем кажешься! У меня прога, построенная по этому принципу, прекрасно работала и в локалке и в Нете.
А теперь ты пытаешься усмирить свое безразмерное ЕГО, придираясь к мелочам. «Передать string» ему не понравилось! … Да, будет тебе известно, что string на Английском означает «строка», строка текста, если тебя больше так лучше понятно. Так вот, передать текст, через сокет – это не ересь, а формат данных (текстовый формат, если ты не понял). И функция называется SendText … надеюсь с этим проблем нет!
Ты мне напоминаешь дурного ребёнка. Если тебе нужно отдельно объяснять, что имелось ввиду в вопросе, то извини это не лечится! А все эти дурные статьи, которые ты так ценишь, я ещё лет 5-7 назад все перечитал. Так что успокойся.
Digitman (2005-07-22 17:30:00) [14]
> Wm.DIGGER © (22.07.05 17:03) [10]
> ты проверь ка
и проверять не буду даже, ибо содрал ты это бездумно с демо-примера, каковой мне давным-давно известен
> сначала тоже написал в другом порядке, а вызываются они
> так,
> как здесь написал
LMD
умерь свою дурь и проштудируй от корки до корки хотя бы это
http://book.itep.ru/7/sock_71.htm
потом уже будешь раздавать направо-нгалево дурацкие "советы начинающим".
> и для локальной сети и для Интернета и вообще РАБОТАЕТ
когда врешь - прищиривай один глаз.
> прекрас тно
впору заняться изучением русского.
> если ты
да, если я.
"стринги через сокеты" есть полная галиматья, а решений для галиматьи я, увы, не имею.
а тебе, сударь, советую прекратить публиковать в Форуме копии зачастую дурных (и не проверенных тобой) примеров от Борланда и заняться изучением различий между синхронным и асинхронным гнездовым транспортом.
Wm.DIGGER (2005-07-22 17:16:00) [15]зато ТАМ это "кретично" !
крИтично в условиях Интерсети ! - ой, боже мой, какое чудо!
ТАМ это где?
в Интерсети твой код работать не будет.
и дело даже не в [7] - в твоем коде полно упрощений, допустимых в ряде случаев лишь для условий лок.сети, если не сказать - для условий лок.хоста
и вообще, откуда ты это всё взял?
такм всего-то: подключение и отправка строки текста и ВСЁ.
это везде одинаково для любой сети!
просили написать ПРОСТОЙ ПРИМЕР!
я написал, да для локального хоста, т.к. это ПРИМЕР!
замени Host := '127.0.0.1'; на 'www.delphimaster.ru', а порт на 80 и подключишься к этому сайту!
в место текста, пошли HTTPшный GET запрос и получишь в ответ главную страницу ... так, что всё, это работает. Не нужно тут сказок рассказывать.
Wm.DIGGER (2005-07-22 17:03:00) [16]Digitman © (22.07.05 16:57) [9]
>последовательность возникновения этих событий строго обратная - сначала Accept, затем Connect
даааа, а ты проверь ка сначала, а потом пиши!
я сначала тоже написал в другом порядке, а вызываются они так,
как здесь написал! И работает это и для локальной сети и для Интернета и вообще РАБОТАЕТ. А если ты такой принципиальный, то написал бы сам, а не разводил тут демагогию.
Digitman (2005-07-22 16:57:00) [17]
> здесь это не кретично
зато ТАМ это "кр етично" !
кр Итично в условиях Интерсети !
в Интерсети твой код работать не будет.
и дело даже не в [7] - в твоем коде полно упрощений, допустимых в ряде случаев лишь для условий лок.сети, если не сказать - для условий лок.хоста
кр.того, прочей отсебячины навалом ..
хочешь еще примеры отсебячины ?
пожалуйста !
procedure TForm1.ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
Form1.Memo1.Lines.Append('Клиент подключился.');
end;
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Form1.Memo1.Lines.Append('Подключается клиент ...');
end;
последовательность возникновения этих событий строго обратная - сначала Accept, затем Connect
еще желаешь примеры отсебячины в твоем коде ?)
Wm.DIGGER (2005-07-22 16:47:00) [18]Digitman © (22.07.05 16:41) [7]
да нет, я просто имел ввиду, что возникла ошибка сокета.
ну, написал случайно слово "подключение" ...
просто в данном, подчёркиваю, самом простом, как просили
примере, это самое вероятное что может возникнуть (если допустим, сервак забыли запустить :-)
я прекрастно понимаю, что ошибка может быть вызвана и другими вещами, но здесь это не кретично. спрашивали, как передать текст,
а не как ошибки обрабатывать. можно было вообще ни чего не писать про ошибки :)
Digitman (2005-07-22 16:41:00) [19]
> Wm.DIGGER © (22.07.05 16:18) [4]
ну взять хотя бы это :
procedure TForm1.ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Form1.Memo1.Lines.Append('Ошибка при подключении: '+IntToStr(ErrorCode));
ErrorCode := 0;
end;
то что возникновение события ClientError ты сопоставляешь с ошибкой при подключении кого-то там к кому-то - это и есть ничто иное как отсебячина.
Wm.DIGGER (2005-07-22 16:30:00) [20]Profik © (22.07.05 16:19) [5]
угу, спасибки ...