Socket programmering
Jeg har lavet en simpel webserver. Og den kører nogenlunde. Dog et lille problem - den æder 40% af cpu tiden. Jeg anvder NON-Blocking sockets og SELECT !!!Nogle konstruktive forslag til hvordan prob. løses?
MVH
Thomas Hansen
Nedenfor er min source:
void WebServer(void)
{
int servSock; // Socket descriptor for server
int clntSock; // Socket descriptor for client
struct sockaddr_in echoServAddr; // Local address
struct sockaddr_in echoClntAddr; // Client address
unsigned short echoServPort; // Server port
int servLen; // Length of server address data structure
int n_received; //
fd_set fd_read, fd_write;
long arg;
typedef struct timeval
{
int tv_sec; // second
int tv_usec; // microseconds
} TIMEVAL;
//timeval select_to;
// int visitcount = 1;
TIMEVAL select_to;
echoServPort = 80; // Port 80 - WWW
// Create socket for incoming connections
if ((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
return;
// Construct local address structure
memset(&echoServAddr, 0, sizeof(echoServAddr)); // Zero out structure
echoServAddr.sin_family = AF_INET; // Internet address family
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface
echoServAddr.sin_port = htons(echoServPort); // Local port
// Bind to the local address
if (bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("bind() failed");
// Set socket to nonblocking
arg = 1; // enables non blocking mode
if (ioctlsocket(servSock, FIONBIO,(PFDWORD)&arg)!= 0) // All options off
{
closesocket(servSock);
return;
}
// Mark the socket so it will listen for incoming connections
if (listen(servSock, MAXPENDING) < 0)
DieWithError("listen() failed");
while(1)
{
// Socket list for select is set up here !
FD_ZERO(&fd_read);
FD_SET(servSock, &fd_read);
// Wait for connection to be ready !
if (select(1,(PFDSET)&fd_read,(PFDSET)0,(PFDSET)0,(PTIMEVAL)0) !=1)
continue;
// Accept available connected socket !
servLen = sizeof((echoClntAddr));
//if ((clntSock = accept(servSock, (PSOCKADDR)&echoClntAddr,(PFINT)&servLen))<0)
if ((clntSock = accept(servSock, (PSOCKADDR)&echoServAddr,(PFINT)&servLen))<0) // Tvivl om echoServAdr?
continue;
// Set socket to nonblocking mode
// Force recv to return an error if no data is available.
// Force send to return an error if it needs to block ->
// send needs only to block if it can't fit all output data into output window.
arg = 1; // enables non blocking mode
if (ioctlsocket(clntSock, FIONBIO,(PFDWORD)&arg)!= 0) // All options off
{
closesocket(clntSock);
continue;
}
// Set up socket list for select
FD_ZERO(&fd_read);
FD_SET(clntSock,&fd_read);
// Wait for any data to be available
if (select(1,(PFDSET)&fd_read,(PFDSET)0, (PFDSET)0,(PCTIMEVAL)0)!=1)
{
closesocket(clntSock);
continue;
}
// Get data and ....
while ((n_received = recv(clntSock,buf,BUFSIZE,0))>0)
{
// set up socket list for select
FD_ZERO(&fd_write);
FD_SET(clntSock,&fd_write);
// Wait 20 sec. for previos sent to complete. ie. waits until all ouput data has been asked !
select_to.tv_sec = 90;
select_to.tv_usec = 0;
if (select(1,NULL,(PFDSET)&fd_write,NULL,(PCTIMEVAL)&select_to) != 1)
//if (select(1,NULL,(PFDSET)&fd_write,NULL, NULL) != 1)
{
closesocket (clntSock);
continue; // select error
}
// send output data
send(clntSock,defaultside, strlen(defaultside),0);
// setup socket list for select !
FD_ZERO(&fd_read);
FD_SET(clntSock,&fd_read);
// Wait for any data to be available
if (select(1,(PFDSET)&fd_read,(PFDSET)0, (PFDSET)0,(PCTIMEVAL)0)!=1)
{
closesocket(clntSock);
continue;
}
closesocket(clntSock);
printf("clntSock Close\n");
}
close(servSock);
}
/* NOT REACHED */
}