Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблемы с сокетами [D7, WinXP]


Страницы:   1 2

maxistent ©   (2008-01-10 20:00:00) 

Добрый вечер, ув. Мастера! Помогите разобраться вот в чем. Я нашел одну статью по сокетам и оттуда взял готовые кусочки кода для сервера и клиента. Вот они:
Код сервера:

var S,AcceptedSock:TSocket;
   Addr:TSockAddr;
   Data:TWSAData;
   Len:Integer;
begin
 WSAStartup($101,Data);
 S:=Socket(AF_Inet,Sock_Stream,0);
 Addr.sin_family:=PF_Inet;
 Addr.sin_port:=HToNS(1234);
 Addr.sin_addr.S_addr:=InAddr_Any;
 FillChar(Addr.Sin_Zero,SizeOf(Addr.Sin_Zero),0);
 Bind(S,Addr,SizeOf(TSockAddr));
 Listen(S,SoMaxConn);
 Len:=SizeOf(TSockAddr);
 AcceptedSock:=Accept(S,@Addr,@Len);
 { Теперь Addr содержит адрес клиента, с которым установлено
   соединение, а AcceptedSock - дескриптор, обслуживающий это
   соединение. Допустимы следующие действия:
    Send(AcceptedSock,…) - отправить данные клиенту
    Recv(AcceptedSock,…) - получить данные от клиента
    Accept(…) - установить соединение с новым клиентом }


Код клиента:

var S:TSocket;
   Addr:TSockAddr;
   Data:TWSAData;
begin
 WSAStartup($101,Data);
 S:=Socket(AF_Inet,Sock_Stream,0);
 Addr.sin_family:=AF_Inet;
 Addr.sin_port:=HToNS(1234);
 Addr.sin_addr.S_addr:=Inet_Addr('127.0.0.1');
 FillChar(Addr.Sin_Zero,SizeOf(Addr.Sin_Zero),0);
 Connect(S,Addr,SizeOf(TSockAddr));
 { Теперь соединение установлено. Допустимы следующие действия:
    Send(S,…) - отправить данные серверу
    Recv(S,…) - получить данные от сервера }

Проблема в том, что локально (на одном компе) этот код работает, а через ИНЕТ почему-то сервер не реагирует на входящий коннект, кагбутта ево нету :-( а клиент при попытке коннекта вроде как подключается, но видно, что НЕ ТУДА, КУДА НАДО. Может в коде что-то не так? Подскажите, кто чем может...


maxistent   (2008-01-15 06:17:00) [1]

=-о  О как!.. ясно... пасиб за замечания.


Slym   (2008-01-15 04:14:00) [2]

maxistent ©   (14.01.08 16:50) [23]
for i:=0 to x do
param.Buffer[param.DataSize-x+i]:=buf[i];

пипец...
зачем данные накапливаешь? всеравно каждый раз DoOnRead вызываешь в котором скорее всего буфер чистишь
maxistent ©   (14.01.08 16:50) [23]
передать в параметрах Buffer и DataSize

проблемы передать 2 параметра? если var buf; то передавать Buffer:array of char; нужно как Buffer[0]

и зачем весь этот гемор? твой самодельный сервер с кучей ошибок завалить будет проще пареной репы...
for i:=0 to x do
for i:=0 to x do// принято х, а копируем x+1 раз....
т.е. теоретически посылая по 1 байту ты огребешь по 2 причинам:
1. переполнение буфера на 1 байт
2. SetLength(MainBuffer,1); приведет к фрагментации памяти и дальнейшему краху сервера


maxistent   (2008-01-14 17:55:00) [3]

p.s. Как-то даже не удобно... я почти ушел от темы...


maxistent   (2008-01-14 17:53:00) [4]

Я "сохраняю" входящий поток данных в массив <Buffer:array of char>. Теперь мне нужно написать обработчик, который смог бы сделать что-то вроде

ClientSocket1.Socket.ReceiveBuf();

точнее, написать функцию ReceiveBuf для своей конкретной задачи:

Function ReceiveBuf(var buf; BufSize:integer):integer;
begin
что здесь сделать,
чтобы в <Buf> скопировать <BufSize> байт из <Buffer>?
я не знаю, как преобразовать... :-(
end;


Григорьев Антон   (2008-01-14 17:29:00) [5]


> maxistent ©   (14.01.08 16:50) [23]
> Статья нормальная. Но желательно было бы в конце пару-тройку
> примеров приводить :-)

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

> ...Вот тут я незнаю что сделать...

Что-то как-то я не понял, что именно вызывает затруднения. Что именно вы не знаете как сделать?


maxistent   (2008-01-14 17:20:00) [6]

???


Сергей М.   (2008-01-14 17:17:00) [7]


> maxistent ©   (14.01.08 16:50) [23]


Ты бы к Кетмарю обратился - он знает куда тебе, твентинейджеру, податься.


maxistent   (2008-01-14 16:50:00) [8]

Статья нормальная. Но желательно было бы в конце пару-тройку примеров приводить :-) Тада п ей ваще небыло п цены :-) Я по ней почти всё сделал. Вот только с "чтением" данных не могу разобрацо... Я сделал отдельный поток для recv() и там же определяю: если result<=0, то коннект, наскока я понимаю, пропал (выполняю необходимые действия). Если же result>0, то я делаю сохраняю данные в массив. Вот примерно так это выглядит:

x:=recv(FClientSocket,buf,BufSize,0);
if x>0 then
begin //Данные есть
inc(DataSize,x);
SetLength(MainBuffer,DataSize);
for i:=0 to x do
param.Buffer[param.DataSize-x+i]:=buf[i];
DoOnRead;
end
else
begin //Данных нету
DoOnDisconnect;
break;
end;

DoOnRead;
begin
//Здесь у меня есть
Buffer:array of char;
DataSize:integer;
Здесь нужно вызвать ещё одну процедуру обработки и передать в параметрах Buffer и DataSize.
end;

Procedure DoOnRead(var buf; BufSize:integer);
begin
if @OnClientRead<>nil then
begin
...Вот тут я незнаю что сделать...
??? OnClientRead(buf,BufSize); ???
end;
end;


Slym   (2008-01-14 09:49:00) [9]

Григорьев Антон ©   (14.01.08 9:18) [19]
А проверки в таких примерах я опускал

как в сексе: сначала научись предохраняться - пользоваться призервативом,
а уж потом учи матчасть применения "девайса"
Connect("Девушка")//нету проверки - девушка ли это?
Write("Туды")// raise Exception.Create("Не туда..:)")
Read("Сюды")// raise Exception.Create("Словили трепака")
Close("Девушка")// raise Exception.Create("через 9 месяцев Out of memory, Произошло рождение ошибки молодости")


Григорьев Антон ©   (14.01.08 9:18) [19]
это не готовые примеры, а иллюстрации последовательности вызова сокетных функций для получения нужного результата

тыды надо пЕсать что это псевдокод и компиляции не подлежит... (как приведено выше :) )


Григорьев Антон   (2008-01-14 09:38:00) [10]


> Slym ©   (14.01.08 09:36) [20]
> P.S. Дайте хоть ссылку на статью, а то хаю неведомо что
> :)

http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1021


Slym   (2008-01-14 09:36:00) [11]

Григорьев Антон ©   (14.01.08 9:18) [19]
Пример - он на то и пример: "Делай так и будет работать".
А все что иначе не пример, а никчему не обязывающая демонстрация работы CTRL+V
P.S. Дайте хоть ссылку на статью, а то хаю неведомо что :)


Григорьев Антон   (2008-01-14 09:18:00) [12]


> Slym ©   (11.01.08 04:28) [1]
> > Я нашел одну статью по сокетам
> если в статье не описано как вызывать функции то это плохая
> статья...

Так как речь идёт о моей статье, приходится оправдываться :)

Сразу после процитированного в [0] кода там написано:

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

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

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


Сергей М.   (2008-01-12 18:13:00) [13]


> с это функцией я ещё не разобрался


Как раз есть повод.


> Это глюк?


Нет, это нормальное поведение функции.


maxistent   (2008-01-12 18:04:00) [14]


> с пом. ф-ции select()

с это функцией я ещё не разобрался...

> по результату вызова send() или recv()

хм... Пока коннект не установлен, вызов ф-ии recv() возвращает -1. После успешного коннекта вызов ф-ии recv() возвращает 0 (ну, если данные не идут ОТТУДА). Так и должно быть, наскока я понимаю. НО И ПОСЛЕ ДИСКОННЕКТА эта функция возвращает 0, и WSAGetLastError=0 <=-о Как быть? Это глюк?


Сергей М.   (2008-01-12 17:06:00) [15]


> слишком много "напихано"


Это в TTCPClient/Server понапихано ?!

Аскетичней (безо всяких излишеств) и надежней компонентов чем эти еще поискать надо .


Сергей М.   (2008-01-12 15:34:00) [16]


> maxistent ©   (12.01.08 01:16) [14]


В блокирующем режиме - а ты именно его используешь - узнать о дисконнекте можно, например, с пом. ф-ции select() или по результату вызова send() или recv()


maxistent   (2008-01-12 01:16:00) [17]

Уважаемый Сергей М. !!! В третий раз повторяю: с коннектом я разобрался, во всяком случае, я получил то, что было нужно. Принимать и отправлять данные я тоже умею. Остался один вопрос, и я его уже "озвучил". Если Вы не знаете ответа, или знаете, но не хотите отвечать - дело ваше. Просто молчите и фсьо! Функцию CONNECT в [8] я, как видите, не "обидел". Да и дело даже не в этом... Как я её использую - дело десятое. Главное, чтобы работало. А работает почти фсьо. Кроме дисконнекта. :-/


Сергей М.   (2008-01-11 23:37:00) [18]


> КОННЕКТ Я НАУЧИЛСЯ ДЕЛАТЬ


Судя по вышеприведенному тобой коду, нихрена ты не научился.

Читай [1] до полного просветления.

connect() есть функция, какого же лешего ты используешь ее как процедуру ?


maxistent   (2008-01-11 23:17:00) [19]

Я ж сказал: КОННЕКТ Я НАУЧИЛСЯ ДЕЛАТЬ. А вот как например клиенту узнать что сервер его "БРОСИЛ"? а серверу - что клиент отключился (или связь оборвалась)? Т.е. если я делаю на одной стороне ShutDown и CloseSocket, на другой стороне что должно произойти? Как этот момент отловить?

> А нахрена соббсно что-то делать ?

Чтобы знать, что коннекта больше нету и ничего не слать "ТУДА" и не ждать "ОТТУДА". Думаю, вполне логично :)


Сергей М.   (2008-01-11 22:22:00) [20]


> как поймать момент дисконнекта?


Ты еще момент коннекта на стороне его инициатора не ущучил, а уже о дисконнекте у партнера по коннекту рассуждаешь)


> что нужно сделать на другом конце "провода"


Можно вообще ничего не делать.
А нахрена соббсно что-то делать ?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо