Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 17.07.2012
Сообщений: 12
1

Почему при попытке организовать условное завершение нити (по итератору, или по времени), всё виснет?

03.02.2013, 21:54. Показов 902. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Это UDP-сервер. Главная нить в это время висит на приёме консольных команд, нить-приёмник- на приеме команд ото всех, устанавливает флаг msg для сообщения по списку подключенных адресов. Почему при попытке организовать условное завершение нити (по итератору, или по времени), всё виснет? Вернее, если верить отладчику, оно не виснет, корректно отрабатывает printf и т.д,, НО - в выводе этого нет.

Ну что, товарищи, где я наложала в этот раз, м? )

Здесь приведены нить-общий приёмник, и нить-индивидуальный передатчик.

I need help! Очень.

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#include "Allincludes.h"
 
sockaddr_in clients[10];
int onsrv[10];
int msg[10];
 
 
struct my_struct
{
    int socket;
    int num;
};
 
 
 
// Поток приёма
 
void* RecvThread(void* pMyData)
{
    
    // Получение серверного сокета от главного потока
    
    int ServerSock=*(int*)pMyData;
    
    
    // Заполнение по умолчанию адресов всех клиентов
    // для адресов заполняется только семейство адресов
    // также заполняется переменная onsrv[] - 1 - для клиента с адресом есть сессия
    // 0 -нет
    // msg - флаг, выставляющийся при принятом сообщении
    
    for (int i=0;i<10;i++)
    {
        clients[i].sin_family=AF_INET;
        onsrv[i]=0;
        msg[i]=0;
    }
    
    int stop=0; // флаг для ответа об остановке клиентам, не влезающих в список адресов возврата
    
    while(1)
    {
     
        char recvbuf[100]={0};
        char mybuf[100]={0};
        
        sockaddr_in common_clnt_addr;
        common_clnt_addr.sin_family=AF_INET;
        
        
        // Получаем данные и определяем адрес возврата
        
        unsigned int len=sizeof(common_clnt_addr);
        int recved=recvfrom(ServerSock,recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&common_clnt_addr,&len);
        
        if(recved<0) perror("Recved error");
        else
            printf("Received data=%s",recvbuf);
     
        
        // Ищем по списку совпадения адреса возврата
        int num_searched=-1;
        
        for (int i=0;i<10;i++)
        {
            // Анализ порта на совпадение
           if (clients[i].sin_port==common_clnt_addr.sin_port)
           {
               // Порт совпал, анализируем IP
               if(clients[i].sin_addr.s_addr==common_clnt_addr.sin_addr.s_addr)
               {
                   // Проверяем подключенность адреса возврата
                   if(onsrv[i]==1)
                   {
                       // Если адрес полностью совпал, и он подключен, возвращаем номер подключения
                       num_searched=i;
                       break;
                   }
               }
           }
        };
        
        int add=0;
        
        // Если есть подключение, пишем его номер
        
        if (num_searched!=-1)
        {
            printf("Received data from %d.\n",num_searched);
        }
        else
        { 
            // Если подключения нет, то ищем номер первого неподключенного адреса, и подключаем наш
            
            for (int i=0;i<10;i++)
            {
                if(onsrv[i]!=1)
                {
                    num_searched=i;
                    break;
                }
            };
            
            // Если не нашли пустого, индицируем сигнал "список адресов возврата полон"
            
            if (num_searched==-1)
            {
                printf("List of adressess is full.\n");
                stop=1; // клиенту должно быть послано сообщение об остановке
                
            }
            else
            {
                // иначе добавляем адрес возврата в список на первое неподсоединненое место
                
                clients[num_searched]=common_clnt_addr;
                onsrv[num_searched]=1;
                
                // и индицирцем добавление
                
                printf("Client №%d added to list.\n",num_searched);
                add=1; // флаг первичного добавления в список
            }
            
        };
        
        
        // Отправляем данные тому же клиенту:
        // Если stop==1, формируем клиенту посылку об остановке, он лишний
        
        if (stop==1)
        {
            strncpy(mybuf,"stop",sizeof(mybuf));
            int sended=sendto(ServerSock,mybuf,sizeof(mybuf),0,(sockaddr *)&common_clnt_addr,sizeof(common_clnt_addr));
        
            if(sended<0) perror("Sended error");
            else
                printf("Sended data=%s.\n",mybuf);
            
            // после отправления сообщения об отключении
            // идём в начало цикла
            
            continue;
           
         
        };
        
        
        
        // Иначе - клиент либо вновь подключен (add=1), либо был подключенным(add=0), его идентификатор подключения - номер num_searched
        // В таком случае - клиенту пришло новое сообщение
        // Если он вновь подключен - создаем новый поток и устанавливаем флаг
        // Если был - устанавливаем флаг[num_searched]=1 
        
        msg[num_searched]=1;
        
        if (add==1)
        {
            // Добавляем новый поток для обработки принятых сообщений от квази-подключенного сокета 
            // и посылки на них ответа
            
             pthread_t Sender;
             
             // структура для передачи серверного сокета и идентификатора подключения-номера в списках
             
             my_struct param;
             param.num=num_searched;
             param.socket=ServerSock;
             
             pthread_create(&Sender,NULL,SendThread,&param);
        }
        
        
    };   
}
 
 
// Поток передачи
 
void* SendThread(void* pMyData)
{
    
    // Восстанавливаем серверный сокет и идентификатор подключения - номер клиента в списках
    
    my_struct param;
    
    param=*(my_struct*)pMyData;
    
    
    int ServerSock=param.socket;
    int clnt=param.num;
    
    
    while(1)
    {
        
        // Вместо поллинга организуем таймаут
        
        time_t t1;
        time(&t1);
        
        // Ждём в поллинге появления флага прихода сообщения msg[clnt]
        // и выводим разницу во времени между началом ожидания и текущим временем
        
        while(!msg[clnt])
        {
            time_t t2;
            time(&t2);
            
            printf("delta-t=%d.\n",t2-t1);
            
            // Время таймаута:
            if (t2-t1==5)
            {
                printf("-------------------Timeout----------------------");
                
                //очищение идентификатора подключения, позиция в списке адресов не требует очищения
                
                onsrv[clnt]=0;
                
                //выход с сервера
                pthread_exit(0);
                
            };
        };
        
        // Получено сообщение, необходимо ответить
        
        char mybuf[100]={0};
        
        sprintf(mybuf,"Server to %d",clnt); // Сервер отправляет клиенту посылку с номером его идентификации на сервере
        
        int sended=sendto(ServerSock,mybuf,sizeof(mybuf),0,(sockaddr *)&clients[clnt],sizeof(clients[clnt]));
        
        if(sended<0) perror("Sended error");
        else
            printf("Sended data=%s.\n",mybuf);
        
        // После ответа освобождаем флаг сообщения для данного клиента
        
        msg[clnt]=0;
    }
    
    
}
Добавлено через 4 минуты
Причём без pthread_exit или break, или return в ветке условного сравнения всё работает корректно.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.02.2013, 21:54
Ответы с готовыми решениями:

C DVD или флешки ноутбук загружается нормально, но при попытке поставить любую систему на винт виснет
Здравствуйте.Проблема с запуском ноута с HDD. C DVD или флешки грузится нормально но при попытке...

Почему не могу кинуть файлик по Blue Tooth? Всё обнаруживает. Но при попытке передачи пишет "Адрес несовместим с выбранным протоколом."
Почему не могу кинуть файлик по Blue Tooth? Всё обнаруживает. Но при попытке передачи пишет...

ПК виснет при попытке запустить IE
Добрый день! Проблемма вот в чем. Есть ПК (ХР SP2) на котором установленны контур, банк клиент...

Виснет при попытке чтения
Здравствуйте. HDD 2,5&quot; 500гб вытащил из старого ноута и сделал из него внешний. Собственно...

4
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
04.02.2013, 10:10 2
\n в printf("---timeout---");
ЗЫ: send-нити у Вас текут в таком виде, да и вообще прок от них тут вряд ли есть (скорости не добавят (тем более с такой реализацией таймаута, логику усложняют).
0
0 / 0 / 0
Регистрация: 17.07.2012
Сообщений: 12
12.02.2013, 15:36  [ТС] 3
g_u_e_s_t, а можно какую-нибудь статью/ещё что-то на тему "нити текут"? Пожалуйста) Если это про память, то я не вполне понимаю, о чём здесь речь... И в чём трабл с printf? Это просто особенности форматирования, нет?
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
12.02.2013, 17:52 4
Цитата Сообщение от Rye_eyes Посмотреть сообщение
а можно какую-нибудь статью/ещё что-то на тему "нити текут"? Пожалуйста) Если это про память, то я не вполне понимаю, о чём здесь речь...
Да, про память. Простое правило: на любую нить в обязательном порядке делать либо join, либо detach. Статью погуглите сами
Цитата Сообщение от Rye_eyes Посмотреть сообщение
И в чём трабл с printf?
\n кроме форматирования сбрасывает все накопленное в stdio буфере связанном с соответсвующим потоком вывода.
0
0 / 0 / 0
Регистрация: 17.07.2012
Сообщений: 12
12.02.2013, 20:36  [ТС] 5
g_u_e_s_t, большое человеческое спасибо).
0
12.02.2013, 20:36
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.02.2013, 20:36
Помогаю со студенческими работами здесь

При попытке переустановки windows при подключении дисковода виснет комп
слетела виндовс, при попытке переустановить получается что,при подключении дисковода виснет комп...

AsRock 890fx deluxe4, биос постоянно виснет при попытке сохранить изменения и при загрузке.
Здравствуйте. Вчера купил мп AsRock 890fx deluxe4, биос постоянно виснет при попытке сохранить...

Виснет при попытке войти в безопасный режим
Windows 10 виснет на заставке, при попытке войти в безопасный режим. Пробовал накатывать...

iis5.1 (XP) при обращении к FileSystemObject всё виснет. Идеи?
скрипт выглядит так: strPhysPath = Server.MapPath(&quot;file.txt&quot;) Set MyFileObj =...


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

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