注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

itoedr的it学苑

记录从IT文盲学到专家的历程

 
 
 

日志

 
 

"Unix域套接字"应用初步理解  

2014-08-17 21:24:06|  分类: 现代编程方法 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

*****************************************

socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。 UNIX域套接字与TCP套接字相比较,在同一台主机的传输速度前者是后者的两倍。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯 设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIXDomain Socket也是可靠的,消息既不会丢失也不会顺序错乱。

使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。

UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP地址加端口 号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存 在,则bind()错误返回。

#define UNIX_PATH_MAX    108

struct sockaddr_un {
sa_family_tsun_family;               /* AF_UNIX */
charsun_path[UNIX_PATH_MAX];  /* pathname */
};


*************************************

UNIX 域套接字以 UNIX 路径命名。例如,可以将套接字命名为/tmp/foo。UNIX 域套接字只在一台主机上的进程之间通信。UNIX 域中的套接字不会被视为网络协议的一部分,因为它们只用于在一台主机上的进程之间通信。

套接字类型定义用户可见的通信属性。Internet 域套接字提供对 TCP/IP 传输协议的访问。Internet 域由值AF_INET标识。套接字仅与同一域中的套接字交换数据。

 创建套接字socket(3SOCKET)
调用创建指定系列和指定类型的套接字。
s = socket(family, type, protocol);
如果未指定协议(值0),则系统将选择支持所需套接字类型的协议。将返回套接字句柄(文件描述符)。

系列由 sys/socket.h中定义的一个常量指定。名为AF_suite的常量指定要在解释名称时使用的地址格式。
下面创建在同一计算机内部使用的数据报套接字:

  s = socket(AF_UNIX, SOCK_DGRAM, 0);
在大多数情况下,请将protocol参数设置为0(即缺省协议)。

本地名称绑定创建套接字时不带名称。只有在套接字绑定到地址之后,远程进程才能引用此套接字。通信进程通过地址连接。

 在 UNIX 系列中,连接通常包括一个或两个路径名。
UNIX 系列套接字无需始终绑定到名称。如果它们绑定到名称,则从不会存在绑定的重复排序组(如local pathname或foreign pathname)。路径名不能涉及现有文件。

通过bind(3SOCKET)调用,进程可以指定套接字的本地地址。
这样会创建local pathname排序组,而connect(3SOCKET)和accept(3SOCKET)通过添加地址的远程部分来完成套接字的关联。可以按如下方式使用bind(3SOCKET):
bind (s, name, namelen);
套接字句柄为s。绑定名称是由支持协议解释的字节字符串。

UNIX 系列名称包含一个路径名和一个系列。本示例说明将名称/tmp/foo绑定到 UNIX 系列套接字.

      Unix域套接字是通过套接字API实现的简单的协议族。实际上它并不代表一个网络协议;它只能连接到同一台机器上的套接字。它提供了灵活的IPC机制。它的地址是它所在的文件系统的路径名,创建之后套接字就和路径名绑定在一起。用来表示Unix域地址的套接字文件能够使用stat()但是不能通过open()打开,而且应该使用套接字API对它进行操作。

Unix域套接字是面向连接的,每个套接字的连接都建立了一个新的通讯信道。服务器可能同时处理许多连接,但对于每个连接都有不同的文件描述符。这个属性使Unix域套接字能够比命名管道更好的适应IPC任务。

.

在一个终端运行服务器,然后在另一个终端(在相同目录下)运行客户端。当从客户端输入一行时,数据将通过套接字送到服务器。当退出客户端,服务器将 等待另外一个连接。还可以通过客户端程序的重定向输入来传送文件,cat uclient.c | ./uclient ./uclient < uclient.c

服务器程序userver.c

/* userver.c - Simple Unix Domain Socket server */

/* Waits for a connection on the ./sample-socket Unix domain
   socket. Once a connection has been established, copy data
   from the socket to stdout until the other end closes the
   connection, and then wait for another connection to the
   socket. */

#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include "sockutil.h"          /* some utility functions */

int main(void) {
    struct sockaddr_un address;
    int sock, conn;
    size_t addrLength;

    if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        die("socket");

    /* Remove any preexisting socket (or other file) */
    unlink("./sample-socket");

    address.sun_family = AF_UNIX;       /* Unix domain socket */
    strcpy(address.sun_path, "./sample-socket");

    /* The total length of the address includes the sun_family
       element */
   
addrLength = sizeof(address.sun_family) +
                 strlen(address.sun_path);

    if (bind(sock, (struct sockaddr *) &address, addrLength))
        die("bind");

    if (listen(sock, 5))
        die("listen");

    while ((conn = accept(sock, (struct sockaddr *) &address,
                          &addrLength)
) >= 0) {
        printf("---- getting data\n");
        copyData(conn, 1);
        printf("---- done\n");
       
close(conn);
    }

    if (conn < 0)
        die("accept");
   
   
close(sock);
    return 0;
}

客户端程序uclient.c

/* uclient.c - Simple Unix Domain Socket client */

/* Connect to the ./sample-socket Unix domain socket, copy stdin
   into the socket, and then exit. */

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include "sockutil.h"          /* some utility functions */

int main(void) {
    struct sockaddr_un address;
    int sock;
    size_t addrLength;

    if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        die("socket");

    address.sun_family = AF_UNIX;    /* Unix domain socket */
    strcpy(address.sun_path, "./sample-socket");

    /* The total length of the address includes the sun_family
       element */
   
addrLength = sizeof(address.sun_family) +
                 strlen(address.sun_path);

    if (connect(sock, (struct sockaddr *) &address, addrLength))
        die("connect");

    copyData(0, sock);

    close(sock);
   
    return 0;
}


*********************************
另一个说明:
       Unix域套接字其实不是一个网络协议,所以只能在MySQL客户端和数据库实例在同一台服务器上的情况下使用。你可以在配置文件中指定套接字文件的路径,如-socket=/tmp/mysql.sock。
  评论这张
 
阅读(771)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018