Unix™ Systems Programming [Electronic resources] : Communication, Concurrency, and Threads نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Unix™ Systems Programming [Electronic resources] : Communication, Concurrency, and Threads - نسخه متنی

Prentice Hall

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید










18.5 UICI Implementations of Different Server Strategies


Program 4.6 on page 100 to perform the actual copying. Once it has finished the copying, the server closes the communication file descriptor, displays the number of bytes copied, and resumes listening.

Program 18.1 server.c

A serial server implemented using UICI.


#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "restart.h"
#include "uici.h"
int main(int argc, char *argv[]) {
int bytescopied;
char client[MAX_CANON];
int communfd;
int listenfd;
u_port_t portnumber;
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
return 1;
}
portnumber = (u_port_t) atoi(argv[1]);
if ((listenfd = u_open(portnumber)) == -1) {
perror("Failed to create listening endpoint");
return 1;
}
fprintf(stderr, "[%ld]:waiting for the first connection on port %d\n",
(long)getpid(), (int)portnumber);
for ( ; ; ) {
if ((communfd = u_accept(listenfd, client, MAX_CANON)) == -1) {
perror("Failed to accept connection");
continue;
}
fprintf(stderr, "[%ld]:connected to %s\n", (long)getpid(), client);
bytescopied = copyfile(communfd, STDOUT_FILENO);
fprintf(stderr, "[%ld]:received %d bytes\n", (long)getpid(), bytescopied);
if (r_close(communfd) == -1)
perror("Failed to close communfd\n");
}
}

Exercise 18.9

Under what circumstances does a client cause the server in Program 18.1 to terminate?

Answer:

The server executes the first return statement if it is not started with a single command-line argument. The u_open function creates a communication endpoint associated with a port number. The u_open function fails if the port is invalid, if the port is in use, or if system resources are not available to support the request. At this point, no clients are involved. Once the server has reached u_accept, it does not terminate unless it receives a signal. A client on a remote machine cannot cause the server to terminate. A failure of u_accept causes the server to loop and try again. Notice that I/O errors cause copyfile to return, but these errors do not cause server termination.

Program 18.2 implements the parent-server strategy. The parent accepts client connections and forks a child to call copyfile so that the parent can resume waiting for connections. Because the child receives a copy of the parent's environment at the time of the fork, it has access to the private communication channel represented by communfd.

Exercise 18.10

What happens if the client name does not fit in the buffer passed to u_accept?

Answer:

The implementation of u_accept does not permit the name to overflow the buffer. Instead, u_accept truncates the client name. (See Section 18.7.6.)

Exercise 18.11

What happens if after the connection is made, you enter text at standard input of the server?

Answer:

The server program never reads from standard input, and what you type at standard input is not sent to the remote machine.

Exercise 18.12

Program 18.2 uses r_close and r_waitpid from the restart library. How does this affect the behavior of the program?

Answer:

Functions in the restart library restart the corresponding function when the return value is 1 and errno is EINTR. This return condition occurs when the signal handler of a caught signal returns. Program 18.2 does not catch any signals, so using the restarted versions is not necessary. We use the functions from the restart library to make it easier to add signal handling capability to the programs.

Program 18.2 serverp.c

A server program that forks a child to handle communication.


#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "restart.h"
#include "uici.h"
int main(int argc, char *argv[]) {
int bytescopied;
pid_t child;
char client[MAX_CANON];
int communfd;
int listenfd;
u_port_t portnumber;
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
return 1;
}
portnumber = (u_port_t) atoi(argv[1]);
if ((listenfd = u_open(portnumber)) == -1) {
perror("Failed to create listening endpoint");
return 1;
}
fprintf(stderr, "[%ld]: Waiting for connection on port %d\n",
(long)getpid(), (int)portnumber);
for ( ; ; ) {
if ((communfd = u_accept(listenfd, client, MAX_CANON)) == -1) {
perror("Failed to accept connection");
continue;
}
fprintf(stderr, "[%ld]:connected to %s\n", (long)getpid(), client);
if ((child = fork()) == -1) {
perror("Failed to fork a child");
continue;
}
if (child == 0) { /* child code */
if (r_close(listenfd) == -1) {
fprintf(stderr, "[%ld]:failed to close listenfd: %s\n",
(long)getpid(), strerror(errno));
return 1;
}
bytescopied = copyfile(communfd, STDOUT_FILENO);
fprintf(stderr, "[%ld]:received %d bytes\n",
(long)getpid(), bytescopied);
return 0;
}
if (r_close(communfd) == -1) /* parent code */
fprintf(stderr, "[%ld]:failed to close communfd: %s\n",
(long)getpid(), strerror(errno));
while (r_waitpid(-1, NULL, WNOHANG) > 0) ; /* clean up zombies */
}
}


    / 276