LINUX.ORG.RU

ESMTP, чтение-запись из сокета


0

0

2. Увидел в протоколе ESMTP, что может быть несколько ответов: ehlo office.company1.tld 250-mail.company2.tld is pleased to meet you 250-DSN 250-SIZE 250-STARTTLS 250-AUTH LOGIN PLAIN CRAM-MD5 DIGEST-MD5 GSSAPI MSN NTLM 250-ETRN 250-TURN 250-ATRN 250-NO-SOLICITING 250-HELP

Хотя про SMTP было написано в той же Википедии, что ответ всегда 1 строка. (То есть, когда реализуешь протокол SMTP, надо дождаться приема символов 0D 0A в ответ, да?)

Telnet (стандартный, из FreeBSD) работает по схеме "ввели 1 символ - послали", да? И вообще при такой передаче, получив один символ на любой стороне, никак нельзя сказать, собирается ли вторая сторона послать за ним еще символы (считая их неразрывным по смыслу целым) или нет? Т.е. нужно ждать определенного признака, например того же 0D 0A (cr lf)?

Как же тогда можно работать по протоколу ESMTP, ведь откуда клиент знает, сколько строчек ему послал сервер?

3. Что должна делать нормальная функция приема ответа от сервера? Где можно найти ее схему. Имеется в виду надежное соединение, по TCP. Например, есть такая книжка - Теренс Чан. Системное программирование на C++ для Unix. Так у него ничего из нижеперечисленного нету (просто вызов recv(), подразумевается, что он примет абсолютно все данные, посланные другой стороной по одному вызову send(), за один вызов recv). А я современные функции почитал - там целая куча всего. - Вроде бы количество прочитанных байт 0 означает, что у той стороны, наконец, нет ничего, что бы она хотела нам послать. Но с другой стороны, вторая сторона вроде в любой момент может передумать и решить послать еще данные, новым вызовом send... С другой стороны походит, что возврат recv 0 прочитанных байт сродни нулю в ASCIIZ-строке, разделяющему одну строку из идущих подряд от другой. А если мы не успели дочитать первую строку “KISA1”, сервер послал уже вторую “KISA2”... То прочитав 0, мы можем подумать, что более нам ничего не посылали, в то время как там еще вторая строка? Или это неправда? Т.е. что мы прочитаем из сокета: 5 байт + “KISA1” – 0 байт – 5 байт + “KISA2” – 0 байт ? Или : 5 байт + “KISA1” – 5 байт + “KISA2” – 0 байт? Или 10 байт + “KISA1KISA2” – потом 0 байт? - Если прочитано не 0 байт из сокета, то большинство функций чтения (не как у Чана!) читают и читают, пока не прочитают 0 байт. - Надо как-то ловить разрывы соединения (по ошибке) и нормальное закрытие сокета второй стороной (как???? У Теренса Чана об этом ничего не сказано).

Можно ли различить на второй стороне 2 случая: а) первая сторона послала туда первым вызовом send() строку из 40 байт, вторым – еще строку из 40 байт; б) первая сторона послала все 80 байт одним вызовом send(). Я подумывал, что функция recv возвращает 0 прочитанных байт, именно чтобы дать знать, что кончились за один раз посланные данные. Т.е. например в случае с ESMTP когда очередное обращение вернет 0 прочитанных байт, значит мы дочитали все строчки этого длинного ответа сервера (см. выше про ESMTP). А то может быть, если сообщение шло частями (не гарантируется доставка мгновенно и всего сразу), то может ли быть так, что прочитается из сокета первая часть сообщения, а потом, т.к. остаток еще не пришел, то прочитается 0 байт?? Не преждевременно ли будет в таком случае считать ответ полностью полученным. И может ли такое случиться.

Все вопросы - http://unixvop.narod.ru/


1) Search - возможность прочитать содержимое диры
т.е. список элементов которые она содержит.
2) RFC почитай что-ли для начала, в многострочном ответе
последняя строка содержит признак того что она последняя.
3) TCP стрим ориентированный протокол, ты можешь сделать
3000 сендов а получить все что послал одним ресивом,
если тебе надо создать какие-то мессаги, сам позаботься
о том чтобы принимающая сторона могла определить их границы.
А если recv вернул 0 это значит другая сторона закрыла соединение.

Tima2008
()
Ответ на: комментарий от Tima2008

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

Теперь на часть вопроса, что созрел у меня утром, можно дать ответ - "нормально закрытый сокет вернет 0 байт". ((1) - А пока он не закрыт, но даже 1 байтом принятым не можем похвастаться, мы будем висеть и ждать, вместо того чтобы вернуть 0 байт?)

Вопрос же был такой - очень буду рад получить ответ, хотя мне кажется, тут просто либо можно различить коды в errno, либо нет: "(2) - Можно ли отличить принятые 2 байта и разрыв после этого (сервер взорвался промежуточный) от принятых 2 байт и благополучного закрытия сокета от принятых 2 байт, после чего вторую сторону сняли по ^C от приняли 2 байта, после чего вторая сторона получила suspend."

И еще был вопрос, эквивалентный вопросу 1 - можно ли получить скажем 2байта(КИ) + 0 байт (ничего пока не готово) + 2байта(СА), если та сторона отправила "КИСА"? (ну что мало байт это пример, можно увеличить их число).

Vedmak
() автор топика
Ответ на: комментарий от Vedmak

Непонятно зачем такие вопросы, и не уверен что правильно их понял, но тем не мение попробую ответить.

Если случился разрыв связи то один вызов recv вернет что принято, к примеру 2кб данных, а следующий -1, если другая сторона коректно закрыла соединение, то второй recv вернет 0 Только вот определить разрыв соединения не так просто, поэтому можно висеть в recv очень долго, хотя передающая сторона уже давно выключилась. Поэтому если надо поддерживать связь все протоколы поверх TCP на это ориентированные имеют свою реализацию некого механизма "пинга", чтобы определить есть ли связь, и соответственно оговоренные таймауты.

Да можно отправить кусок данных одним сендом а получить получить их несколькими recv.

Tima2008
()
Ответ на: комментарий от Vedmak

>И еще был вопрос, эквивалентный вопросу 1 - можно ли получить скажем 2байта(КИ) + 0 байт (ничего пока не готово) + 2байта(СА), если та сторона отправила "КИСА"? (ну что мало байт это пример, можно увеличить их число).

Нет НЕЛЬЗЯ. Ты можешь получить при recv() либо EAGAIN, если у тебя неблокируемый сокет, либо заснуть на операции чтения, если у тебя блокируемый сокет. Если ты получил 0 при возврате из recv() на сокете, то это ОДНОЗНАЧНО закрытие соединения.

pathfinder ★★★★
()

Впервые слышу про ESMTP. Чем отн отличается от SMTP?

pacify ★★★★★
()

> ... 0D 0A ...

Да. Точно помню, что на практике, клиенты по FTP обычно завершают строки цепочкой '\r\n', \r - return carriage (возврат каретки), код \x0D \n - new line (перевод каретки на новую строку), код \x0A.

Соответственно, '\r\n' = '\x0D\x0A', так как CR = '\x0D', LF = u'\x0A'.

pacify ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.