Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564

Send без реальной отправки

07.02.2018, 02:39. Показов 1029. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Ситуация следующяя..

Есть Сервер и Клиент на WinSock, использую обычные Send и Recv. Когда всё нормально, то оба приложения работают нормально (сотни send / recv обрабатываются поочерёдно, т.е. сначала клиент шлёт send, потом 5 сек задержка, затем сервер шлёт send, естественно recv у тех, кто должен принимать).. но чуть какой косяк с коннектом, и тайминг перестаёт совпадать.. то происходят странные вещи..

Самая странная вещь, которую я даже понять не могу такая:
Отправляется файл, ввиду этого, очерёдности нету, т.к. у сервера только send, а у клиента соответственно только recv, так же с таймингом. (т.е. может доходить до сотен send, в зависимости от размера файла) Так вот, если в момент отправки файла клиент решает, что "не нужен мне никакой файл", то он меняет своё состояние recv, на минуту отдыха "sleep" (пока сервер не поймёт, что клиент не хочет докачивать файл), при этом не отключается от конекта с сервером.. Поидее у сервера при посылке очередного send, должен возникать SOCKET_ERROR, но его почему то не происходит, сервер как слал куски файла, так и продолжает, а return значение функции send продолжает возвращять значение, как будто send функция отработала как надо, и на другой стороне кто то принял recv.
Тестировал я это дело на локальной сети, ну т.е. взял два компа, соединил шнуром, выставил маску и айпишники, делая один из компов основным.

Может кто то может помочь с тем почему так происходит, и send не возвращяет SOCKET_ERROR.

Добавлено через 3 часа 44 минуты
P.S.
WinSock версии 2.2 (в WSAStartup передаётся MAKEWORD(2,2))
Библиотека: Ws2_32.lib
Протокол Ipv4. (по крайней мере его свойства я меняю для поднятия локалки)
Код смысла выкладывать не вижу, всё точно так же как и на MSDN.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
07.02.2018, 02:39
Ответы с готовыми решениями:

Можно ли реализовать программу для отправки смс без
Можно ли реализовать программу для отправки смс без запроса на сайт Сотовой компании? Смотрел исходники coyote, программа тоже грубо говоря...

API для отправки подобных net send сообщений.
Говорят в VB есть замечательные API которые позволяют отправлять сообщения наподобе net send? Или какнибудь иначе сделать?

Создать файл send.php для отправки сообщения через mysqladmin
Мы заходим как авторизованные пользователи. Не знаю как написать файл отправки. У нас будет файл index.php, где авторизация. База данных...

10
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
07.02.2018, 06:26
Izual, какой размер файла? Может система принимает его в буфер и ей без разницы что вы пока решили данные не забирать

Добавлено через 8 минут
Пошлите ему скажем 2 ГБ без приёма вот тогда наверняка вернёт ошибку но ничего хорошего в этой ситуации ждать не приходится - буфер на обоих концах будет забит данными которые вам не нужны - легче клиенту послать на сервер сообщение "горшочек не вари" или разорвать подключение
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
07.02.2018, 13:56  [ТС]
Файл не большой. У меня размер буффера 1024 байт, поэтому файлы выбираю соответственно 4-40кб. (небольшие, чтоб за минуту - две файл скачался) Естественно, send / recv идут по циклу, и код контролирует сколько положить в буффер, в зависимости от остатка файла.
Нет система тут не причём, код сделан так, что если я нажму на клиенте кнопку отмены, то цикл recv на клиенте прервётся, из за изменения глобальной переменной. (после нажатия кнопки и получения команды "отмены" на клиенте - логер пишет что "ухожу в сон", ну и как я уже сказал sleep(xxx))

2 гб или 20 мегабайт, разницы нету. Я тестировал это поведение на 40 кб файле, если я нажимаю отмену где то в середине.
Ещё раз. Без отмены, пока клиент реально ждёт посылки файла - всё нормально, и если я ему не мешаю, то файл скачивается полностью.

Вопрос в том, почему send на сервере не возвращяет 0 или SOCKET_ERROR, ведь на клиенте recv прерывается. Коннект я не глушу, т.е. shutdown'a нет.

Цитата Сообщение от vxg Посмотреть сообщение
легче клиенту послать на сервер сообщение
Сервер не примет его, ведь у него текущяя задача - send file. Он не может выйти в recv состояние пока не вышлет весь файл, или пока send не вернёт значение отличное от размера посылаемого пакета (включая error).

У меня предположение, что локальная сеть во всём виной, т.е. поведение send и recv отличны в интернете и в локалке, хотя какое то бредовое предположение. Я честно говоря уже голову сломал с этим недоразумением.
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
07.02.2018, 21:16
Цитата Сообщение от Izual Посмотреть сообщение
У меня размер буффера 1024 байт
покажите код где это будет видно
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
07.02.2018, 21:32  [ТС]
Кусок серверной части (отдельный поток для каждого клиента)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
char fBuf[1024]=""; //выделяется при старте потока
while(1)
    {
        Sleep(5000);
        //проверка ошибок
        if(si[fCn].st % 2)
        {
            memset(fBuf, 0, _countof(fBuf));
            fSz = recv(sock, fBuf, 1024, 0);
            if(fSz < 1 || fSz > 1022)
            {
                if(fSz == 0)
                {
                    sprintf(fLbuf,"cPC[%ld] #ERROR# o.Recv ret=0.", fCn);
                    fErr[0]=-1;
                }
                else if(fSz == -1)
                {
                    sprintf(fLbuf,"cPC[%ld] #ERROR# o.Recv ret=SOCKET_ERROR.", fCn);
                    fErr[0]=-2;
                }
                else
                {
                    sprintf(fLbuf,"cPC[%ld] #ERROR# o.Recv OOR:ret=%ld.", fCn, fSz);
                    fErr[0]=-3;
                }
                LogMessage(fLbuf);
                continue;
            }
            sprintf(fLbuf,"cPC[%ld] RECV ret=%ld(b)", fCn, fSz);
            LogMessage(fLbuf);
            fBuf[fSz] = '\0';
            fErr[3]=fMessager(fCn, fBuf, fSz); // тут обработка
            if(fErr[3] != 1)
            {
                sprintf(fLbuf,"cPC[%ld] #ERROR# o.Recv.fMsg() ret=%ld cST=%ld nST=%ld.", fCn, fErr[3], fStc, si[fCn].st);
                LogMessage(fLbuf);
                fErr[0]=-4;
                break;
            }
            sprintf(fLbuf,"cPC[%ld] #OK# o.Recv ret=%ld(b) cST=%ld nST=%ld", fCn, fSz, fStc, si[fCn].st);
            LogMessage(fLbuf);
        }
        else // 2 4
        {
            fErr[3]=fMessager(fCn, fBuf, fSz);
            if(fErr[3] != 1)
            {
                sprintf(fLbuf,"cPC[%ld] #ERROR# o.Send.fMsg() ret=%ld cST=%ld nST=%ld.", fCn, fErr[3], fStc, si[fCn].st);
                LogMessage(fLbuf);
                fErr[0]=-10;
                break;
            }
            if(fSz < 1 || fSz > 1024)
            {
                sprintf(fLbuf,"cPC[%ld] #ERROR# o.Send OOR:(fsz)%ld.", fCn, fSz);
                LogMessage(fLbuf);
                fErr[0]=-11;
                break;
            }
            ret = send(sock, fBuf, fSz, 0);//sizeof(fBuf), 0);
            if(ret == SOCKET_ERROR)
            {
                sprintf(fLbuf,"cPC[%ld] #ERROR# o.Send ret=SOCKET_ERROR.", fCn);
                LogMessage(fLbuf);
                fErr[0]=-12;
                continue;
            }
            if(ret != fSz)
            {
                sprintf(fLbuf,"cPC[%ld] #ERROR# o.Send (ret)%ld != (fsz)%ld.", fCn, ret, fSz);
                LogMessage(fLbuf);
                fErr[0]=-13;
                break;
            }
            sprintf(fLbuf,"cPC[%ld] #OK# o.Send ret=%ld(b) cST=%ld nST=%ld", fCn, ret, fStc, si[fCn].st);
            LogMessage(fLbuf);
        }
    }
Ничего особенного...
Клиент:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Sleep(5000);
            fStc=m.st;
            if(m.st % 2)
            {
                fArr[0]=fMessager();
                if(fArr[0]!=1)
                {
                    sprintf(fLbuf,"#ERROR# o.Send.fMsg() ret=%ld cST=%ld nST=%ld", fArr[0], fStc, m.st);
                    LogMessage(fLbuf);
                    fErr[5]=-1;
                    continue;
                }
                if(fsz < 1 || fsz > 1023)
                {
                    sprintf(fLbuf,"#ERROR# o.Send.fMsg() sz=%ld cST=%ld", fsz, fStc);
                    LogMessage(fLbuf);
                    fErr[5]=-2;
                    continue;
                }
                ret = send(sClient, szBuf, fsz, 0);
                if(ret != fsz)
                {
                    if(ret == SOCKET_ERROR)
                    {
                        sprintf(fLbuf,"#ERROR# o.Send ret=SOCKET_ERROR cST=%ld", fsz, fStc);
                        fErr[5]=-3;
                    }
                    else
                    {
                        sprintf(fLbuf,"#ERROR# o.Send ret=%ld sz=%ld cST=%ld", ret, fsz, fStc);
                        fErr[5]=-4;
                    }
                    LogMessage(fLbuf);
                    continue;
                }
                sprintf(fLbuf,"o.Send cST=%ld nST=%ld", fStc, m.st);
                LogMessage(fLbuf);
                //-
            }
            else
            {
                memset(szBuf, 0, _countof(szBuf));
                fsz = recv(sClient, szBuf, 1024, 0);
                if(fsz < 1 || fsz > 1023)
                {
                    if(fsz == -1)
                    {
                        sprintf(fLbuf,"#ERROR# o.Recv ret=SOCKET_ERROR cST=%ld", fStc);
                        fErr[5]=-11;
                    }
                    else
                    {
                        sprintf(fLbuf,"#ERROR# o.Recv ret=%ld cST=%ld", fsz, fStc);
                        fErr[5]=-12;
                    }
                    LogMessage(fLbuf);
                    continue;
                }
                sprintf(fLbuf,"o.Recv ret=%ld(b)", fsz);
                LogMessage(fLbuf);
                szBuf[fsz] = '\0';
                fArr[0]=fMessager();
                if(fArr[0]!=1)
                {
                    sprintf(fLbuf,"#ERROR# o.Recv.fMsg() ret=%ld cST=%ld nST=%ld", fArr[0], fStc, m.st);
                    LogMessage(fLbuf);
                    fErr[5]=-13;
                    continue;
                }
                sprintf(fLbuf,"o.Recv cST=%ld nST=%ld", fStc, m.st);
                LogMessage(fLbuf);
                //-
            }
Так же в цикле.. буфер - глобальный, т.к. поток у клиента один (ну не считая оконные потоки для логера и т.п.)
C++
1
char szBuf[1024]="";
Как видиш, ничего сверхъестественного..
Думаю что код ничему не поможет.. В общем я попробую попозже сделать более простой клиент-серверный, и буду тестить, т.к. текущий проэкт очень большой.
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
08.02.2018, 07:37
Izual, как "видиш" код твоего "проэкта" однозначно говорит умеющим читать о том что ты путаешь понятия буфер системы и буфер в который ты попросил систему отсыпать из системного буфера немножко данных: по коду 1024 - это размер второго буфера, система буферизирует гораздо большие объёмы и то что ты не хочешь их забирать из системного буфера к себе не останавливает их поступление если вторая сторона бездумно продолжает их посылать - буферизация будет продолжаться пока не переполнятся буфера на обеих машинах - в начале буфер приёма на принимающей, следом начнёт заполнятся и переполнится буфер отправки на передающей. Как видишь ничего особенного...

Добавлено через 2 минуты

Не по теме:

Может рано ещё большой проект то заваливать?

0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
08.02.2018, 14:21  [ТС]
Мне кажется что ты троллиш.

Какой системный буффер?.. Файл подкачки?.. О чём ты?..

Цитата Сообщение от vxg Посмотреть сообщение
1024 - это размер второго буфера
Они оба 1024. И посылающий и принимающий.

Цитата Сообщение от vxg Посмотреть сообщение
система буферизирует гораздо большие объёмы
Силикон качает?..

Цитата Сообщение от vxg Посмотреть сообщение
не останавливает их поступление если вторая сторона бездумно продолжает их посылать
Ну да, а SOCKET_ERROR для чего?

Цитата Сообщение от vxg Посмотреть сообщение
Может рано ещё большой проект то заваливать?
Я сделал некоторые выводы про то кто ты и что ты пытаешся мне тут втюхать. Больше не пиши тут, мне твои комменты не нужны.
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
08.02.2018, 19:00
Izual, расширьте кругозор начав например отсюда https://stackoverflow.com/ques... so-recvbuf
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
08.02.2018, 21:14  [ТС]
Цитата Сообщение от vxg Посмотреть сообщение
начав например отсюда
Я конешно признателен за помощь. Но, есть большое "НО".
1. На форуме нельзя размещять ссылки на сторонние ресурсы. (в связи с этим у меня уже двоякое мнение лично о вас, а о правилах форума я промолчу вовсе, ибо нет смысла)
2. Даже в этом топике написано, что сокет будет выбрасывать ошибку. А у меня ошибку он не выбрасывает вовсе. Так что это всё совсем другая история, и не надо меня путать понятиями, которые может и полезны для ознакомления, но совершенно безполезны в конкретном вопросе.

Остаюсь с предположением, что это локальная сеть так работает криво, ибо я сталкивался и с другими непонятными явлениями, которых не было в локальном тесте, но были в интернет.
0
09.02.2018, 06:34

Не по теме:

Цитата Сообщение от Izual Посмотреть сообщение
1. На форуме нельзя размещять ссылки на сторонние ресурсы.
на другие форумы - нельзя.
на русский stackoverflow - нельзя.
на английский - можно.
почему так - не знаю, уточняйте у администрации самостоятельно.
плюс к этому: вы думаете, что модератор правил не знает что ли?

0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
09.02.2018, 08:45
Izual, про правила форума вам постом выше человек все доходчиво объяснил, а про буферы - читайте внимательнее что там написано: рассмотрим системный буфер приёма - в системе для каждого сокета резервируется системный буфер размер которого можно узнать / изменить при помощи вызовов get / setsockopt - в этот системный буфер данные поступают прямо от адаптера даже когда вы не вызываете recv, вызов recv забирает данные из этого системного буфера и помещает их в указанную вами область памяти в количестве меньшом либо равным указанному вами. По вашему коду нигде не устанавливаются размеры системных буферов (нет вызовов setsockopt) поэтому логично предположить что они имеют значения по умолчанию которые зависят от ОС и в данном случае оказались достаточными для размещения всех данных которые не захотел принимать ваш клиент без того чтобы спровоцировать ошибку передачи на сервере
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
09.02.2018, 08:45
Помогаю со студенческими работами здесь

Socket.Send + Async & Await: свой асинхронный метод отправки данных
Привет. Хочу написать свой асинх. метод для отправки данных при помощи класса Socket и его метода Send. Работать должно так. Есть некий...

Считать переменную без отправки запроса.
в общем такое дело:) я тут замутил одну форму, но чтобы не перегружать браузер постоянно создал в vbscript переменную, а потом в куске...

Обработка запроса без обратной отправки
Проблема состоит в том что: 1.Есть БД 2.Есть лист бокс куда вводятся данные 3.По нажатию ЕНТЕРА происходит поиск введеного значения...

Повторная отправки формы, без редиректа!
Как мне запретить повторную отправку формы? Редирект мне не подходит, action на этой же странице Вот как я делал, но это не верно... В...

Значение текстового поля без отправки данных и js
Здравствуйте. У меня есть вот такой код: $count = 1; echo &quot; &lt;input type='text' name='count' value='&quot;.$count.&quot;'&gt;; если я введу...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
1С: Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере документа выдачи шин для спецтехники с табличной частью. Данные берутся из регистра сведений, по которому настроено. . .
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru