Форум программистов, компьютерный форум CyberForum.ru

(WinSock) Условие прихода пакета данных - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 8, средняя оценка - 5.00
AntiAlianKiller
1 / 1 / 0
Регистрация: 08.05.2013
Сообщений: 14
20.07.2013, 00:07     (WinSock) Условие прихода пакета данных #1
Допустим, я хочу написать чат на WinSock. Мне нужно, чтобы при приходе пакета специально отведенный буфер заполнялся данными, после чего выводился на экран в виде текста.
Как определить, пришел ли пакет с данными? Есть ли специальное условие? На подобии " if( если пришел пакет с сервера ) { код }

Сработает-ли такое условие?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
while(true) {
recv(//чтение
             SSock,//сокет
             recv_data,//буфер куда попадут данные
             1024,//размер буфера чтения - сколько считать
             0//делаем ее аналогичной как функция read
             );
 
        if( recv_data[0] == '[' ) { // Если первый символ в буфере данных, пришедших с сервера равен началу любого сообщения... ( [???] ??? ) 
            recv_dataString = gcnew String(recv_data); // передаем строке значение буфера
            textBox4->Text = textBox4->Text + recv_dataString + Environment::NewLine; //Выводим буфер (в виде строки) в текстбокс
            recv_data[0] = '?'; //Заменяем символ, чтобы последнее сообщение, пришедшее с сервера, не выводилось циклично
            }
}
Если я правильно понимаю, пришедший однажды пакет с данными ( recv() ) заполнит буфер единожды, и после повторной проверки ( если запихнуть этот код в цикл ( а надо? ) ) он не будет заполнять буфер последними данными что он получил ( не будет выводить последнее сообщение до бесконечности ). Верно?

Если не правильно понял механику того, как это работает, напишите.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.07.2013, 00:07     (WinSock) Условие прихода пакета данных
Посмотрите здесь:

C++ winsock. ip
C++ Модификатор FAR (WinSock)
C++ WinSock tcp client/server
C++ перекомпиляция пакета на Си
WinPcap - модификация пакета C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Убежденный
Системный программист
 Аватар для Убежденный
14209 / 6224 / 987
Регистрация: 02.05.2013
Сообщений: 10,368
Завершенные тесты: 1
20.07.2013, 00:38     (WinSock) Условие прихода пакета данных #2
Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
Если я правильно понимаю, пришедший однажды пакет с данными ( recv() ) заполнит буфер единожды, и после повторной проверки ( если запихнуть этот код в цикл ( а надо? ) ) он не будет заполнять буфер последними данными что он получил ( не будет выводить последнее сообщение до бесконечности ). Верно?
Верно. Только с одним "но".

TCP - это просто поток байт, в нем нет такого понятия, как пакет или сообщение.
Если на одном конце кто-то вызвал send с "привет, колян!", то на другом конце
recv вовсе не обязана прочесть эту строку за один вызов, может получиться,
например, такая последовательность: "прив", "ет, кол", "ян!". Работать с TCP
следует исключительно как с потоком байт, разбитым на фрагменты заранее
неизвестного размера - только так и никак иначе. Конец "сообщения", если таковое
имеет какой-то смысл в приложении, определяется не количеством байт, прочитанных
за один вызов recv, а по содержимому этих байт (например, по какому-нибудь
маркеру или спец. символу).

Ну и не забывайте, что recv может вернуть код ошибки (-1) или 0. Последнее означает,
что удаленный компьютер разомкнул свой конец соединения.
AntiAlianKiller
1 / 1 / 0
Регистрация: 08.05.2013
Сообщений: 14
20.07.2013, 01:08  [ТС]     (WinSock) Условие прихода пакета данных #3
То есть, в моем случае (бесконечный цикл приема данных) я скорее всего приму не "[Андрей] Привет, колян!", а "[А", "н", "др", "е" и т.д. ? Или сообщение считается до конца ( или в TCP нет такого понятия, как конец или начало сообщения? ), прежде чем будет выведено на экран? Если я понял верно, мне нужно использовать UDP ( recvfrom(), sendto() ) способ подключения для моей задачи?

Добавлено через 8 минут
Если Вам не составит труда, прочитайте внимательно код в основном посте. Если мои догадки верны, то я скорее получу в текстбоксе такую надпись (Если придет сообщение: "[Андрей] Привет, колян! [qweqwe] [123]") :

C++
1
2
3
4
[А 
[q
[1
//Я не уверен, что с такой скоростью считается именно 2 символа ( не более, не менее) - просто привел пример, чтобы было понятно, что я имею ввиду
Или, если все-же сообщение считается до конца, то:

C++
1
[Андрей] Привет, колян! [qweqwe] [123]
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
20.07.2013, 01:46     (WinSock) Условие прихода пакета данных #4
Если Вам не составит труда, прочитайте внимательно код в основном посте. Если мои догадки верны, то я скорее получу в текстбоксе такую надпись (Если придет сообщение: "[Андрей] Привет, колян! [qweqwe] [123]") :
Скорее всего нет. Убежденный указал вам, что recv() вовсе не обязательно прочитает всё сообщение сразу (хотя для такого короткого сообщения скорее всего так и будет). То есть, сообщение может фрагментироваться на букве "л" (например) и вы получите "[Андрей] Привет, кол". Оставшаяся часть будет принята при следующем вызове recv() но выведена в текстбокс не будет т.к. не пройдет проверку условием.
Убежденный
Системный программист
 Аватар для Убежденный
14209 / 6224 / 987
Регистрация: 02.05.2013
Сообщений: 10,368
Завершенные тесты: 1
20.07.2013, 10:15     (WinSock) Условие прихода пакета данных #5
Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
То есть, в моем случае (бесконечный цикл приема данных) я скорее всего приму не "[Андрей] Привет, колян!", а "[А", "н", "др", "е" и т.д. ? Или сообщение считается до конца ( или в TCP нет такого понятия, как конец или начало сообщения? )
Именно. Нет такого понятия.
TCP - это просто поток байт. recv принимает этот поток частями заранее неизвестного размера.

Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
Если я понял верно, мне нужно использовать UDP ( recvfrom(), sendto() ) способ подключения для моей задачи?
Переходить на UDP необязательно, данная задача может быть решена и на TCP, просто
нужно использовать какой-то маркер для того, чтобы обозначать конец сообщения.
И recv вычитывать данные до тех пор, пока не встретится этот маркер (или ошибка).
AntiAlianKiller
1 / 1 / 0
Регистрация: 08.05.2013
Сообщений: 14
20.07.2013, 12:12  [ТС]     (WinSock) Условие прихода пакета данных #6
Т.е. нужно использовать GetToken? "[Андрей] Привет, колян!%", и считывать вплоть до символа '%' ? Как реализовать такой код? Я не совсем понимаю.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.07.2013, 13:49     (WinSock) Условие прихода пакета данных
Еще ссылки по теме:

Winsock C++ клиент - сервер C++
Winsock - UDP вместо ТСР C++
C++ Winsock.h ругается на ssleay32.dll

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Убежденный
Системный программист
 Аватар для Убежденный
14209 / 6224 / 987
Регистрация: 02.05.2013
Сообщений: 10,368
Завершенные тесты: 1
20.07.2013, 13:49     (WinSock) Условие прихода пакета данных #7
Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
Как реализовать такой код? Я не совсем понимаю.
Прежде всего, нужна система определения границ сообщений, передающихся по TCP.
Сам TCP, как Вы уже поняли, таких границ не предоставляет. Поэтому нужен протокол
поверх TCP, в котором эти границы были бы определены. Например, можно каждое
сообщение предварять определенным количеством байт, в которых указывать его длину.
Тогда recv сначала будет вычитывать из сокета эти байты, а затем, получив длину,
вычитывать остаток сообщения, зная сколько именно байт должно прийти.

Другой распостраненный подход - определять конец сообщения по его содержимому.
Например, в HTTP большинство сообщений имеют заголовок, в котором указывается
длина, а затем тело указанной длины. Для Вашего случая подойдет какой-нибудь
специальный символ-разделитель, который не встречается в тексте - как на счет \0 ?
То есть: "Привет, Андрей !0Как дела ?0Где вчера пропадал ?0".

Итак, протокол сформирован, теперь нужен парсер протокола - компонент, которому
вы сможете "скармливать" данные, порезанные сетью на фрагменты, и который будет
"склеивать" из них целые сообщения. Например, отправляем в парсер "При", "вет, А",
"ндрей!0Как д", "ела", "?0" - он возвращает нам строку "Привет,
Андрей" (без нуля, разумеется), затем "Как дела ?" и т.д.

Ну а дальше все просто - читаете в цикле данные из recv и кидаете их в парсер.
Он возвращает готовые целые сообщения, которые можно отображать в окне чата.
Yandex
Объявления
20.07.2013, 13:49     (WinSock) Условие прихода пакета данных
Ответ Создать тему
Опции темы

Текущее время: 05:38. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru