【发布时间】:2015-01-20 16:23:15
【问题描述】:
我正在编写一个 HTTP 服务器,我想为它实现 408 响应状态码
此状态代码用于“请求超时”,我不知道应该如何以及何时发送此响应。
这是 RFC 中此状态代码的定义: 服务器等待请求超时。根据 HTTP 规范:“客户端在服务器准备等待的时间内没有产生请求。客户端可以在以后的任何时间重复请求而无需修改。”
服务器一直在循环和接受连接我不知道如何计算请求时间,如果发送请求的时间达到某个阈值,则发送响应。
这是我的代码:
int sock, connected, bytes_recieved , _true = 1 , portNumber;
char send_data [1024] , recv_data[1024];
struct sockaddr_in server_addr,client_addr;
int sin_size;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Unable to create the Socket");
exit(1);
}
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(const char*)&_true,sizeof(int)) == -1) {
perror("Unable to Setsockopt");
exit(1);
}
char *server_address="127.1.1.1";
portNumber=8080;
server_addr.sin_family = AF_INET;
////htons function makes sure that numbers are stored in memory in network byte order (big indian)
server_addr.sin_port = htons(portNumber);
server_addr.sin_addr.s_addr = inet_addr("127.1.1.1");//inet_pton(AF_INET,"127.0.0.1",&server_addr.sin_addr);//INADDR_ANY;
//save the host information for future purposes
string host=server_address+':'+to_string(portNumber);
//bzero(&(server_addr.sin_zero),8); --This is for POSIX based systems
memset(&(server_addr.sin_zero),0,8);//sockaddr_in zero padding is needed
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))==-1) //bind the socket to a local address
{
perror("Unable to bind");
exit(1);
}
if (listen(sock, 5) == -1) //listen to the socket with the specified waiting queue size
{
perror(" Listen");
exit(1);
}
cout << "MyHTTPServer waiting on port 8080" << endl;
fflush(stdout);
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
cout<< "I got a connection from (" << inet_ntoa(client_addr.sin_addr) << "," << ntohs(client_addr.sin_port) << ')' << endl;
//fflush(stdout);
char sendBuffer[500];
FILE *sendFile = fopen("foo.html", "r");
fseek(sendFile, 0L, SEEK_END);
int sz = ftell(sendFile);
fseek(sendFile, 0L, SEEK_SET);
char receiveBuffer[400];
recv(connected,receiveBuffer,sizeof(receiveBuffer),0);
cout << "Received:\n" << receiveBuffer << endl;
string s1;
s1="HTTP/1.1 200 OK\nContent-length: " + to_string(sz) + "\n";
std::vector<char> writable(s1.begin(), s1.end());
writable.push_back('\0');
//"HTTP/1.1 200 OK\nContent-length: 222\n"
strcpy(sendBuffer,(const char *)&writable[0]);
int c=send(connected,(const char*)&sendBuffer,strlen(&writable[0]),0);
printf("\nSent : %s\n",sendBuffer);
strcpy(sendBuffer,"Content-Type: text/html\n\n");
c=send(connected,(const char*)&sendBuffer,strlen("Content-Type: text/html\n\n"),0);
printf("\nSent : %s\n",sendBuffer);
char send_buffer[500];
while( true )
{
if(feof(sendFile))
{
break;
}
int numread = fread(send_buffer, sizeof(unsigned char), sz, sendFile);
if( numread < 1 ) break; // EOF or error
char *send_buffer_ptr = send_buffer;
do
{
int numsent = send(connected,send_buffer_ptr, numread, 0);
if( numsent < 1 ) // 0 if disconnected, otherwise error
{
if( numsent < 0 )
{
if( WSAGetLastError() == WSAEWOULDBLOCK )
{
fd_set wfd;
FD_ZERO(&wfd);
FD_SET(connected, &wfd);
timeval tm;
tm.tv_sec = 10;
tm.tv_usec = 0;
if( select(0, NULL, &wfd, NULL, &tm) > 0 )
continue;
}
}
break; // timeout or error
}
send_buffer_ptr += numsent;
numread -= numsent;
cout << "round";
}
while( numread > 0 );
}
//printf("\nSTATUS:%d",c);
WSACleanup();
【问题讨论】:
-
@EJP 的回答看起来足以满足您的目的。如果你想要一个额外的挑战,你可以考虑在你的服务器上处理诸如慢速客户端 DOS 攻击之类的事情。
标签: c sockets http network-programming