《UNIX网络编程 卷2》读书笔记(一)

时间:2022-08-04 21:06:14

1,获取Posix IPC的名字

《UNIX网络编程 卷2》读书笔记(一)#include  " unpipc.h "
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)
char *  px_ipc_name( const   char *  name)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)      
char* dir,*dst,*slash;
《UNIX网络编程 卷2》读书笔记(一)      
if((dst = malloc(PATH_MAX))==NULL) return NULL;//分配失败
《UNIX网络编程 卷2》读书笔记(一)
      if((dir=getenv("PX_IPC_NAME"))==NULL)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)      
{//目录名
《UNIX网络编程 卷2》读书笔记(一)
          #ifdef POSIX_IPC_PREFIX
《UNIX网络编程 卷2》读书笔记(一)               dir 
= POSIX_IPC_PREFIX;
《UNIX网络编程 卷2》读书笔记(一)          
#else
《UNIX网络编程 卷2》读书笔记(一)               dir 
= "/tmp/";
《UNIX网络编程 卷2》读书笔记(一)          
#endif
《UNIX网络编程 卷2》读书笔记(一)      }

《UNIX网络编程 卷2》读书笔记(一)      slash 
= (dir[strlen(dir)-1== '/')?"":"/";
《UNIX网络编程 卷2》读书笔记(一)      snprintf(dst,PATH_MAX,
"%S%S%S",dir,slash,name);//全路径名称
《UNIX网络编程 卷2》读书笔记(一)
      return dst;
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)

2Mq_open,lsem_open,shm_open用来创建或打开一个IPC对象,第2个参数oflag指定打开IPC对象的方式。消息队列可以以只读,只写或读写任何一种模式打开,信号灯的打开不指定任何模式,共享内存区不能以只写模式打开

3System V IPC使用key_t作为其名字,通常是先调用stat函数,再调用ftok函数得到的,函数ftok把一个已经存在的路径和一个整数标识符转换为一个key_t,IPC(IPC key).

4,内核给每个IPC对象维护一个数据结构

《UNIX网络编程 卷2》读书笔记(一)struct  ipc_perm
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)   uid_t uid;
//owner的用户ID 
《UNIX网络编程 卷2》读书笔记(一)
   gid_t gid;//owner的组ID 
《UNIX网络编程 卷2》读书笔记(一)
   uid_t cuid;//creater的用户ID
《UNIX网络编程 卷2》读书笔记(一)
   gid_t cgid;//creater的组ID
《UNIX网络编程 卷2》读书笔记(一)
   mode_t mode;//读写模式 
《UNIX网络编程 卷2》读书笔记(一)
   ulong_t seq;//序列号 
《UNIX网络编程 卷2》读书笔记(一)
   key_t key;//IPC key 
《UNIX网络编程 卷2》读书笔记(一)
}
;
《UNIX网络编程 卷2》读书笔记(一)

   ipc_perm 结构体中的seq成员很有意思,它是作为一个计数器,每当删除一个IPC时,内核就递增这个变量,若溢出则循环回到0.

 

5,管道是最初的Unix IPC形式,其局限性在于没有名字,而且只能由有亲缘关系的进程使用。FIFO又叫有名管道,任何进程之间都能使用。两者都可以使用通常的readwrite访问。

6,

《UNIX网络编程 卷2》读书笔记(一)#include  " unpipc.h "
《UNIX网络编程 卷2》读书笔记(一)
void  client( int  readfd, int  writefd)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{//客户 
《UNIX网络编程 卷2》读书笔记(一)
     size_t len;
《UNIX网络编程 卷2》读书笔记(一)     ssize_t n;
《UNIX网络编程 卷2》读书笔记(一)     
char buff[MAXLINE];
《UNIX网络编程 卷2》读书笔记(一)     fgets(buff,MAXLINE,stdin);
//读入路径名
《UNIX网络编程 卷2》读书笔记(一)
     len = strlen(buff);
《UNIX网络编程 卷2》读书笔记(一)     
if(buff[len-1]=='\n')//去掉结尾处的行符 
《UNIX网络编程 卷2》读书笔记(一)
        len--;
《UNIX网络编程 卷2》读书笔记(一)     write(writefd,buff,len);
//写入管道  
《UNIX网络编程 卷2》读书笔记(一)
     while((n==read(readfd,buff,MAXLINE))>0)//从管道读入数据 
《UNIX网络编程 卷2》读书笔记(一)
         write(STDOU_FILENO,buff,n);//输出 
《UNIX网络编程 卷2》读书笔记(一)
      
《UNIX网络编程 卷2》读书笔记(一)}
 
《UNIX网络编程 卷2》读书笔记(一)
void  server( int  readfd, int  writefd)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{//服务器 
《UNIX网络编程 卷2》读书笔记(一)
     int fd;
《UNIX网络编程 卷2》读书笔记(一)     ssize_t n;
《UNIX网络编程 卷2》读书笔记(一)     
char buff[MAXLINE+1];
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)     
if((n==read(readfd,buff,MAXLINE))>0)//从管道读入数据 
《UNIX网络编程 卷2》读书笔记(一)
         buff[n]='\0';
《UNIX网络编程 卷2》读书笔记(一)     
if((fd=open(buff,0_RDONLY))<0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)     
{//给客户端返回出错信息 
《UNIX网络编程 卷2》读书笔记(一)
         snprintf(buff+n,sizeof(buff)-n,"can't open,%s\n",strerror(errno));
《UNIX网络编程 卷2》读书笔记(一)         n 
= strlen(buff);
《UNIX网络编程 卷2》读书笔记(一)         write(writefd,buff,n);
《UNIX网络编程 卷2》读书笔记(一)     }

《UNIX网络编程 卷2》读书笔记(一)     
else
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)     
{
《UNIX网络编程 卷2》读书笔记(一)          
while((n=read(fd,huff,MAXLINE))>0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)          
{//给客户端返回文件内容 
《UNIX网络编程 卷2》读书笔记(一)
              write(writefd,buff,n);
《UNIX网络编程 卷2》读书笔记(一)          }

《UNIX网络编程 卷2》读书笔记(一)          close(fd);
《UNIX网络编程 卷2》读书笔记(一)     }
    
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)
int  main( int  argc, char **  argv)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)    
int pipe1[2],pipe2[2];
《UNIX网络编程 卷2》读书笔记(一)    pid_t childpid;
《UNIX网络编程 卷2》读书笔记(一)    
//创建两个管道 
《UNIX网络编程 卷2》读书笔记(一)
    pipe(pipe1);
《UNIX网络编程 卷2》读书笔记(一)    pipe(pipe2);
《UNIX网络编程 卷2》读书笔记(一)    
if((childpid=fork())==0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)    
{
《UNIX网络编程 卷2》读书笔记(一)        close(pipe1[
1]);//子进程关闭管道1的写入端 
《UNIX网络编程 卷2》读书笔记(一)
        close(pipe2[0]);//子进程关闭管道2的读出端 
《UNIX网络编程 卷2》读书笔记(一)
        server(pipe1[0],pipe2[1]);
《UNIX网络编程 卷2》读书笔记(一)        exit(
0);
《UNIX网络编程 卷2》读书笔记(一)    }

《UNIX网络编程 卷2》读书笔记(一)    close(pipe1[
0]);//父进程关闭管道1的读出端 
《UNIX网络编程 卷2》读书笔记(一)
    close(pipe2[1]);//父进程关闭管道2的写入端 
《UNIX网络编程 卷2》读书笔记(一)
    client(pipe2[0],pipe1[1]);
《UNIX网络编程 卷2》读书笔记(一)    waitpid(childpid,NULL,
0);
《UNIX网络编程 卷2》读书笔记(一)    
return 0;
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)


上面这个例子也可以使用popencat来实现

《UNIX网络编程 卷2》读书笔记(一)#include  " unpipc.h "
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)
int  main( int  argc, char **  argv)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)    size_t n;
《UNIX网络编程 卷2》读书笔记(一)    
char buff[MAXLINE],command[MAXLINE];
《UNIX网络编程 卷2》读书笔记(一)    FILE
* fp;
《UNIX网络编程 卷2》读书笔记(一)    fgets(buff,MAXLINE,stdin);
//读入路径名
《UNIX网络编程 卷2》读书笔记(一)
    n = strlen(buff);
《UNIX网络编程 卷2》读书笔记(一)    
if(buff[n-1]=='\n')n--;
《UNIX网络编程 卷2》读书笔记(一)    snprintf(command,
sizeof(command),"cat %s",buff);//构造命令字
《UNIX网络编程 卷2》读书笔记(一)
    fp = popen(command,"r");//创建管道并启动另一个进程
《UNIX网络编程 卷2》读书笔记(一)
    while(fgets(buff,MAXLINE,fp)!=NULL)
《UNIX网络编程 卷2》读书笔记(一)        fputs(buff,stdout);
《UNIX网络编程 卷2》读书笔记(一)    pclose(fp);
《UNIX网络编程 卷2》读书笔记(一)    
return 0;
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)

7FIFO是一个单向数据流,有一个路径名与之关联,从而允许没有亲缘关系的进程访问同一个FIFO,也叫有名管道(named pipe),由函数mkfifo创建。

《UNIX网络编程 卷2》读书笔记(一)#include  " unpipc.h "
《UNIX网络编程 卷2》读书笔记(一)
#define  FIFO1 "tmp/fifo.1"
《UNIX网络编程 卷2》读书笔记(一)
#define  FIFO2 "tmp/fifo.2"
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)
void  server( int  readfd, int  writefd)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{//服务器 
《UNIX网络编程 卷2》读书笔记(一)
     int fd;
《UNIX网络编程 卷2》读书笔记(一)     ssize_t n;
《UNIX网络编程 卷2》读书笔记(一)     
char buff[MAXLINE+1];
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)     
if((n==read(readfd,buff,MAXLINE))>0)//从管道读入数据 
《UNIX网络编程 卷2》读书笔记(一)
         buff[n]='\0';
《UNIX网络编程 卷2》读书笔记(一)     
if((fd=open(buff,0_RDONLY))<0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)     
{//给客户端返回出错信息 
《UNIX网络编程 卷2》读书笔记(一)
         snprintf(buff+n,sizeof(buff)-n,"can't open,%s\n",strerror(errno));
《UNIX网络编程 卷2》读书笔记(一)         n 
= strlen(buff);
《UNIX网络编程 卷2》读书笔记(一)         write(writefd,buff,n);
《UNIX网络编程 卷2》读书笔记(一)     }

《UNIX网络编程 卷2》读书笔记(一)     
else
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)     
{
《UNIX网络编程 卷2》读书笔记(一)          
while((n=read(fd,huff,MAXLINE))>0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)          
{//给客户端返回文件内容 
《UNIX网络编程 卷2》读书笔记(一)
              write(writefd,buff,n);
《UNIX网络编程 卷2》读书笔记(一)          }

《UNIX网络编程 卷2》读书笔记(一)          close(fd);
《UNIX网络编程 卷2》读书笔记(一)     }
    
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)
int  main( int  argc, char **  argv)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)    
int readfd,writefd;
《UNIX网络编程 卷2》读书笔记(一)    pid_t childpid;
《UNIX网络编程 卷2》读书笔记(一)    
//创建两个有名管道 
《UNIX网络编程 卷2》读书笔记(一)
    mkfifo(FIFO1,FILE_MODE);
《UNIX网络编程 卷2》读书笔记(一)    mkfifo(FIFO2,FILE_MODE);
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)    readfd 
= open(FIFO1,O_RDONLY,0);
《UNIX网络编程 卷2》读书笔记(一)    writefd 
= open(FIFO2,O_WRONLY,0);
《UNIX网络编程 卷2》读书笔记(一)    server(readfd,writefd);
《UNIX网络编程 卷2》读书笔记(一)    
return 0;
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)
void  client( int  readfd, int  writefd)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{//客户 
《UNIX网络编程 卷2》读书笔记(一)
     size_t len;
《UNIX网络编程 卷2》读书笔记(一)     ssize_t n;
《UNIX网络编程 卷2》读书笔记(一)     
char buff[MAXLINE];
《UNIX网络编程 卷2》读书笔记(一)     fgets(buff,MAXLINE,stdin);
//读入路径名
《UNIX网络编程 卷2》读书笔记(一)
     len = strlen(buff);
《UNIX网络编程 卷2》读书笔记(一)     
if(buff[len-1]=='\n')//去掉结尾处的行符 
《UNIX网络编程 卷2》读书笔记(一)
        len--;
《UNIX网络编程 卷2》读书笔记(一)     write(writefd,buff,len);
//写入管道  
《UNIX网络编程 卷2》读书笔记(一)
     while((n==read(readfd,buff,MAXLINE))>0)//从管道读入数据 
《UNIX网络编程 卷2》读书笔记(一)
         write(STDOU_FILENO,buff,n);//输出 
《UNIX网络编程 卷2》读书笔记(一)
      
《UNIX网络编程 卷2》读书笔记(一)}
 
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)
int  main( int  argc, char **  argv)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)    
int readfd,writefd;
《UNIX网络编程 卷2》读书笔记(一)    pid_t childpid;
《UNIX网络编程 卷2》读书笔记(一)    
//创建两个有名管道 
《UNIX网络编程 卷2》读书笔记(一)
    mkfifo(FIFO1,FILE_MODE);
《UNIX网络编程 卷2》读书笔记(一)    mkfifo(FIFO2,FILE_MODE);
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)    readfd 
= open(FIFO1,O_RDONLY,0);
《UNIX网络编程 卷2》读书笔记(一)    writefd 
= open(FIFO2,O_WRONLY,0);
《UNIX网络编程 卷2》读书笔记(一)    server(readfd,writefd);
《UNIX网络编程 卷2》读书笔记(一)    
《UNIX网络编程 卷2》读书笔记(一)    writefd 
= open(FIFO1,O_WRONLY,0);
《UNIX网络编程 卷2》读书笔记(一)    readfd 
= open(FIFO2,O_RDONLY,0);
《UNIX网络编程 卷2》读书笔记(一)    client(readfd,writefd);
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)    close(readfd);
《UNIX网络编程 卷2》读书笔记(一)    close(writefd);
《UNIX网络编程 卷2》读书笔记(一)    
//删除有名管道 
《UNIX网络编程 卷2》读书笔记(一)
    unlink(FIFO1);
《UNIX网络编程 卷2》读书笔记(一)    unlink(FIFO2);
《UNIX网络编程 卷2》读书笔记(一)    
return 0;
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)

8,能通过两种方式设置为非阻塞:

1)调用open时指定O_NONBLOCK标志。

2)若描述字已经打开,用fcntlenableO_NONBLOCK标志,对于管道来说,必须这样,因为它没有open调用,在pipe调用中也无法指定O_NONBLOCK标志,代码如下:

《UNIX网络编程 卷2》读书笔记(一)int  flags;
《UNIX网络编程 卷2》读书笔记(一)flags 
=  fcntl(fd,F_GETFL, 0 );
《UNIX网络编程 卷2》读书笔记(一)flags 
|=  O_NONBLOCK;
《UNIX网络编程 卷2》读书笔记(一)fcntl(fd,F_SETFL,flags);

9,单进程服务器,多客户端

服务器代码:

《UNIX网络编程 卷2》读书笔记(一)int  main( int  argc, char **  argv)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)    
int readfifo,writefifo,dummyfd,fd;
《UNIX网络编程 卷2》读书笔记(一)    
char *ptr,buff[MAXLINE],fifoname[MAXLINE];
《UNIX网络编程 卷2》读书笔记(一)    pid_t pid;
《UNIX网络编程 卷2》读书笔记(一)    ssize_t n;
《UNIX网络编程 卷2》读书笔记(一)    mkfifo(SERV_FIFO,FILE_MODE);
《UNIX网络编程 卷2》读书笔记(一)    readfifo 
= open(SERV_FIFO,O_RDONLY,0);//服务器的读管道 
《UNIX网络编程 卷2》读书笔记(一)
    dummyfd = open(SERV_FIFO,O_WRONLY,0);//写管道,没使用,开启为了防止服务器管道重复打开,关闭 
《UNIX网络编程 卷2》读书笔记(一)
    while((n=readline(readfifo,buff,MAXLINE))>0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)    
{
《UNIX网络编程 卷2》读书笔记(一)        
if(buff[n-1]=='\n')n--;
《UNIX网络编程 卷2》读书笔记(一)        buff[n] 
= '\0';
《UNIX网络编程 卷2》读书笔记(一)        
if((ptr=strchr(buff,''))==NULL)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)        
{
《UNIX网络编程 卷2》读书笔记(一)            err_msg(
"请求命令错误");
《UNIX网络编程 卷2》读书笔记(一)            
continue
《UNIX网络编程 卷2》读书笔记(一)        }

《UNIX网络编程 卷2》读书笔记(一)        
*ptr++ = 0;
《UNIX网络编程 卷2》读书笔记(一)        pid 
= atoi(buff);//获取客户端进程号 
《UNIX网络编程 卷2》读书笔记(一)
        snprintf(fifoname,sizeof(fifoname),"/tmp/fifo.%ld",(long)pid);
《UNIX网络编程 卷2》读书笔记(一)        writefifo 
= open(fifoname,O_WRONLY,0);//打开客户端管道的写端 
《UNIX网络编程 卷2》读书笔记(一)
        if(fd = open(ptr,O_RDONLY,0))<0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)        
{//读文件失败 
《UNIX网络编程 卷2》读书笔记(一)
           snprintf(buff+n,sizeof(buff)-n,"can't open,%s\n",strerror(errno));
《UNIX网络编程 卷2》读书笔记(一)           n 
= strlen(ptr);
《UNIX网络编程 卷2》读书笔记(一)           write(writefifo,ptr,n);
//往客户端管道写数据 
《UNIX网络编程 卷2》读书笔记(一)
           close(writefifo);
《UNIX网络编程 卷2》读书笔记(一)        }

《UNIX网络编程 卷2》读书笔记(一)        
else
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)        
{
《UNIX网络编程 卷2》读书笔记(一)            
while((n = read(fd,buff,MAXLINE))>0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)            
{
《UNIX网络编程 卷2》读书笔记(一)                write(writefifo,buff,n);
《UNIX网络编程 卷2》读书笔记(一)            }

《UNIX网络编程 卷2》读书笔记(一)            close(fd);
《UNIX网络编程 卷2》读书笔记(一)            close(writefifo);
《UNIX网络编程 卷2》读书笔记(一)        }

《UNIX网络编程 卷2》读书笔记(一)    }

《UNIX网络编程 卷2》读书笔记(一)    
return 0;
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)

客户端代码:

《UNIX网络编程 卷2》读书笔记(一)int  main( int  argc, char **  argv)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)    
int readfifo,writefifo;
《UNIX网络编程 卷2》读书笔记(一)    size_t len;
《UNIX网络编程 卷2》读书笔记(一)    ssize_t n;
《UNIX网络编程 卷2》读书笔记(一)    
char *ptr,buff[MAXLINE],fifoname[MAXLINE];
《UNIX网络编程 卷2》读书笔记(一)    pid_t pid;
《UNIX网络编程 卷2》读书笔记(一)    pid 
= getpid();//获取当前进程ID 
《UNIX网络编程 卷2》读书笔记(一)
    snprintf(fifoname,sizeof(fifoname),"/tmp/fifo.%ld",(long)pid);
《UNIX网络编程 卷2》读书笔记(一)    
《UNIX网络编程 卷2》读书笔记(一)    mkfifo(fifoname,FILE_MODE);
//创建客户端管道
《UNIX网络编程 卷2》读书笔记(一)
    snprintf(buff,sizeof(buff),"%ld",(long)pid);
《UNIX网络编程 卷2》读书笔记(一)    len  
= strlen(buff);
《UNIX网络编程 卷2》读书笔记(一)    ptr 
= buff+len;
《UNIX网络编程 卷2》读书笔记(一)    
//读入文件路径名 
《UNIX网络编程 卷2》读书笔记(一)
    fgets(ptr, MAXLINE-len,stdin);
《UNIX网络编程 卷2》读书笔记(一)    len 
= strlen(buff);
《UNIX网络编程 卷2》读书笔记(一)    writefifo 
= open(SERV_FIFO,O_WRONLY,0);//打开服务器的写管道 \
《UNIX网络编程 卷2》读书笔记(一)
    write(writefifo,buff,len);//给服务器传送指定格式的命令字
《UNIX网络编程 卷2》读书笔记(一)
    readfifo = open(fifoname,O_RDONLY,0);/打开客户端读管道
《UNIX网络编程 卷2》读书笔记(一)   
《UNIX网络编程 卷2》读书笔记(一)    
while((n=read(readfifo,buff,MAXLINE))>0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)    
{
《UNIX网络编程 卷2》读书笔记(一)        write(STDOUT_FILENO,buff,n);
//输出 
《UNIX网络编程 卷2》读书笔记(一)
    }

《UNIX网络编程 卷2》读书笔记(一)    close(readfifo);
//关闭读端
《UNIX网络编程 卷2》读书笔记(一)
    unlink(fifoname);//删除管道 
《UNIX网络编程 卷2》读书笔记(一)
    return 0;
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)

但是这个程序会导致DoS攻击,因为服务器会一直阻塞在对客户端FIFOopen调用中,若客户端不打开此FIFO来读,则服务器会一直阻塞,因此客户很容易通过阻止发送封包来使得服务器垮掉,解决办法有很多,可以一个客户一个进程,或一个客户一个线程,或使用进程池,或线程池。

10,UNIX默认的I/O模型是字节流模型,也就是不存在记录边界,一般有3种技巧来改造:

1)带内特殊终止序列:很多使用换行符来分隔每个消息,写入进程给每个消息加入一个换行符,读出进程每次读出一行,但缺点是分隔符要进行转义处理。如:FTP,SMTP等就使用一个回车后跟一个换行符来分隔记录。

2)显示长度:记录前加入其长度。

3)一次连接一个记录,通过关闭与对方的连接来指示一个记录结束,例如HTTP1.0

《UNIX网络编程 卷2》读书笔记(一)#include  " unpipc.h "
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)
#define  MAXMESGDATA (PIPE_BUF-2*sizeof(long))
《UNIX网络编程 卷2》读书笔记(一)
#define  MESGHDRSIZE (sizeof(struct mymesg)-MAXMESGDATA)
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)
struct  mymesg
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)   
long mesg_len;//消息长度 
《UNIX网络编程 卷2》读书笔记(一)
   long mesg_type;//消息类型 
《UNIX网络编程 卷2》读书笔记(一)
   long mesg_data[MAXMESGDATA];//数据域 
《UNIX网络编程 卷2》读书笔记(一)
}
;
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)size_t mesg_send(
int  fd, struct  mymesg *  mptr)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)   
return(write(fd,mptr,MESGHDRSIZE+mptr->mesg_len));
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)ssize_t mesg_recv(
int  fd, struct  mymesg *  mptr)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{
《UNIX网络编程 卷2》读书笔记(一)   size_t len;
《UNIX网络编程 卷2》读书笔记(一)   ssize_t n;
《UNIX网络编程 卷2》读书笔记(一)   
if((n = read(fd,mptr,MESGHDRSIZE))==0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)   
{
《UNIX网络编程 卷2》读书笔记(一)       
return 0;
《UNIX网络编程 卷2》读书笔记(一)   }

《UNIX网络编程 卷2》读书笔记(一)   
else if(n!= MESGHDRSIZE)
《UNIX网络编程 卷2》读书笔记(一)      err_quit(
"头部错误");
《UNIX网络编程 卷2》读书笔记(一)   
if((len = mptr->mesg_len)>0)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)   
{
《UNIX网络编程 卷2》读书笔记(一)      
if((n=read(fd,mptr->mesg_data,len))!=len)
《UNIX网络编程 卷2》读书笔记(一)         err_quit(
"数据错误"); 
《UNIX网络编程 卷2》读书笔记(一)   }
 
《UNIX网络编程 卷2》读书笔记(一)   
return len;
《UNIX网络编程 卷2》读书笔记(一)   
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)
void  client( int  readfd, int  writefd)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{//客户 
《UNIX网络编程 卷2》读书笔记(一)
     size_t len;
《UNIX网络编程 卷2》读书笔记(一)     ssize_t n;
《UNIX网络编程 卷2》读书笔记(一)     
struct mymesg mesg;
《UNIX网络编程 卷2》读书笔记(一)     
《UNIX网络编程 卷2》读书笔记(一)     
char buff[MAXLINE];
《UNIX网络编程 卷2》读书笔记(一)     fgets(mesg.mesg_data,MAXMESGDATA,stdin);
//读入路径名
《UNIX网络编程 卷2》读书笔记(一)
     len = strlen(mesg.mesg_data);
《UNIX网络编程 卷2》读书笔记(一)     
if(mesg.mesg_data[len-1]=='\n')//去掉结尾处的行符 
《UNIX网络编程 卷2》读书笔记(一)
        len--;
《UNIX网络编程 卷2》读书笔记(一)     mesg.mesg_len 
= len;
《UNIX网络编程 卷2》读书笔记(一)     mesg.mesg_type 
= 1;
《UNIX网络编程 卷2》读书笔记(一)     mesg_send(writefd,
&mesg);
《UNIX网络编程 卷2》读书笔记(一)     
while((n==mesg_recv(readfd,&mesg))>0)//从管道读入数据 
《UNIX网络编程 卷2》读书笔记(一)
         write(STDOU_FILENO,mesg.mesg_data,n);//输出 
《UNIX网络编程 卷2》读书笔记(一)
      
《UNIX网络编程 卷2》读书笔记(一)}
 
《UNIX网络编程 卷2》读书笔记(一)
void  server( int  readfd, int  writefd)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)
{//服务器 
《UNIX网络编程 卷2》读书笔记(一)
     int fd;
《UNIX网络编程 卷2》读书笔记(一)     ssize_t n;
《UNIX网络编程 卷2》读书笔记(一)     
char buff[MAXLINE+1];
《UNIX网络编程 卷2》读书笔记(一)     FIFL 
*fp;
《UNIX网络编程 卷2》读书笔记(一)     
struct mymesg mesg;
《UNIX网络编程 卷2》读书笔记(一)     mesg.mesg_type 
= 1;
《UNIX网络编程 卷2》读书笔记(一)     
《UNIX网络编程 卷2》读书笔记(一)
《UNIX网络编程 卷2》读书笔记(一)     
if((n==mesg_recv(readfd,&mesg))>0)//从管道读入数据 
《UNIX网络编程 卷2》读书笔记(一)
         mesg.mesg_data[n]='\0';
《UNIX网络编程 卷2》读书笔记(一)     
if((fd=fopen(mesg.mesg_data,"r"))==NULL)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)     
{//给客户端返回出错信息 
《UNIX网络编程 卷2》读书笔记(一)
         snprintf( mesg.mesg_data+n,sizeof( mesg.mesg_data)-n,"can't open,%s\n",strerror(errno));
《UNIX网络编程 卷2》读书笔记(一)          mesg.mesg_len 
= strlen( mesg.mesg_data);
《UNIX网络编程 卷2》读书笔记(一)         mesg_send(writefd, 
&mesg);
《UNIX网络编程 卷2》读书笔记(一)     }

《UNIX网络编程 卷2》读书笔记(一)     
else
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)     
{
《UNIX网络编程 卷2》读书笔记(一)          
while(fgets( mesg.mesg_data,MAXMESGDATA,fp))!=NULL)
《UNIX网络编程 卷2》读书笔记(一)《UNIX网络编程 卷2》读书笔记(一)          
{//给客户端返回文件内容 
《UNIX网络编程 卷2》读书笔记(一)
              mesg.mesg_len = strlen(mesg.mesg_data);
《UNIX网络编程 卷2》读书笔记(一)              mesg_send(writefd,
&mesg);
《UNIX网络编程 卷2》读书笔记(一)          }

《UNIX网络编程 卷2》读书笔记(一)          fclose(fp);
《UNIX网络编程 卷2》读书笔记(一)     }
  
《UNIX网络编程 卷2》读书笔记(一)     mesg.mesg_len 
= 0 ;
《UNIX网络编程 卷2》读书笔记(一)     mesg_send(writefd,
&mesg);  
《UNIX网络编程 卷2》读书笔记(一)}

《UNIX网络编程 卷2》读书笔记(一)