/usr/include/linux/limits.h:#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/param.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#include "npipe.h"
#define WELL_KNOWN_FIFO "/tmp/ssp_fifo"
#define LINE_LEN 256
#define MAXPID 512
static void rm_fifo (void);
int main (void)
{
int n;
int fd;
int *fd_pid;
char buf [LINE_LEN];
char cmd [LINE_LEN];
char path [MAXPATHLEN];
pid_t pid;
double num;
double res;
if (unlink (WELL_KNOWN_FIFO) == -1) {
if (errno != ENOENT)
perror("unlink failed"); /*没有权限删除*/
}
/*创建一个共知的 FIFO*/
if (mkfifo (WELL_KNOWN_FIFO, S_IFIFO|0777) == -1) {
perror("mkfifo failed");
exit(1);
}
/*注册退出处理程序.当服务器终止时,退出处理程序确保共知FIFO不会搞乱文件系统,因为有名管道是以文件形式存储在文件系统中而不是和无名管道那样在内存中*/
if (atexit (rm_fifo) == -1) {
perror("atexit failed");
exit(1);
}
/*读共知FIFO以查客户机送来的消息,若客户机没有写FIFO或以写方式大开FIFO,服务器在此阻塞*/
if ((fd = open (WELL_KNOWN_FIFO, O_RDONLY)) == -1) {
perror("open");
exit(1);
}
if ((fd_pid = calloc (MAXPID, sizeof (int))) == NULL) {
perror("calloc failed");
exit(1);
}
/*忽略 SIGPIPE 信号以防止客户端提交了请求但在我们有机会应答之前服务器被终止*/
if (sigset (SIGPIPE, SIG_IGN) == SIG_ERR) {
perror("sigset");
exit(1);
}
/*从共知FIFO读取一行,遇到NULL时终止.使用 sscanf() 解析指令并提取出进程ID,命令字符串,可选数字*/
while ((n = read (fd, buf, LINE_LEN)) > 0) {
buf [n] = '\0';
sscanf (buf, "%d %s %lf", &pid, cmd, &num);
if (strcmp (cmd, "open") == 0) {
if (fd_pid [pid] == 0) {
snprintf (path, MAXPATHLEN, "%s.%ld", WELL_KNOWN_FIFO, (long)pid);
if (unlink (path) == -1) { /*如果存在则先删除*/
if (errno != ENOENT) {
printf("unlink failed\n");
continue;
}
}
if (mkfifo (path, S_IFIFO|0777) == -1) { /*建立特定于客户机的FIFO*/
printf("mkfifo failed\n");
continue;
}
if ((fd_pid [pid] = open (path, O_WRONLY)) == -1) { /*服务器只写客户机特定FIFO*/
printf("open failed\n");
fd_pid [pid] = 0;
continue;
}
}
}
if (strcmp (cmd, "sqrt") == 0) { /*客户端送来 sqrt 求平方根请求*/
res = sqrt (num);
snprintf (buf, LINE_LEN, "%lf\n", res);
n = strlen (buf);
if (writen (fd_pid [pid], buf, n) == -1) {
printf ("writen failed\n");
close (fd_pid [pid]);
fd_pid [pid] = 0;
}
}
if (strcmp (cmd, "quit") == 0) { /*客户机退出,使服务器关闭FIFO自己这一端*/
close (fd_pid [pid]);
fd_pid [pid] = 0;
}
}
return (0);
}
static void rm_fifo (void)
{
unlink (WELL_KNOWN_FIFO);
}
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/param.h>
#include <errno.h>
#include <string.h>
#include "npipe.h"
#include <stdlib.h>
#define WELL_KNOWN_FIFO "/tmp/ssp_fifo"
#define LINE_LEN 256
/*客户机发送格式字符串到服务器*/
/*简单协议: PID command [number]*/
int main (void)
{
pid_t pid;
int wk_fd;
int my_fd;
int n;
char buf [LINE_LEN];
char path [MAXPATHLEN];
/*只写方式打开有名管道*/
if ((wk_fd = open(WELL_KNOWN_FIFO, O_WRONLY)) == -1) {
perror("open FIFO");
exit(1);
}
pid = getpid();
snprintf(buf, LINE_LEN, "%d open \n", pid);
n = strlen (buf);
if (writen (wk_fd, buf, n) == -1) { /*写 "pid open \n" 到FIFO,请求建立连接 */
perror("write failed");
exit(1);
}
/*path中: /tmp/ssp_fifo.客户机pid*/
snprintf(path, MAXPATHLEN, "%s.%d", WELL_KNOWN_FIFO, pid);
while ((my_fd = open (path, O_RDONLY)) == -1) { /*特定的客户机FIFO不存在则连续读取(等待服务器创建)*/
if (errno != ENOENT) {
printf("Can't open my fifo");
exit(1); /*存在而不能打开则错误退出*/
}
}
if (unlink (path) == -1) { /*服务器已经建立客户机FIFO确认连接,客户端将其删除*/
perror("unlink"); /*!!!--文件在程序退出前并没有真正删除--!!!*/
exit(1);
}
/*提示输入要求平方根的数字*/
printf ("Enter a number: ");
fflush (stdout);
while (fgets (path, LINE_LEN, stdin) != NULL) {
snprintf (buf, LINE_LEN, "%d sqrt %s", pid, path); /* pid sqrt 数字*/
n = strlen (buf);
if (writen (wk_fd, buf, n) == -1) { /*写到共知 FIFO*/
perror("writen");
exit(1);
}
if ((n = read (my_fd, buf, LINE_LEN)) == -1) { /*读特定客户端FIFO*/
printf("Can't read my FIFO");
exit(1);
}
if (n == 0) {
printf("Server closed my pipe");
exit(1);
}
buf [n] = '\0'; /*输出到标准输出*/
if (fputs (buf, stdout) == EOF) {
printf("fputs failed");
exit(1);
}
printf ("Enter a number: ");
fflush (stdout);
}
if (ferror (stdin)) {
printf("fgets from standard input failed");
exit(1);
}
snprintf (buf, LINE_LEN, "%d close\n", pid);
n = strlen (buf);
if (writen (wk_fd, buf, n) == -1) {
printf("writen failed");
exit(1);
}
printf("\n");
close (wk_fd);
close (my_fd);
return (0);
}
欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) | Powered by Discuz! X3.2 |