c++ - 等待接受方法 30 秒后退出服务器
问题描述
我有代码:
int client_fd = accept(fd, (struct sockaddr*) &client_address, &len);
服务器在这一行等待。如果 30 秒内没有传入连接请求,我想退出服务器。如何做到这一点?
下面的代码基本上等待来自客户端的传入请求并进行一些处理。但其中大部分可能对我们正在讨论的超时事情毫无用处。可能只有 accept 方法上面的部分很重要。
为清楚起见,在此处粘贴完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <map>
using namespace std;
void Trans( int n );
char* getEpochTime(char* epochTime);
int main(int argc, char *argv[]) {
char epochTime[20];
char startEpochTime[20];
strcpy(startEpochTime, getEpochTime(startEpochTime));
bool epochFlag = false;
char endEpochTime[20];
strcpy(endEpochTime, getEpochTime(endEpochTime));
int port = atoi(argv[1]);
int transactionNumber=0;
std::map<std::string, int> summaryMap;
int fd = socket(AF_INET, // an Internet socket
SOCK_STREAM, // reliable stream-like socket
0); // OS determine the protocol (TCP)
if (fd < 0)
return 1; // something went wrong
struct sockaddr_in serv_addr;
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
// setup server address
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port); // port
if (bind(fd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) // bind socket to the server address
return 1;
if (listen(fd, 1) < 0) // wait for clients, only 1 is allowed.
return 1;
printf("Using port %d\n",port);
while(1) {
struct sockaddr_in client_address; // client address
socklen_t clientLen;
clientLen = sizeof(client_address);
int client_fd;
if (select(fd+1, &readfds, NULL, NULL, &timeout) > 0)
{
client_fd = accept(fd, (struct sockaddr*) &client_address, &clientLen); // accept connection
}
else {
break;
}
if (client_fd < 0) // bad connection
continue; // discard
char buffer[1024];
int count = 0;
count = read(client_fd, buffer, sizeof(buffer));
char hostname[30];
if(count > 0) {
transactionNumber++;
buffer[count] = '\0';
char *pt;
pt = strtok (buffer,",");
char message[10];
strcpy(message,pt);
printf("%s\n", message);
pt = strtok (NULL,",");
char epoch[20];
strcpy(epoch,pt);
pt = strtok (NULL,",");
strcpy(hostname,pt);
summaryMap[hostname]++;
if(!epochFlag) {
strcpy(startEpochTime,epoch);
epochFlag=true;
}
printf("%s: # %d (%s) from %s\n",epoch,transactionNumber, message, hostname);
int transactionExecutionLength;
sscanf(message+1,"%d", &transactionExecutionLength);
Trans(transactionExecutionLength);
}
char clientMessage[50];
char _epochTime[50];
strcpy(_epochTime, getEpochTime(_epochTime));
sprintf(clientMessage,"%d,%s",transactionNumber,_epochTime);
write(client_fd, clientMessage, sizeof(clientMessage));
printf("%s: # %d (Done) from %s\n",_epochTime,transactionNumber, hostname);
stpcpy(endEpochTime,_epochTime);
}
map<string, int>::iterator it;
for ( it = summaryMap.begin(); it != summaryMap.end(); it++ )
{
std::cout << it->first // string (key)
<< ':'
<< it->second // string's value
<< std::endl ;
}
double startTime = std::stod(startEpochTime);
double endTime = std::stod(endEpochTime);
double TotalTime = endTime - startTime;
return 0;
}
char* getEpochTime(char* epochTime){
struct timeval current_time;
gettimeofday(¤t_time, NULL);
char epochTimeMilli[100];
char partialSeconds[10];
sprintf(epochTimeMilli, "%ld", current_time.tv_sec);
sprintf(partialSeconds, ".%d", (int)(current_time.tv_usec/10000));
strcat(epochTimeMilli, partialSeconds);
epochTime = epochTimeMilli;
return epochTime;
}
void Trans( int n ) {
int TransSave = 0;
long i, j;
// Use CPU cycles
j = 0;
for( i = 0; i < n * 100000; i++ ) {
j += i ^ (i+1) % (i+n);
}
TransSave += j;
TransSave &= 0xff;
}
解决方案
accept()
不提供任何超时功能。使用select()
or(e)poll()
预先检测侦听套接字何时处于可读状态,表明它有一个入站连接等待被接受。这些函数提供超时。例如:
#include <sys/select.h>
#include <sys/time.h>
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
struct timeval timeout;
timeout.tv_sec = 30;
timeout.tv_usec = 0;
if (select(fd+1, &readfds, NULL, NULL, &timeout) > 0)
{
len = sizeof(client_address);
int client_fd = accept(fd, (struct sockaddr*) &client_address, &len);
...
}
else
{
// do something else...
}
推荐阅读
- google-sheets - 如何在谷歌表格的多个列中搜索?
- python - pytorch nn 模块中的错误语法无效
- http - 在 Flutter 中使用服务器定期更新本地数据
- javascript - 如何将成员从电报组移动到另一个组
- elasticsearch - ELASTICSEARCH - 无限大小的内部点击 elasticsearch
- python - AttributeError:“事件”对象没有属性“键”我找不到错误
- google-chrome - Delphi 和 Google-Chrome 浏览器
- c# - 如何从 datagridview 中的按钮单击中删除项目。并在文本框中显示总和
- powershell - Powershell:检查 HKEY USER 中的值
- javascript - 如何重定向到 React.js 中的页面