====== تابع ()fork ======
از این تابع به وسیله multi-process کردن سرور، یک سرور concurrent می سازیم
#include
#include
pid_t fork(void);
اسکلت کلی استفاده از [[fork]] در سرور
pid_t pid;
int listen_sock, client_sock;
listen_sock = socket(...);
bind(listen_sock, ...);
listen(listen_sock, ...);
// ignoring the SIGCHLD signal
// prevent zombie/defunct child processes
signal(SIGCHLD, SIG_IGN);
while(1) {
client_sock = accept(listen_sock, ...); // blocking call
pid = fork();
if (pid == 0 ) { // this is the child process
close(listen_sock); // child doesn't need the listener
// process the request, doing something using client_sock
close(client_sock);
exit(0); // child terminates
}
close(client_sock); // parent doesn't need this
}
مثال یک سرور multi-process
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT "54990"
#define BACKLOG 120
int main()
{
int status, listen_sock, client_sock, sockopt;
struct addrinfo hints, *res, *rp;
struct sockaddr_storage client_addr;
socklen_t addrlen;
char ipstr[INET_ADDRSTRLEN];
pid_t pid;
char *msg = "Message from server: Hello World\n";
size_t msglen;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
status = getaddrinfo(NULL, PORT, &hints, &res);
if (status != 0) {
fprintf(stderr, "getaddrinfo() error: %s\n",
gai_strerror(status));
exit(EXIT_FAILURE);
}
for (rp = res; rp != NULL; rp = rp->ai_next) {
listen_sock = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (listen_sock == -1) {
perror("socket() error ");
continue;
}
sockopt = 1;
status = setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
(void*)&sockopt, sizeof(sockopt));
if (status == -1) {
perror("setsockopt() error ");
exit(EXIT_FAILURE);
}
status = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (status == -1) {
perror("bind() error ");
close(listen_sock);
continue;
}
break;
}
freeaddrinfo(res);
if (rp == NULL) {
fprintf(stderr, "Could not bind()\n");
exit(EXIT_FAILURE);
}
status = listen(listen_sock, BACKLOG);
if (status == -1) {
perror("listen() error ");
exit(EXIT_FAILURE);
}
printf("Wating for connections...\n");
signal(SIGCHLD, SIG_IGN);
addrlen = sizeof(client_addr);
while(1) {
client_sock = accept(listen_sock, (struct sockaddr *)&client_addr,
&addrlen);
if (client_sock == -1) {
perror("accept() error ");
continue;
}
inet_ntop(client_addr.ss_family,
&(((struct sockaddr_in *)&client_addr)->sin_addr),
ipstr, INET_ADDRSTRLEN);
printf("Got connection from: %s\n", ipstr);
pid = fork();
if (pid == 0) {
close(listen_sock);
msglen = strlen(msg);
status = send(client_sock, msg, msglen, 0);
if (status == -1) {
perror("send() error ");
close(client_sock);
exit(EXIT_FAILURE);
}
close(client_sock);
exit(EXIT_SUCCESS);
} else if (pid == -1) {
perror("fork() error ");
close(client_sock);
continue;
}
printf("Forked process PID: %d\n", pid);
close(client_sock);
}
close(listen_sock);
return 0;
}