我正在构建一个应用程序,我在其中接收套接字数据。我需要在几秒钟后回复这些收到的数据(比如说8秒后)。所以我想知道有没有办法安排一个事件,它会在8秒后自动发送套接字数据。我不喜欢在接收线程或任何其他线程中不必要地睡8秒。这是我到目前为止所写的用于接收pthread的套接字数据。
long DataSock_fd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
StSocketAddress.sin_family=AF_INET; //address family
StSocketAddress.sin_addr.s_addr=inet_addr("10.10.10.10"); //load ip address
StSocketAddress.sin_port=htons(1234); //load port number
//bind the above socket to the above mentioned address, if result is less than 0(error in binding)
if(bind(DataSock_fd,(struct sockaddr *)&StSocketAddress,sizeof(StSocketAddress))<0)
{
close(DataSock_fd); //close the socket
perror("error while binding\n");
exit(EXIT_FAILURE); //exit the program
}
char Buff[1024];
long lSize = recvfrom(DataSock_fd,(char *)Buff,sizeof(Buff),0,NULL,NULL);
但我坚持安排一个在8秒后发送数据的事件。
答案 0 :(得分:1)
看看这个SO answer。
您可以像这样使用<async>
来解决您的问题:
auto f = std::async(std::launch::async, [] {
std::this_thread::sleep_for(std::chrono::seconds(5));
printf("(5 seconds later) Hello");
});
答案 1 :(得分:0)
你可以使用boost :: sleep,或chrono :: sleep_for或chrono :: sleep_until, 但是如果你不想打电话给睡眠,我最好的建议是使用std :: mutex并锁定从Time.currenttime -startTime == 8接收信息的线程。
答案 2 :(得分:0)
<强>方法-1 强>
由于您没有启用C++11
编译器,并假设您没有使用Qt / boost等框架。请检查以下代码是否回答了您的问题。它是使用pthreads
示例代码:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#define TIME_TO_WAIT_FOR_SEND_SECS (8)
#define FAIL_STATUS_CODE (-1)
#define SUCCESS_STATUS_CODE (0)
typedef void (*TimerThreadCbk)(void *);
typedef struct tTimerThreadInitParams
{
int m_DurationSecs; /* Duration of the timer */
TimerThreadCbk m_Callback; /* Timer callback */
void * m_pAppData; /* App data */
}tTimerThreadInitParams;
void PrintCurrTime()
{
time_t timer;
char buffer[26];
struct tm* tm_info;
time(&timer);
tm_info = localtime(&timer);
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
puts(buffer);
}
void* TimerThreadEntry(void *a_pTimerThreadInitParams)
{
tTimerThreadInitParams *pTimerThreadInitParams = (tTimerThreadInitParams *)a_pTimerThreadInitParams;
if(NULL != pTimerThreadInitParams)
{
/*Do validattion of init params */
sleep(pTimerThreadInitParams->m_DurationSecs);
pTimerThreadInitParams->m_Callback(pTimerThreadInitParams->m_pAppData);
}
else
{
printf("pTimerThreadInitParams is (nil)\n");
}
}
TimerCallbackForSend(void *a_pAppData)
{
(void)a_pAppData;
/* Perform action on timer expiry using a_pAppData */
printf("TimerCallbackForSend trigggered at: ");
PrintCurrTime();
}
int main()
{
/* Timer thread initialization parameters */
pthread_t TimerThread;
tTimerThreadInitParams TimerInitParams = {};
TimerInitParams.m_DurationSecs = TIME_TO_WAIT_FOR_SEND_SECS;
TimerInitParams.m_Callback = (TimerThreadCbk) TimerCallbackForSend;
/* Print current time */
printf("Starting timer at:");
PrintCurrTime();
/* Create timer thread*/
if(pthread_create(&TimerThread, NULL, TimerThreadEntry, &TimerInitParams))
{
fprintf(stderr, "Error creating thread\n");
return FAIL_STATUS_CODE;
}
else
{
printf("TimerThread created\n");
}
/* wait for the second thread to finish */
if(pthread_join(TimerThread, NULL))
{
fprintf(stderr, "Error joining thread\n");
return FAIL_STATUS_CODE;
}
else
{
printf("TimerThread finished\n");
}
return SUCCESS_STATUS_CODE;
}
示例输出:
Starting timer at:2017-08-08 20:55:33
TimerThread created
TimerCallbackForSend trigggered at: 2017-08-08 20:55:41
TimerThread finished
备注:强>
这是一个临时自定义实现。您可以将main重命名为ScheduleTimer
,这将是一个通用API,它会生成一个线程并在其自己的上下文中调用已注册的回调。
刚才看到你不想在任何一个线程中睡觉。
<强>方法-2 强>
请参阅C: SIGALRM - alarm to display message every second以获取SIGALRM。可以在信号处理程序中,您可以将事件发布到您的线程将监视的队列
答案 3 :(得分:0)
无论是通过C ++包装还是通过系统的nanosleep
函数进行休眠 - 它都不能说得足够 - 是错误的。除非精确性和可靠性根本不重要,否则不要睡觉。从来没有。
对于与计时相关的任何事情,请使用计时器。
如果可移植性不是高优先级,并且由于问题被标记为&#34; Linux&#34;,timerfd将是最好的解决方案之一。
在等待接收某些内容时,可以使用select
/ poll
/ epoll
等待timerfd,同时等待其他内容(信号,事件)。这非常优雅,也非常高效。
承认,既然您正在使用UDP,那么首先不要等待准备就绪,而是要recvfrom
阻止。然而,等待准备就没有什么本质上的错误。对于中等负载,额外的系统调用并不重要,但对于超高负载,您甚至可以考虑进一步进入非便携式土地并使用recvmmsg
一次性接收多个数据报,如图所示按epoll报告的数据报数量(请参阅recvmmsg
手册页上的代码示例,其中recvmmsg
与epoll_wait
合并。)
使用eventfd,您可以在一个单个线程中将所有内容放在一个单一的事件循环中,可靠且高效。不需要任何技巧,不需要太聪明,不用担心并发问题。