|
以下实现了典型的server程序,它以并行的方式来处理文本请求。因为处理请求时大部分时间都消耗在了创建进程,所以下面这个例程像apache那样事先创建几个进程,当连接已经建立以后,客户端的请求由已经创建的那些进程来处理。
希望对大家有所帮助
[code:1]#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/types.h>
#define PORT 9876
#define FALSE 0
#define TRUE 1
#define MAX 5
int Running = TRUE;
int main(void)
{
/*
** prepool_server.c - Concurrent Server: Subtask Pool
*/
struct area { /* flag for every subtask*/
int flag[MAX]; /* 0:idle, 1:good -:exit */
} area, *aptr;
int flag = (IPC_CREAT | IPC_EXCL | 0660);
int size = sizeof(struct area);
key_t key = 0x5a5a5a5a;
int shmid; /*shared memory area id */
void control_C(); /* ctrl-c signal handler */
struct sockaddr_in sock;
int socklen = sizeof(sock); /* struct len for accept() */
FILE *fp;
fd_set fds;
int acc;
int cli;
int line;
int opt = 1;
int ident;
int pids[MAX];
char file[32];
char buf[80];
int status;
/* initialize ~C handler */
signal(SIGINT, control_C);
/* create a (server) socket to accept a client */
acc = socket(AF_INET, SOCK_STREAM, 0);
/* bind socket to port */
sock.sin_family = AF_INET;
sock.sin_port = htons(PORT);
sock.sin_addr.s_addr = htonl(INADDR_ANY);
bind(acc, (struct sockaddr *)&sock, socklen);
setsockopt(acc, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
listen(acc, 5);
/* get the shared memory area */
shmid = shmget(key, size, flag);
/* attach subtask's shared memory array */
[color=red]aptr = (struct area *) shmat(shmid, 0, 0);[/color]
/* pre-establish subtask pool */
for (ident = 0; ident < MAX; ident++) {
aptr->flag[ident] = 0; /* set flags idle */
if ((pids[ident] = fork()) == 0) { /* subtask */
/* attach parent's shared memory array */
aptr = (struct area *) shmat(shmid, 0, 0);
/* notice: shmid is still set correctly */
/* nullify ~C handler */
signal(SIGINT, SIG_DFL);
/*
** Pool Memory array for a non-zero flag
*/
while (1) {
if (aptr->flag[ident] = 0) {
usleep(1); /* release processor */
continue; /* stay in pool loop */
} else if (aptr->flag[ident] < 0) {
exit(0);
} [color=red][color=#444444]else [/color][/color]{
cli = accept(acc, (struct sockaddr *)&sock, &socklen);
/* receive an incoming query */
recv(cli, buf, sizeof(buf), 0);
/* open the requested text file */
sscanf(buf, "%s %d", file, &line);
fp = fopen(file, "r");
while (line--) {
fgets(buf, sizeof(buf), fp);
}
fclose(fp);
/* send back a response */
buf[strlen(buf) - 1] = '\0';
send(cli, buf, strlen(buf) + 1, 0);
close(cli);
/* set to available */
aptr->flag[ident] = 0;
}
}
}
}
/*
** Parent task passes incoming connection to a subtask
*/
while (Running) { /* set FALSE in control_C signal handler */
FD_ZERO(&fds);
FD_SET(acc,&fds);
/* block until client is ready for connect */
if (select(acc + 1, &fds, NULL, NULL, NULL) < 0) {
break;
}
/*
** Assign incoming query to first available subtask
*/
for (ident = 0; ident < MAX; ident++) {
if (aptr->flag[ident] == 0) {
aptr->flag[ident] = 1;
break;
}
}
}
/* wait for each subtask exit */
for (ident = 0; ident < MAX; ident++) {
aptr->flag[ident] = -1;
waitpid(pids[ident], &status, 0);
}
/* remove unused shared memory area and exit */
shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);
return 0;
}
/*
** ~C signal handler
*/
void control_C()
{
Running = FALSE; /* reset flag to allow exit */
exit(0);
}
[/code:1] |
|