HTMLページまたはエラーページをブラウザに送信するだけの小さなWebサーバーを作成しました。私の新しいソケットの知識を練習するためだけに。
このプログラムでは、select メソッドを使用して複数のリクエストを処理しようとしていました。
プログラムは接続を受け入れますが、何も起こりません... Firefox は引き続きファイルをロードしますが、ファイルは表示されず、プログラムは何もしません (ただし、クラッシュはしません)。
これは私のコードです:
#include <stdio.h>
#include <winsock2.h>
#include <winsock.h>
#include <Ws2tcpip.h>
#include <time.h>
#pragma comment(lib, "ws2_32.lib" )
#define BUFFSIZE 512
#define PORT "9001"
#define MAXCONNECTIONS 10
char * getPath(char * input, int var, char result[]);
void sendHeader(char * ext, char *path, int socketDescr, int code);
void sendBody(char * ext, char *path, int socketDescr, int code);
int main()
{
WSADATA wsaData;
struct timeval tv; // timeinterval for request (should arrive in less than 2seconds)
fd_set master; // keeps track of all open file descriptors + listener
fd_set read_fds; // list of file descriptors to read from
int fdmax; // max file descriptor number
int listener; // file descriptor on socket
int newfd; // new client file descriptor
struct sockaddr_storage clientaddr; // client address
socklen_t addrlen; // length of address
char clientIP[INET_ADDRSTRLEN]; // client ip-address (ipv4)
char buffer[BUFFSIZE]; // buffer for request
char request[BUFFSIZE]; // buffer for request
int recvbytes; // amount of bytes received
int yes = 1; // reuse address
int i,rv;
struct addrinfo serverinfo, *socketlist, *sock;
char result[BUFFSIZE];
char * path;
char * extension;
if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
// Set up time interval
tv.tv_sec = 5;
tv.tv_usec = 0;
// Clean up file descriptor sets
FD_ZERO(&master);
FD_ZERO(&read_fds);
// Get a socket and bind for listening
memset(&serverinfo, 0, sizeof(serverinfo));
serverinfo.ai_family = AF_INET;
serverinfo.ai_socktype = SOCK_STREAM; // TCP
serverinfo.ai_flags = AI_PASSIVE; // we search a socket on our side (server side) for listening
if((rv = getaddrinfo(NULL,PORT,&serverinfo,&socketlist)) != 0)
{
fprintf(stderr,"Server: %s\n",gai_strerror(rv));
exit(1);
}
// loop trough sockets
for(sock = socketlist; sock != NULL; sock = sock->ai_next)
{
listener = socket(sock->ai_family, sock->ai_socktype, sock->ai_protocol);
if(listener < 0)
{
continue; // not correct socket
}
setsockopt(listener,SOL_SOCKET,SO_REUSEADDR, &yes, sizeof(int));
if(bind(listener, sock->ai_addr, sock->ai_addrlen) < 0)
{
closesocket(listener);
continue; // could not bind to socket
}
break;
}
// if could not get socket
if(sock == NULL)
{
fprintf(stderr,"Server: %s\n","Could not bind to socket");
exit(2);
}
// free up list, we have the socket
freeaddrinfo(socketlist);
// listen on socket
if(listen(listener,MAXCONNECTIONS) < 0)
{
perror("Server: listen");
exit(3);
}
// add listener to master set
FD_SET(listener,&master);
fdmax = listener;
fprintf(stdout,"Server: %s\n","Waiting for connections...");
for(;;)
{
read_fds = master;
if(select(fdmax+1,&read_fds,NULL,NULL,&tv) < 0)
{
perror("Server: select");
exit(4);
}
// run through existing connections to see if request has arrived
for(i = 0; i <= fdmax; i++)
{
if(FD_ISSET(i, &read_fds))
{
if(i == listener)
{
// we have a new connection
addrlen = sizeof clientaddr;
if((newfd = accept(listener,(struct sockaddr*)&clientaddr,&addrlen)) < 0)
{
perror("Server: accept");
exit(5);
}
else
{
FD_SET(newfd,&master);
if(newfd > fdmax)
{
fdmax = newfd;
}
fprintf(stdout, "Server: New connection from %s on socket %d\n",inet_ntop(clientaddr.ss_family, &(((struct sockaddr_in*)((struct sockaddr*)&clientaddr))->sin_addr), clientIP, sizeof(clientIP)),newfd);
}
}
else
{
// handle data from request
if((recvbytes = recv(i,buffer,BUFFSIZE-1,0)) <= 0)
{
if(recvbytes == 0) //connection closed
{
fprintf(stdout,"Server: socket %d goodbye\n",i);
}
else //request error [BAD REQUEST]
{
perror("Server: recv");
}
closesocket(i);
FD_CLR(i,&master);
}
else
{
recvbytes = recv(i, buffer,BUFFSIZE-1 , 0);
if(recvbytes > 0)
{
buffer[recvbytes]='\0';
strcat(request,buffer);
}
fprintf(stdout,"Server: request received:\n");
printf("%s", request);
//Get path
path = getPath(request,0, result);
if(strcmp(path,"error") != 0)
{
extension = getPath(request,1,result);
if(strcmp(extension,"error") != 0)
{
// send file 200
sendBody(extension,path,i,200);
}
}
else
{
// send code 400
sendBody("html","400.html",i,400);
}
closesocket(i);
FD_CLR(i,&master);
}
}
}
}
}
return 0;
}
// Gives path, extension of file or error
char * getPath(char * input, int var, char result [])
{
char * pch;
char str[BUFFSIZE];
strcpy(str,input);
pch = strtok(str,"\r\n");
pch = strtok(pch," ");
if(strcmp(pch,"GET") != 0)
{
strcpy(result,"error");
return result;
}
pch = strtok(NULL," ");
if(var == 0)
{
strcpy(result,pch);
return result;
}
pch = strtok(pch,".");
pch = strtok(NULL,".");
if(var == 1)
{
strcpy(result,pch);
return result;
}
return 0;
}
//Send header
void sendHeader(char * ext, char *path, int socketDescr, int code)
{
FILE * fp;
int fileSize = 0;
char fileSizeChar[32];
char * header;
char * status;
char * contenType;
char * contentLength;
char * msg;
if((fp = fopen(path, "r")) == NULL)
{
printf("Error opening file %s\n",path);
return;
}
//Get filesize
fseek(fp, 0L, SEEK_END);
fileSize = ftell(fp);
fseek(fp, 0L, SEEK_SET);
fclose(fp);
//Create header response message
header = "HTTP/1.0 ";
if(code == 200)
strcpy(status,"200");
else if(code == 400)
strcpy(status,"400");
else if(code == 404)
strcpy(status,"404");
if(strcmp(ext,"html") == 0)
strcpy(contenType," text/html\n");
//create and send header
strcat(msg,header);
strcat(msg,status);
strcat(msg,contenType);
strcat(msg,contentLength);
strcat(msg,fileSizeChar);
send(socketDescr, msg, strlen(msg), 0);
}
//Sending data like, pictures, zip, html pages... or an error html page
void sendBody(char * ext, char *path, int socketDescr, int code)
{
FILE * fp;
int fileSize = 0;
int sendBytes = 0;
int resultRead;
int resultSend;
char buffer[1000];
if((fp = fopen(path, "r")) == NULL)
{
printf("Can't open file %s\n",path);
if(code == 400)
{
printf("Error page 400 doesn't exist.\n");
return;
}
if((fp = fopen("404.html","r")) == NULL)
{
printf("Error page 404 doesn't exist.\n");
return;
}
strcpy(ext,"html");
strcpy(path,"404.html");
code = 404;
}
sendHeader(ext,path,socketDescr,code);
fseek(fp, 0L, SEEK_END);
fileSize = ftell(fp);
fseek(fp, 0L, SEEK_SET);
while(sendBytes < fileSize)
{
fseek(fp,sendBytes,SEEK_SET);
resultRead = fread(buffer,sizeof buffer[0],1000,fp);
resultSend = send(socketDescr,buffer,resultRead,NULL);
sendBytes +=resultSend;
}
fclose(fp);
}
表示される唯一の行は「サーバー: ソケット上の %s からの新しい接続」です。
誰か助けてくれませんか?
敬具、