Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
25 / 26 / 16
Регистрация: 27.09.2015
Сообщений: 110
1

Функции puts(), send(), recv() и какая-то дичь

13.10.2016, 18:11. Показов 2144. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем здравствовать!
Столкнулся с невероятно непонятной мне вещью и просто уже не могу... не могу разобраться.
Написал я значится морской бой, и все работает, сделал игру против игрока по сети, и все работает, но до того момента как кто-то победил. Задумка была такая, когда кто-то побеждает, то строкой формируется поле победившего игрока и отправляется проигравшему игроку, чтобы тот знал, где корабли его противника, по которым он не попал. Вот как это выглядит в коде.

Со стороны клиента
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
recv(player, buffer_For_RECV, sizeof(buffer_For_RECV), 0); //принимаем или маркер победы, или поле победившего игрока
    if (!strcmp(WIN, buffer_For_RECV)) {
        puts("");
        char *string = (char *)calloc((SIZE_OF_STRING), sizeof(char));//выделяется память под строку
        if (NULL == string) memory_Allocation_Error();
        show_Your_Ships(Our_Area, Size_Of_Area, string);//в нее записывается поле победившего игрока
        puts(string);//проверка, а выведеться ли строка у пользователя (не выводиться, но на сервере - выводиться!)
        send(player, string, (sizeof(char) * SIZE_OF_STRING), MSG_DONTROUTE);//отправляем поле на сервер
        free(string);// освобождаем память для строки
        system("cls");
        print_Areas(Our_Area, Another_Area, Size_Of_Area, 0);
        beauty_Output("\a\aYou killed enemy ship! YEAHHHH!\n\n");
        beauty_Output("\a\aCongratulations? you won this game!!!!");
        puts("");
    }
    else {
        puts("");
        beauty_Output("\a\aSorry, you lost!\n\n");
        puts(buffer_For_RECV); //выводим строку содержащую поле победившего игрока(не выводиться, чтоб её)
        beauty_Output("\a\aLook the location of the enemy ships\n\n");
    }
Со стороны сервера
C
1
2
3
4
5
6
7
8
9
10
11
12
13
if (amount_Of_Ships_Of_Player1 != 0) {
        send(player1, WIN, (strlen(WIN) + 1), MSG_DONTROUTE);//отправляем игроку маркер победы
        recv(player1, buffer_For_RECV, sizeof(buffer_For_RECV), 0);//ждем от него его поле
        puts(buffer_For_RECV);//выводим поле ради проверки на сервере (выводиться, зараза!)
        send(player2, buffer_For_RECV, (strlen(buffer_For_RECV) + 1), MSG_DONTROUTE);//переправляем поле проигравшему игроку
        puts("Player1 won!\a");
    }
    else {
        send(player2, WIN, (strlen(WIN) + 1), MSG_DONTROUTE);
        recv(player2, buffer_For_RECV, sizeof(buffer_For_RECV), 0);
        send(player1, buffer_For_RECV, (strlen(buffer_For_RECV) + 1), MSG_DONTROUTE);
        puts("Player2 won!\a");
    }
В чем дело, не пойму, если прогоняю через дебагер, то вообще магия. В зависимости от того, что в дебагере(сервер, игрок1, игрок2) совершенно разный результат. Может кто-то понимает, что это за ерунда, вся игра протекает нормально, все отправляется и принимается, и только здесь не пойму что происходит... То ли в puts() проблема, то ли в send(). В принципе игра по сети готова, осталось вот этот стришок доделать, и все, он как бы не обязателен, но очень хочу его добавить, помогите пожалуйста.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.10.2016, 18:11
Ответы с готовыми решениями:

Сокеты: после вызова send программа зависает на функции recv
Извеняюсь за такое назание темы, но уже перепробовал 100 вариантов и постоянно выкидывает данное...

send(.);recv(.);
Привет всем. Хроника событий: В сети имеются компьютеры a-сервер,b-клиент. 1. они соединяются...

send/recv
Всем доброго времени суток. При написании простейшей клиент-серверной программы с возможностью...

Сокеты, send(), recv()
задача- пользователь ввел количество структур. заполнил их. Агенты-Клиенты работают просто так, в...

9
25 / 26 / 16
Регистрация: 27.09.2015
Сообщений: 110
13.10.2016, 18:17  [ТС] 2
Вот результат работы, может поможет.
Миниатюры
Функции puts(), send(), recv() и какая-то дичь  
0
25 / 26 / 16
Регистрация: 27.09.2015
Сообщений: 110
13.10.2016, 18:41  [ТС] 3
А вот еще и странности при дебагинге.
Здесь ситуация такая, игрок который победит - не в дебаге, а сервер и игрок, который проиграет - в дебаге. Когда игрок побеждает, то если быстро пронажимать F10, то мы словим от победившего игрока его поле и выведем как на сервере, так и у проигравшего игрока.
Миниатюры
Функции puts(), send(), recv() и какая-то дичь   Функции puts(), send(), recv() и какая-то дичь  
0
25 / 26 / 16
Регистрация: 27.09.2015
Сообщений: 110
13.10.2016, 18:48  [ТС] 4
Далле, если мы также дебажим, но чуть задержимся и дадим выполниться программе победившего игрока, то мы вообще ничего не получим, у на останется старая метка в буфере. Это в принципе кажется логичным, но не объясняет, почему у победившего игрока в puts() не выводиться сформированное строкой поле.
Миниатюры
Функции puts(), send(), recv() и какая-то дичь   Функции puts(), send(), recv() и какая-то дичь  
0
25 / 26 / 16
Регистрация: 27.09.2015
Сообщений: 110
13.10.2016, 18:53  [ТС] 5
Ну и наконец, если все проходит через процесс, когда дебажится игрок, который победит, то все puts() работают, везде все выводиться и все до всего доходит.

Подводя все вышесказанное, я думал, что проблема в том, что победивший игрок заканчивает работу, до того, как сервер получит от него сообщение и данные теряются, но я ставил цикл, и должен был получить и переправить данные проигравшему игроку, проигравший игрок заканчивал работу раньше победившего, но все-равно ничего не выводилось. В любом случае у игрока, который победил, puts() все-равно не выводит строку (а в режиме дебагинага - выводит). И в чем проблема - не понятно.
Миниатюры
Функции puts(), send(), recv() и какая-то дичь  
0
25 / 26 / 16
Регистрация: 27.09.2015
Сообщений: 110
13.10.2016, 23:37  [ТС] 6
Так, после пяти часов разбирательств вот что выяснилось.

C
1
2
3
4
        send(player2, WIN, (strlen(WIN) + 1), MSG_DONTROUTE);
        recv(player2, buffer_For_RECV, sizeof(buffer_For_RECV), 0);
        send(player1, buffer_For_RECV, (strlen(buffer_For_RECV) + 1), MSG_DONTROUTE);
        puts("Player2 won!\a");
Проблема в строке 3

C
1
send(player1, buffer_For_RECV, (strlen(buffer_For_RECV) + 1), MSG_DONTROUTE);
она вроде бы отправляет сообщение, но принимающая функция, почему-то не принимает, это сообщение

C
1
recv(player, buffer_For_RECV, sizeof(buffer_For_RECV), 0);//функция у клиента
При этом, если я поставлю точку останова на строке 1, а затем ее запущу, то все нормально отработает, клиент получит строку и выведет ее. Но если перед строкой 3 не будет точки останова, то клиент ничего не примет/не запишет. Я понимаю, что это возможно глупо, но это так. И это я говорил про режим дебагинга, когда просто запускаешь как приложение, то ничего не выводиться.
0
shvyrevvg
14.10.2016, 08:11
  #7

Не по теме:

Цитата Сообщение от Pavel Kisliuk Посмотреть сообщение
C
1
send(player2, buffer_For_RECV, (strlen(buffer_For_RECV) + 1), MSG_DONTROUTE);
Чисто из любопытства, почему strlen() вместо sizeof()?:)

0
153 / 148 / 66
Регистрация: 20.02.2014
Сообщений: 556
14.10.2016, 10:50 8
Pavel Kisliuk, честно говоря, не сильно вдавался в проблему, но похоже на то, что у тебя получается лок на каком-то из сокетов на сервере. То есть в текущий момент сервер общается с игроком №1 и ждет, например, от него recv(), а в это время ему делает send() игрок №2 и сам потом от него ждет recv(). Так как сокеты у тебя блокирующие, то они и весят в своего рода дедлоке. Попробуй на сервер либо юзать select(), либо неблокирующие сокеты FIONBIO. А в дебаг режиме работает, скорее всего потому, что успевает выполнить правильный порядок send()/recv() между сервером и игроками.
1
25 / 26 / 16
Регистрация: 27.09.2015
Сообщений: 110
14.10.2016, 12:36  [ТС] 9
shvyrevvg, ну, как ни странно, но у меня в коде buffer_For_RECV объявляется так:
C
1
char buffer_For_RECV[SIZE_OF_STRING] = { 0 };
но, если бы, оно было объявлено так
C
1
char *buffer_For_RECV = (char *)calloc(SIZE_OF_STRING, sizeof(char));
то возвращался бы размер указателя, а не строки.
Но, на самом деле я просто сделал так, вообще не задумываясь, как лучше, единственное, что подумал, что мне нужен размер строки, а не размер самого массива.

Добавлено через 18 минут
Вованя, блин, вообще уже ничего не понимаю =) Вставил цикл перед отработкой send, чтобы сделать задержку небольшую, и все работает нормально!
0
1786 / 1036 / 445
Регистрация: 12.05.2016
Сообщений: 2,550
14.10.2016, 12:41 10
Pavel Kisliuk, можете весь код выложить? Попробуйте задержки ставить после вывода на сервере в if и else, посмотреть что будет
0
14.10.2016, 12:41
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.10.2016, 12:41
Помогаю со студенческими работами здесь

SOCKET: send(), recv()
Начал разбираться с сокетами и в самом начале застрял на элементарном, с функциями send и recv, в...

send, recv и close
Что будет, если сервер пошлет данные на accept сокет и сразу же закроет этот сокет? Сможет ли...

Delphi и Winapi: Send и Recv
Здравствуйте, появилась такая проблема не могу разобраться с использованием функций Send и Recv в...

recv() и send() странное поведение
Проблема в двух словах такая, программа сервер принимает сообщение от клиента обрабатывает и...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru