Linux网络编程读书笔记(9)

来源:互联网 发布:mac 查看隐藏文件夹 编辑:程序博客网 时间:2024/06/13 12:55

第十三章 UNIX域套接字和并发服务器的预创建技术

·UNIX域套接字

linux操作系统提供了一种UNIX域协议的进程间通信方式,它不能应用在网络中,能使用在本机两进程间的通信中。它能方便的向两个非亲属关系的进程间传递文件描述符,效果类似于在父子进程间传递一样。UNIX域套接字在和本地进程进行交互时候效率更高,因为它不需要处理网络异常可能。

 

地址结构:

struct sockaddr_un{

       short int sun_family;

       char sun_path[104];

};

使用示例:

listen_fd = socket(AF_UNIX,SOCK_STREAM,0);           //UNIX域套接字

serv_addr.sun_family = AF_UNIX;                        //UNIX域协议簇

strcpy(serv_addr.sun_path, “/tmp/myfile”);                  //创建绑定文件

unbind(serv_addr.sun_path);                             //先解除指定文件的绑定

ret = bind(listen_fd,(struct sockaddr*)&serv_addr,

strlen(serv_addr.sun_path)+sizeof(serv_add.sun_family);   //绑定指定文件路径

       listen(listen_fd, 倾听队列长度);

 

·使用sendmsgrecvmsg传递和接收文件描述符

       主要使用UNIX域套接字,sendmsgrecvmsg两个函数实现。在发送附加数据之前需要自己定义一个联合体。这样附加数据将在内存中置于struct cmsghdr结构之后,同cmsghdr相关宏定义才能正常工作。

示例代码:

void unix_send_fd(int unix_fd, int conn_fd)

{

       struct msghdr msg;

       struct iovec iov[1];

       char c;

       int ret;

       union{

              struct cmsghdr cm;

              char control[CMSG_SPACE(sizeof(int))];

       }control_un; //定义联合体,将附加数据置于struct cmsghdr结构之后

       struct cmsghdr *cmptr;

       //报文套接字使用字段,对于流类型套接字,地址域填为空。

       msg.msg_name = NULL;

       msg.msg_namelen = 0;

       //填写普通数据的缓冲区

       iov[0].iov_base = &c;

       iov[0].iov_len = 1;

       //执行普通数据缓冲区

       msg.msg_iov = iov;

       msg.msg_iovlen = 1;

       //设置附加数据的指针

       msg.msg_control = control_un.control;

       msg.msg_controllen = sizeof(control_un.control);

       //获取结构struct cmsghdr的指针

       cmptr = CMSG_FIRSTHDR(&msg);

       //获取该结构的长度

       cmptr->cmsg_len = CMSG_LEN(sizeof(int));

       //填写控制数据的层次

       cmptr->cmsg_level = SOL_SOCKET;

       //填写控制数据的类型

       cmptr->cmsg_type = SCM_RIGHTS;

       //填写控制数据的内容

       *(int*)CMSG_DATA(cmptr)=conn_fd;

       ret = sendmsg(unix_fd, &msg,0);

       if (ret < 0)

              error_proc();

       //接收就是上面逆向的过程,先预设接收缓冲,然后cmptr= CMSG_FIRSTHDR(&msg);

       //最后return *(int*)CMSG_DATA(cmptr);

}

 

·并发服务器的预创建技术

       预创建技术可以为并发服务器解决以下几个显著缺点:

       1 为新连接上的客户尽快提供服务,消除新建进程的时延

       2 不必为每个客户服务进程都需要建立/释放资源

       3 子进程重复利用率高

       4 通过传递文件描述符,对子进程动态管理

 

       UNIX套接字对

       int socketpari(int family, int type, int protocol, int sockfd[2]);

       //建立两个连接好的套接字对,可以像管道一样使用

       使用套接字和管道相比有“全双工、可以将文件描述符传递给任何进程”的优点

 

 

第十四章 原始套接字

·14.1 原始套接字

原始套接字的使用:

       1  ip_fd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); //只允许超级用户建立和使用

              //SOCK_RAW创建原始套接字,第三个参数是协议,可以使用0或其他

 

2         bindconnect函数对原始套接字的影响

原始套接字工作在传输层以下所以没有端口的概念。bind一个原始套接字的地址后,核心只把目的地址是该原始套接字的IP包发送给它,忽略其它。调用connect后,核心将传递源地址是connect地址的IP包给这个原始套接字。如果没有bindconnect原始套接字,核心将把所有协议匹配的IP包传递给它。

      

IP套接字选项

       getsockopt()函数:IP_TTL获取生存期,IP_HDRINCL自行填充IP包头(可伪造)

原始套接字的使用:

       1  ip_fd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); //只允许超级用户建立和使用

              //SOCK_RAW创建原始套接字,第三个参数是协议,可以使用0或其他

 

2         bindconnect函数对原始套接字的影响

原始套接字工作在传输层以下所以没有端口的概念。bind一个原始套接字的地址后,核心只把目的地址是该原始套接字的IP包发送给它,忽略其它。调用connect后,核心将传递源地址是connect地址的IP包给这个原始套接字。如果没有bindconnect原始套接字,核心将把所有协议匹配的IP包传递给它。

      

IP套接字选项

       getsockopt()函数:IP_TTL获取生存期,IP_HDRINCL自行填充IP包头(可伪造)