C++如何设置时间间隔
程序代码:看主函数中的while即可#include const int TIME=5;
void main()
{
cout<<"请等待5秒钟~!"<<endl;
clock_t now = clock(); //开始计时
while((clock() - now) / CLOCKS_PER_SEC < TIME);//等待5秒种的时间
cout<<"时间到,执行下一步..."<<endl;
}结果:自己执行的看一下~!
请教关于connect函数不退出/阻塞的问题
1.采用select
在学习嵌入式Linux网络编程中,很多同学都发现了一个问题,那就是调用connect函数时,如果服务端关闭,客户 端调用connect()函数时,发现阻塞在那里,而且利用ctrl+c信号去停止客户端程序时,需要等待一个较为长的时间才能响应了,这个时间如果大家 细心会发现,每次都是75秒的时间。那么有没有什么比较好的办法,可以以用户能接受的一个时间响应来停止掉一个正在connect连接的客户端那?比如我 们在做一个网络控制台的程序,用户需要随时可以停止掉任何一个网络服务连接,那么对于这样一个需要等待75秒时间才能反馈出服务状态的程序,用户是无法接 受的。
对于如何解决这个问题,我们可以分析下,要想完成用户在一个能接受的时间里迅速反馈出服务 端已经关闭的状态,那么我们的程序应该做到在一个规定的时间片内,可以捕获到用户发出的控制状态,然后处理用户的需求。那么要做到可以在规定的时间片内捕 获用户的控制状态,就必须禁止让我们的connect()函数阻塞75秒的情况发生,也就是说,要让connect()函数变为非阻塞状态才行。
好了,现在解决问题的关键就是如何把connect变为非阻塞状态了,我们知道,socket编程的操作对象是socket,而socket他又属于系统描述符类型,那么对于系统描述符,我们是怎么操作他变为非阻塞的那?是利用fcntl()函数或者ioctl()函数。
想到这里,好像问题应该已经解决了,但是我们调试发现,在服务端出现错误的时候,connect确实马上返回,但是,如果服务端正确那,connect还是马上返回,这样,我们无法判断connect函数是否成功了,那这个问题又该如何解决呢?
我们是否想到了一个select函数那,他具备监听文件描述符的功能,如果我们把之前的socket让select监听他是否可写,是不是问题也就解决了。
好了,那么我们总结下整个思路:
1.建立socket
2.将该socket设置为非阻塞模式
3.调用connect()
4.使用select()检查该socket描述符是否可写
5.根据select()返回的结果判断connect()结果
6.将socket设置为阻塞模式
对于第六步,为什么还要设置为阻塞模式那,留给我们同学自己思考下。
那么根据上面的6个步骤,我们写一个简单的模块程序来调试看下:
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) exit(1);
struct sockaddr_in serv_addr;
………//以服务器地址填充结构serv_addr
int error=-1, len;
len = sizeof(int);
timeval tm;
fd_set set;
unsigned long ul = 1;
ioctl(sockfd, FIONBIO, &ul); //设置为非阻塞模式
bool ret = false;
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
{
tm.tv_set = TIME_OUT_TIME;
tm.tv_uset = 0;
FD_ZERO(&set);
FD_SET(sockfd, &set);
if( select(sockfd+1, NULL, &set, NULL, &tm) > 0)
{
getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
if(error == 0) ret = true;
else ret = false;
} else ret = false;
}
else ret = true;
ul = 0;
ioctl(sockfd, FIONBIO, &ul); //设置为阻塞模式
//下面还可以进行发包收包操作
……………
}
2.方法二、定义信号处理函数:
sigset(SIGALRM, u_alarm_handler);
alarm(2);
code = connect(socket_fd, (struct sockaddr*)&socket_st, sizeof(struct sockaddr_in));
alarm(0);
sigrelse(SIGALRM);
首先定义一个中断信号处理函数u_alarm_handler,用于超时后的报警处理,然后定义一个2秒的定时器,执行connect,当系统 connect成功,则系统正常执行下去;如果connect不成功阻塞在这里,则超过定义的2秒后,系统会产生一个信号,触发执行 u_alarm_handler函数, 当执行完u_alarm_handler后,程序将继续从connect的下面一行执行下去。
其中,处理函数可以如下定义,也可以加入更多的错误处理。
void u_alarm_handler()
{
}
C++ Socket如何设置Accept和Recv的非阻塞
void* CTCPClient::AUReceive(void *aInstance){struct timeval tv_out;CTCPClient *pInstance = (CTCPClient *)aInstance;fd_set sockfd;pInstance->m_IsExit = false;char ReceiveDataInfo[1024]={0}; char Temp[4] = {0}; while(pInstance->m_IsExit == false){if(pInstance->m_socket == SOCKETERROR){FD_ZERO(&sockfd);}else{FD_ZERO(&sockfd);FD_SET(pInstance->m_socket,&sockfd);}fd_set mySet = sockfd;memset(ReceiveDataInfo,0,1024);int Max_ID = pInstance->m_socket;int position=0;tv_out.tv_sec = 0;tv_out.tv_usec = 1000;if(select(Max_ID+1,&mySet,NULL,NULL,&tv_out)>0) //主要这一句{long nBytesRead = 0;unsigned long nBytesToRecv = pInstance->mreceivebuflen -pInstance->hasrecvlen;pInstance->recvsignal.Wait();if(pInstance->m_socket == SOCKETERROR){FD_ZERO(&sockfd);pInstance->recvsignal.Release();continue;}nBytesRead = recv(pInstance->m_socket,(char *)pInstance->mreceivebuf + pInstance->hasrecvlen, nBytesToRecv, 0);pInstance->recvsignal.Release();if(nBytesRead == -1 || nBytesRead == 0){pInstance->m_CSocket.SocketClose(pInstance->m_socket);FD_ZERO(&sockfd);pInstance->m_socket = SOCKETERROR;continue;}pInstance->hasrecvlen += nBytesRead;pInstance->m_CLog->ddprintf("CTCPClient","AUReceive",1,"recv a package!");pInstance->m_CLog->ddprintf("CTCPClient","AUReceive",1,"recvlen is %ld",nBytesRead);if((pInstance->FindCompletePackage(pInstance->receive,nBytesRead,pInstance->mreceivebuf))==false){continue;}//printf("validlen is %d\n",pInstance->validlen);pInstance->hasrecvlen =0;if(pInstance->validlen m_CLog->ddprintf("CTCPClient","AUReceive",1,"receive data is error(len is error)!");continue;}for(int i =0 ; ivalidlen; i++){sprintf(Temp,"%2x-", pInstance->receive[i]);strcat(ReceiveDataInfo, Temp);}pInstance->m_CLog->ddprintf("CTCPClient","AUReceive",1,"recv data is:%s",ReceiveDataInfo);unsigned int recvSN = Char2Int(pInstance->receive);position+=4;unsigned int recvCMD = Char2Short(pInstance->receive + position);position+=2;unsigned long buflen = Char2Short(pInstance->receive + position);position+=2;if(pInstance->validlen - position != buflen){pInstance->m_CLog->ddprintf("CTCPClient","AUReceive",1,"receive data is error(len error)!");continue;}stCommand newReceiveCommand;newReceiveCommand.CmdSN = recvSN;//newReceiveCommand.DataBuffer = "";bool rest = pInstance->FindSentCommand(newReceiveCommand);if(rest == false){pInstance->m_CLog->ddprintf("CTCPClient","AUReceive",1,"receive data is error(SN can not find)!");continue;}if(newReceiveCommand.CmdCode != recvCMD){pInstance->m_CLog->ddprintf("CTCPClient","AUReceive",1,"receive data is error(CMD is error)!");continue;}char *RecvData = new char[buflen];memcpy(RecvData,pInstance->receive+position,buflen);pInstance->UpdateSentCommand(recvSN,buflen,RecvData);newReceiveCommand.WaitEvent->Release();pInstance->m_CLog->ddprintf("CTCPClient","AUReceive",1,"send a signal of recv!");delete[] RecvData;}elseCsleep(100);}//pInstance->m_ThdRecv.ThreadExit();return NULL;}这个是recv设置非阻塞的方式,accept也是差不多