Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2003.10.09;
Скачать: [xml.tar.bz2];

Вниз

Чаты без сокетов   Найти похожие ветки 

 
Doctor Deejay   (2003-08-07 15:26) [0]

Помогите мне разобраться.... Каким образом работают чаты, у которых нет разделения между кллиентской частью и серверной??? Где-то слышал, что это UDP.
Подскажите, если кто знает. Может статья где-то есть. Как оно работает???
Или скелет такого чата(без наворотов), который показал бы принцип работы.....


 
Erik Ivanov   (2003-08-07 16:52) [1]

Бери Indy и смотри примеры.


 
Rouse_   (2003-08-07 17:07) [2]

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

Желаю успехов


 
Doctor Deejay   (2003-08-08 01:55) [3]


> Rouse_ © ( 07.08.03 16:52)

> Rouse_ ©


А как чат у одного человека может знать, где запущена еще копия? Диапазон всех IP в мире не такой и маленький, чтобы все опрашивать по какому-то порту... :?



> Erik Ivanov (07.08.03 16:52)
> Бери Indy и смотри примеры.


Они есть в 6 Делфи. Какой именно компонент?


 
Rouse_   (2003-08-08 02:19) [4]

> Диапазон всех IP в мире не такой и маленький

Вам так кажется.
Первое: идет ограничение маской подсети
Второе идет ограничение по адресу
К примеру, не обязательно (при соответствующих настройках) что броадкаст с адреса 192.0.0.1 дойдет до адреса 192.0.1.1 (в моей домашней сети доходит только каждый четвертый - шестой пакет).
А вот на адрес 192.0.0.243 - пакет придет обязательно.

Желаю успехов

ЗЫ: Да, а при чем тут мир?
ЗЗЫ: TIdUDPClient, TIdUDPServer + (желательно прописать в uses: IdSocketHandle)


 
Doctor Deejay   (2003-08-08 11:06) [5]


> ЗЫ: Да, а при чем тут мир?


Хочу сделать чат, в котором моглы бы общеться люди с разных городов, но без html и тормознутых обновлений...

Тогда может подскажете мысль???

У меня была идея сделать ответный модуль на php, но я в нем не так силен. Этот модуль и был бы серверов.

Есть еще способ закидывать мессаги на какой-то сайт, а потом заставлять всех их оттуда читать.. Но там только с обновлением... :(


 
servs   (2003-08-08 11:20) [6]

По протоколу Аськи не лучше?

ИМХО peer2peer чаты есть смысл юзать только в локалке.


 
Rouse_   (2003-08-08 11:53) [7]

Ёёё, ну а кто Вам сказал что такие чаты не имеют выделенной серверной части? Я думал, что речь идет о локальном чате. И использование UDP нецелесообразно для таких вещей. А если в PHP не сильны, то посмотрите статьи по написании WEB приложений средствами Delphi. Они были и на нашем сайте и на Королевстве.

Желаю успехов


 
Doctor Deejay   (2003-08-09 00:46) [8]


> А если в PHP не сильны, то посмотрите статьи по написании
> WEB приложений средствами Delphi


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


> По протоколу Аськи не лучше?


У меня были исходники в свое время...
Тогда встречный вопрос. Аська общается с серверов, который написан на пхп(или пёрле). Допустим я каким-то образом прикручу свою прогу к их серверу и заставлю думать его(сервер) что "это" ISeekU к нему обращается. Но как потом мне заставить свой чат не отправлять и не принимать мессаги с айсикьюшных прог?
Или я не так понял. (кстати, спасибо за идею).

А есть ли еще какие-то варианты?

Или встречный вопрос - если на пхп писать, то как отправить сообщение в программу из скрипта? (хотя наверно я не в тот форум пишу). Вот, например, когда кто-то отправляет сообщение, то передается строка типа lkjhg.php?fff=uuu&hgf=pop&...... А скрипт потом посылает принятое всем остальным. Сответсвенно вопрос: как прогой на делфи это поймать(сообщение)?


 
aa5E1   (2003-08-09 00:54) [9]

вот как сделал это я:

unit uMain;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
WSocket, ComCtrls, ExtCtrls, StdCtrls, RVEdit, RVScroll, RichView,
RVStyle, trctrls, NMUDP, Buttons, ImgList, Menus, abcmenu;

type

TChatMessage = record
code: char;
param1: string;
param2: string;
param3: string;
param4: string;
end;

TfMain = class(TForm)
GroupBox1: TGroupBox;
Panel2: TPanel;
Panel3: TPanel;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
sChat: TRVStyle;
rvChat: TRichView;
Splitter2: TSplitter;
GroupBox2: TGroupBox;
Splitter1: TSplitter;
Splitter3: TSplitter;
GroupBox3: TGroupBox;
teNick: TFlatEdit97;
lvNicks: TListView;
udp1: TNMUDP;
SpeedButton1: TSpeedButton;
ImageList1: TImageList;
mChat: TMemo;
mTopic: TMemo;
pmNicks: TabcPopupMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
N5: TMenuItem;
SpeedButton2: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure udp1DataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SpeedButton1Click(Sender: TObject);
procedure teNickKeyPress(Sender: TObject; var Key: Char);
procedure mChatKeyPress(Sender: TObject; var Key: Char);
procedure teNickExit(Sender: TObject);
procedure mTopicKeyPress(Sender: TObject; var Key: Char);
procedure N3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure SendIt(str:string);
function GetMessage(str: string):TChatmessage;
function GetParam(var tmp:string):string;
procedure ChatString(Chat:TChatMessage);
procedure ReportIn(Chat:TChatMessage);
procedure Report(Chat: TChatMessage);
end;

var
fMain: TfMain;
Nick: string[30];

implementation

{$R *.DFM}

procedure TfMain.FormCreate(Sender: TObject);
begin
Nick := teNick.Text;
SendIt("4"+Nick+#00+"#Main"+#00+"00");
end;

procedure TfMain.SendIt(str: string);
var
MyStream: TMemoryStream;
Begin
MyStream := TMemoryStream.Create;
try
MyStream.Write(Str[1], Length(Str));
UDP1.SendStream(MyStream);
finally
MyStream.Free;
end;
end;

procedure TfMain.udp1DataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
var
MyStream: TMemoryStream;
TmpStr: String;
ChatMessage: TChatMessage;
begin
MyStream := TMemoryStream.Create;
try
UDP1.ReadStream(MyStream);
SetLength(TmpStr,NumberBytes);
MyStream.Read(TmpStr[1],NumberBytes);
finally
MyStream.Free;
end;

ChatMessage := GetMessage(TmpStr);

case ChatMessage.code of
"0": Report(ChatMessage);
"1": ReportIn(ChatMessage);
"2": ChatString(ChatMessage);
end;
end;

function TfMain.GetMessage(str: string): TChatmessage;
begin
Result.code := str[1];
delete(str,1,1);
Result.param1 := GetParam(str);
Result.param2 := GetParam(str);
Result.param3 := GetParam(str);
Result.param4 := GetParam(str);
end;

function TfMain.GetParam(var tmp: string): string;
var
i: integer;
begin
Result := "";
for i:= 1 to length(tmp) do
if Tmp[i] = #00 then
break
else
Result := Result + tmp[i];
delete(Tmp,1,Length(Result)+1);
end;


procedure TfMain.ChatString(Chat: TChatMessage);
var
st: integer;
begin
st := 0;
if Chat.param2 = teNick.Text then
st := 1;
rvChat.AddNL("<"+chat.param2+"> "+chat.param3,st,0);
rvChat.FormatTail;
end;

procedure TfMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SendIt("5"+Nick+#00+"#Main"+#00+"00");
end;

procedure TfMain.SpeedButton1Click(Sender: TObject);
begin
lvNicks.Items.Clear;
SendIt("0"+Nick+ #00 + "00");
end;

procedure TfMain.ReportIn(Chat: TChatMessage);
begin
//1Terran|zilot|10
if Chat.param1 = Nick then
lvNicks.Items.Add.Caption := Chat.param2;
end;

procedure TfMain.Report(Chat: TChatMessage);
var
mon: integer;
begin
//if fMain.Showing then
// mon := 1;
SendIt("1"+Chat.param1+#00+Nick+#00+#1);//+"03"+inttostr(mon));
end;

procedure TfMain.teNickKeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
begin
SendIt("3"+Nick+#00+teNick.Text+#00+"10"+#00);
Nick := teNick.Text;
end;
end;

procedure TfMain.mChatKeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
begin
SendIt("2#Main" + #00 + Nick + #00 + mChat.Lines.Strings[mChat.Lines.Count-1] + #00);
end;
end;

procedure TfMain.teNickExit(Sender: TObject);
begin
teNick.Text := Nick;
end;

procedure TfMain.mTopicKeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
begin
SendIt("B"+mTopic.Lines.GetText);
( Sender: TObject)
вот как сделал это я:

unit uMain;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
WSocket, ComCtrls, ExtCtrls, StdCtrls, RVEdit, RVScroll, RichView,
RVStyle, trctrls, NMUDP, Buttons, ImgList, Menus, abcmenu;

type

TChatMessage = record
code: char;
param1: string;
param2: string;
param3: string;
param4: string;
end;

TfMain = class(TForm)
GroupBox1: TGroupBox;
Panel2: TPanel;
Panel3: TPanel;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
sChat: TRVStyle;
rvChat: TRichView;
Splitter2: TSplitter;
GroupBox2: TGroupBox;
Splitter1: TSplitter;
Splitter3: TSplitter;
GroupBox3: TGroupBox;
teNick: TFlatEdit97;
lvNicks: TListView;
udp1: TNMUDP;
SpeedButton1: TSpeedButton;
ImageList1: TImageList;
mChat: TMemo;
mTopic: TMemo;
pmNicks: TabcPopupMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
N5: TMenuItem;
SpeedButton2: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure udp1DataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SpeedButton1Click(Sender: TObject);
procedure teNickKeyPress(Sender: TObject; var Key: Char);
procedure mChatKeyPress(Sender: TObject; var Key: Char);
procedure teNickExit(Sender: TObject);
procedure mTopicKeyPress(Sender: TObject; var Key: Char);
procedure N3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure SendIt(str:string);
function GetMessage(str: string):TChatmessage;
function GetParam(var tmp:string):string;
procedure ChatString(Chat:TChatMessage);
procedure ReportIn(Chat:TChatMessage);
procedure Report(Chat: TChatMessage);
end;

var
fMain: TfMain;
Nick: string[30];

implementation

{$R *.DFM}

procedure TfMain.FormCreate(Sender: TObject);
begin
Nick := teNick.Text;
SendIt("4"+Nick+#00+"#Main"+#00+"00");
end;

procedure TfMain.SendIt(str: string);
var
MyStream: TMemoryStream;
Begin
MyStream := TMemoryStream.Create;
try
MyStream.Write(Str[1], Length(Str));
UDP1.SendStream(MyStream);
finally
MyStream.Free;
end;
end;

procedure TfMain.udp1DataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
var
MyStream: TMemoryStream;
TmpStr: String;
ChatMessage: TChatMessage;
begin
MyStream := TMemoryStream.Create;
try
UDP1.ReadStream(MyStream);
SetLength(TmpStr,NumberBytes);
MyStream.Read(TmpStr[1],NumberBytes);
finally
MyStream.Free;
end;

ChatMessage := GetMessage(TmpStr);

case ChatMessage.code of
"0": Report(ChatMessage);
"1": ReportIn(ChatMessage);
"2": ChatString(ChatMessage);
end;
end;

function TfMain.GetMessage(str: string): TChatmessage;
begin
Result.code := str[1];
delete(str,1,1);
Result.param1 := GetParam(str);
Result.param2 := GetParam(str);
Result.param3 := GetParam(str);
Result.param4 := GetParam(str);
end;

function TfMain.GetParam(var tmp: string): string;
var
i: integer;
begin
Result := "";
for i:= 1 to length(tmp) do
if Tmp[i] = #00 then
break
else
Result := Result + tmp[i];
delete(Tmp,1,Length(Result)+1);
end;


procedure TfMain.ChatString(Chat: TChatMessage);
var
st: integer;
begin
st := 0;
if Chat.param2 = teNick.Text then
st := 1;
rvChat.AddNL("<"+chat.param2+"> "+chat.param3,st,0);
rvChat.FormatTail;
end;

procedure TfMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SendIt("5"+Nick+#00+"#Main"+#00+"00");
end;

procedure TfMain.SpeedButton1Click(Sender: TObject);
begin
lvNicks.Items.Clear;
SendIt("0"+Nick+ #00 + "00");
end;

procedure TfMain.ReportIn(Chat: TChatMessage);
begin
//1Terran|zilot|10
if Chat.param1 = Nick then
lvNicks.Items.Add.Caption := Chat.param2;
end;

procedure TfMain.Report(Chat: TChatMessage);
var
mon: integer;
begin
//if fMain.Showing then
// mon := 1;
SendIt("1"+Chat.param1+#00+Nick+#00+#1);//+"03"+inttostr(mon));
end;

procedure TfMain.teNickKeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
begin
SendIt("3"+Nick+#00+teNick.Text+#00+"10"+#00);
Nick := teNick.Text;
end;
end;

procedure TfMain.mChatKeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
begin
SendIt("2#Main" + #00 + Nick + #00 + mChat.Lines.Strings[mChat.Lines.Count-1] + #00);
end;
end;

procedure TfMain.teNickExit(Sender: TObject);
begin
teNick.Text := Nick;
end;

procedure TfMain.mTopicKeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
begin
SendIt("B"+mTopic.Lines.GetText);
end;
end;

procedure TfMain.N3Click(Sender: TObject);
begin
mChat.Lines.Add(lvNicks.Selected.Caption);
end;

end.


но это еще не идеал... это пародия на QChat


 
aa5E1   (2003-08-09 00:58) [10]

савсем забыл... :)... извините вот еще приложение DFM файл где и есть все необходимые настройки UDP компоненты :

object fMain: TfMain
...
object udp1: TNMUDP
RemoteHost = "192.168.1.255"
RemotePort = 8167
LocalPort = 8167
ReportLevel = 1
OnDataReceived = udp1DataReceived
Left = 119
Top = 178
end
...
end
end


жаль но все не влезло... если тебе интересно то могу выслать мылом исходник полный...


 
Doctor Deejay   (2003-08-09 11:59) [11]

Насчет ICQ. Немного порылся в сети. Вот, что нашел:

.............Пакеты Клиент - Сервер посылаются с использованием протокола UDP ICQ серверу.
Пакеты, посылаемые от клиента к серверу, зашифрованы до их посылки, в отличие от пакетов, посылаемых от сервера клиенту, которые не шифруются............

Всё-таки UDP, но вы мне говорили, что это только в пределах подсети с диапазоном x.x.x.0 - x.x.x.255.


 
SkyN   (2003-08-09 12:07) [12]

Мы говорили о широковешательных пакетах, а они только в подсети, и не обязатьло диапозон будет x.x.x.0 - x.x.x.255. А так если 2 IP извесно, то можно общаться и по UDP


 
Doctor Deejay   (2003-08-09 12:10) [13]


> А так если 2 IP извесно, то можно общаться и по UDP


А если эти IP просто прописывать где-то в инете (на каком-то сайте). А потом рассылать мессаги по этому списку? С сервера делать пинг и следить за состоянием чатлан?


 
Rouse_   (2003-08-09 12:28) [14]

В данном варианте сервер должен собирать информацию от чатов и отправлять ее остальным. Заметьте серверов может быть несколько и они также должны взаимодействовать между собой. А за своевременное обновление информации должен отвечать клиент. Единственно, можно сделать таймлимит на сервере, если по истечении таймлимита от клиента не пришла ни один пакет информации - считать его R.I.P.

Естественно все адреса серверов изначально должны быть известны клиентам.

Желаю успехов


 
Проходил мимо   (2003-08-09 12:41) [15]

Не обязательно делать сервер в интернете, можно его установить на локальном компе. Завести специально мыло которое будет доступно всем участникам чата а в клиент запихнуть какой-нибудь idSMTP и пусть сервер отсылает письмо со своим IP на известное мыло. Клиенты его получают и подключаются к серверу... Разве не красота?


 
Rouse_   (2003-08-09 13:00) [16]

> Проходил мимо (09.08.03 12:41

Ну это один из вариантов, в прошлом году он обсуждался
Его плюсы высокая надежность
Минусы - издержки с разбором писем

Желаю успехов


 
Doctor Deejay   (2003-08-09 21:30) [17]


> отсылает письмо со своим IP на известное мыло. Клиенты его
> получают и подключаются к серверу...


У меня нет возможности повеситься на выделенке.. Уж простите, но финансы поют романсы. Мне же за это никто не платит. Чистый энтузиазм :)


> В данном варианте сервер должен собирать информацию от чатов
>

Кстати, я так и не понял принцип.




А почему сам чат не может это сделать? Например, закачать список, потом пропинговать всех. Если кто-то дохлый, то написать напротив его IP - RIP. И делать такую проверку при подключении и раз в минуту. Как вам такое?


> и пусть сервер отсылает письмо со своим IP на известное
> мыло. Клиенты его получают и подключаются к серверу...



> Ну это один из вариантов, в прошлом году он обсуждался


Это намек, что я не первый такой? А моих предшественников что-то вышло?


 
Проходил мимо   (2003-08-09 23:15) [18]

> Doctor Deejay
И что всю сеть пинговать? Список то откуда взять?
А выделенка не нужна. Зачем?
Для непонятливых:
Подключаешься к интернету, твой сервер узнает IP и отсылает его в письме на мыло которое известно всем любителям этого самодельного чата :) Клиент получает письмо узнает адрес сервера и подключается к нему. И никакая выделенка не нужна. Или чат должен быть постоянно доступен? Тогда другое дело...


 
Doctor Deejay   (2003-08-10 03:00) [19]


> Или чат должен быть постоянно доступен? Тогда другое дело...


Да и я о том же. Я хочу сделать icq, но по возможности без сервера. Если не выйдет - попробовать юзать сервер самого icq. Если и этот вариант не катит, тогда я возьму в руки книгу по пхп, кот. пылится у меня на столе... и тряхну стариной... заранее знаю, что это самый геморный вариант... :(



> И что всю сеть пинговать? Список то откуда взять?


Попытаюсь объяснить проще:
Есть три человека, кот. хотят пообщаться, но заходят в разное время(9-00, 10-00 и 10-30). Где-то в инете, на каком-то сайте(народ.ру подойдет, но лучше платный) зарезервировано место. Запустившись, чат первого чела дописывает в файл строчку со своим ip, предварительно его закачав. Затем пингует все ip, кот. там прописаны. Если ответ пришел от кого-то, то он добавляется в список юзеров в чате. Такая проверка делается раз в минуту(или реже). Затем заходит второй чел и его чат делает тоже самое.

Теперь самое интересное: предположим, что кто-то закрых чат по 3 кнопкам или его просто отключило от инета. Тогда кто-то начнет проверять(пинговать), но не получит ответа. Вполне вероятно, что и ip у того чатла точно такой же очень не скоро появится(динамический, типа). Тут есть вариант - чистить список с мертвыми раз в сутки первым, кто зайдет и ставить где-то пометку о том, что сегодня чистка производилась.

Отправка сообщений всем - только из живых(кот. вися в списке).
Пометка IP как дохлого - писать рядом с ним RIP, например.

Размеры файлов:
для 100 человек - 123.123.123.123(15 знаков * 100 = 1,5 кила)
для 1000 - 15 кил.
Больше общаться не будет!

Единственное, что меня беспокоит - это скорость закачки и скачки этих файлов.


ВОТ ТАКОЙ АЛГОРИТМ. ПИСАТЬ Я ПОКА НЕ НАЧАЛ. ХОЧУ УСЛЫШАТЬ ВСЕ ЕГО МИНУСЫ... (если они есть)


> твой сервер узнает IP и отсылает его в письме на мыло которое
> известно всем любителям этого самодельного чата :)


P.S. А мне казалось, что все чаты самодельные :)


 
Doctor Deejay   (2003-08-12 14:05) [20]

Почему такое затишье????


 
Doctor Deejay   (2003-08-13 01:04) [21]

Так вы одобряете мой алгоритм?



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

Форум: "Сети";
Текущий архив: 2003.10.09;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.009 c
1-27519
k_len
2003-09-26 11:03
2003.10.09
Форма


9-27295
VEG
2003-04-05 20:12
2003.10.09
Вот такая проблема...


1-27598
diww
2003-09-30 12:54
2003.10.09
Как удалить из файла N символов начиная с I?


1-27597
Кен
2003-09-29 07:20
2003.10.09
Как сделать, чтобы через определённый промежуток времени,


14-27658
heady
2003-09-17 13:45
2003.10.09
вопрос по bat нику можно?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский