Я использую pthread + ACE для написания поддельного клиента.
этот клиент имеет 3 потока, и каждый поток может бесконечно отправлять и получать сообщения, используя ACE. однако эти потоки всегда останавливаются функцией send () или recv (). то есть поток завершит работу, если что-то будет не так с отправкой или получением, к сожалению, я не знаю, в чем заключается ошибка, и я тоже не смог ее перехватить. коды:
struct thread_data {
int thread_id;
string ip;
uint32_t port;
uint32_t timeout;
};
std::vector<struct thread_data> m_thread;
void * test_fun1(void * threadid)
{
struct thread_data * tmp_thread_data = (struct thread_data *)threadid;
long tmp_threadid = (long)tmp_thread_data->thread_id;
string tmp_ip = tmp_thread_data->ip;
uint32_t tmp_port = tmp_thread_data->port;
uint32_t tmp_timeout = tmp_thread_data->timeout;
ACE_INET_Addr addr(tmp_port, tmp_ip.c_str());
ACE_Time_Value timeout(0, tmp_timeout * 1000);
ACE_SOCK_Connector connector;
ACE_SOCK_Stream peer;
// connect
if(connector.connect(peer, addr, &timeout) != 0)
pthread_exit((void *) threadid);
// send msg
while (1)
{
ssize_t tmp_ret1 = peer.send("hello world", 12);
if (tmp_ret1 <= 0)
continue;
char tmp_buf[1024] = '\0';
ssize_t tmp_ret2 = peer.recv(tmp_buf, 1024, &timeout);
if (tmp_ret2 <= 0)
continue;
else
fprintf(stderr, "recv:%s\n", tmp_buf);
}
// close
peer.close();
pthread_exit((void *) threadid);
}
int main(int argc, char *argv[])
{
std::vector<pthread_t> threads;
pthread_attr_t attr;
int rc;
int i = 0;
void * status;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// thread create
int tmp_num = 3;
for(i = 0; i < tmp_num; i++)
{
pthread_t tmp_thread_handler;
struct thread_data tmp_thread_info;
tmp_thread_info.thread_id = i;
tmp_thread_info.ip = "127.0.0.1";
tmp_thread_info.port = 8001;
tmp_thread_info.timeout = 100;
rc = pthread_create(&tmp_thread_handler, NULL, test_fun1, (void *)&tmp_thread_info);
if (rc != 0)
return -1;
threads.push_back(tmp_thread_handler);
m_thread.push_back(tmp_thread_info);
}
// thread start
pthread_attr_destroy(&attr);
for(i = 0; i < tmp_num; i++)
{
rc = pthread_join(threads[i], &status);
if (rc != 0)
return -1;
}
pthread_exit(NULL);
return 0;
}
что мне делать, если я хочу бесконечно отправлять и получать сообщения? любая помощь будет оценена!
В этом коде вы столкнулись со значительной проблемой времени жизни области действия. Вы отправляете блок данных в ваши потоки, который создается / уничтожается при каждой итерации цикла. Оставляя в стороне:
// thread create
int tmp_num = 3;
for(i = 0; i < tmp_num; i++)
{
pthread_t tmp_thread_handler;
struct thread_data tmp_thread_info;
// --- snip ----
rc = pthread_create(&tmp_thread_handler, NULL, test_fun1, (void *)&tmp_thread_info);
// --- snip ----
}
Копируется ли полученный блок в базовые информационные векторы или нет, не имеет значения. Как только петля смещается, объект уничтожается, и вместе с ним std::string
переменная-член ip
, Это может находиться в том же пространстве памяти (структура), но перераспределение строки почти наверняка будет не. Другими словами, вы вызываете неопределенное поведение.
Возможное решение этой проблемы — использовать интеллектуальный указатель для структуры, передавая ее get()
член в потоке, и вставка того же умного указателя в ваш информационный вектор (перенастроенный для умных указателей). Я лично предпочитаю более простой подход, а именно выделение обоих векторов до потоки запускаются, тем самым исправляя свои «внутренние возможности» для использования по адресу. Оттуда вы можете отправить адрес структуры, поскольку вектор содержит его для вас:
// thread create
size_t tmp_num = 3;
m_thread.resize(tmp_num);
threads.resize(tmp_num);
for(size_t i = 0; i < tmp_num; i++)
{
m_thread[i].thread_id = i;
m_thread[i].ip = "127.0.0.1";
m_thread[i].port = 8001;
m_thread[i].timeout = 100;
rc = pthread_create(&threads[i], NULL, test_fun1, &m_thread[i]);
if (rc != 0)
return -1;
}
Что касается других проблем, в вашей ветке proc это не компилируется:
char tmp_buf[1024] = '\0';
Но это довольно незначительно по сравнению с вашим неопределенным поведением.
Других решений пока нет …