亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Unix > 正文

高級進程間通信之UNIX域套接字

2024-06-28 13:27:49
字體:
來源:轉載
供稿:網友
高級進程間通信之UNIX域套接字

UNIX域套接字用于在同一臺機器上運行的進程之間的通信。雖然因特網域套接字可用于同一目的,但UNIX域套接字的效率更高。UNIX域套接字僅僅復制數據;它們并不執行協議處理,不需要添加或刪除網絡報頭,無需計算檢驗和,不要產生順序號,無需發送確認報文。

UNIX域套接字提供流和數據報兩種接口。UNIX域數據報服務是可靠的,既不會丟失消息也不會傳遞出錯。UNIX域套接字是套接字和管道之間的混合物。為了創建一對非命名的、相互連接的UNIX域套接字,用戶可以使用它們面向網絡的域套接字接口,也可使用socketpair函數。

#include <sys/socket.h>int socketpair(int domain, int type, int PRotocol, int sockfd[2]);返回值:若成功則返回0,出錯則返回-1

雖然該接口具有足夠的一般性,socketpair可用于任意域,但操作系統通常僅對UNIX域提供支持。

實例:使用UNIX域套接字的s_pipe函數

程序清單17-6 s_pipe函數的套接字版本(創建一對相連接的UNIX域流套接字)

#include "apue.h"#include <sys/socket.h>/** Return a full-duplex "stream" pipe (a UNIX domain socket)* with the two file descriptors returned in fd[0] and fd[1].*/ints_pipe(int fd[2]){    return(socketpair(AF_UNIX, SOCK_STREAM, 0, fd));}

某些基于BSD的系統使用UNIX域套接字實現管道。但當調用pipe時,第一描述符的寫端和第二描述符的讀端都被關閉。為了得到全雙工管道,我們必須直接調用socketpair。

1、命名UNIX域套接字

雖然socketpair函數創建相互連接的一對套接字,但是每一個套接字都沒有名字。這意味著無關進程不能使用它們。

在http://www.CUOXin.com/nufangrensheng/p/3565402.html,我們學習了如何將一個地址綁定一因特網域套接字。恰如因特網域套接字一樣,我們也可以命名UNIX域套接字,并可將其用于告示服務。但是要注意的是,UNIX域套接字使用的地址格式不同于因特網域套接字。

套接字地址格式可能隨實現而變。UNIX域套接字的地址由sockaddr_un結構表示。在linux 2.4.22和Solaris 9中,sockaddr_un結構按下列形式定義在頭文件<sys/un.h>中。

struct sockaddr_un {    sa_family    sun_family;    /* AF_UNIX */    char         sun_path[108];    /* pathname */};

sockaddr_un結構的sun_path成員包含一路徑名。當我們將以地址綁定至UNIX域套接字時,系統用該路徑名創建一類型為S_IfsoCK的文件。

該文件僅用于向客戶進程告知套接字名字。該文件不能打開,也不能由應用程序用于通信。

如果當我們試圖綁定地址時,該文件已經存在,那么bind請求失敗。當關閉套接字時,并不自動刪除該文件,所以我們必須確保在應用程序終止前,對該文件執行解除鏈接操作。

實例

程序清單17-7 將一個地址綁定一UNIX域套接字

#include "apue.h"#include <sys/socket.h>#include <sys/un.h>intmain(void){    int            fd, size;    struct sockaddr_un    un;    un.sun_family = AF_UNIX;    strcpy(un.sun_path, "foo.socket");        if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)        err_sys("socket failed");    size = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);    if(bind(fd, (struct sockaddr *)&un, size) < 0)        err_sys("bind failed");    printf("UNIX domain socket bound/n");    exit(0);}

當運行此程序時,bind請求成功執行,但是如果第二次運行該程序,則出錯返回,其原因是該文件已經存在。在刪去該文件之前,程序清單17-7不會成功執行。

未命名

確定綁定地址長度的方法是,先確定sun_path成員在sockaddr_un結構中的偏移量,然后將此與路徑名長度(不包括終止null字符)相加。因為在sun_path之前的成員與實現相關,所以我們使用<stddef.h>頭文件中的offsetof宏計算sun_path成員從結構開始處的偏移量。如果查看<stddef.h>,則可見到類似于下列形式的定義:

#define offsetof(TYPE, MEMBER)    ((int)&((TYPE *)0)->MEMBER)

假定該結構從地址0開始,此表達式求得成員起始地址的整型值。

2、唯一連接

服務器進程可以使用標準bind、listen和accept函數,為客戶進程安排一個唯一的UNIX域連接(unique UNIX domain connection)??蛻暨M程使用connect與服務器進程聯系;服務器進程接受了connect請求后,在服務器進程和客戶進程之間就存在了唯一連接。這種風格的操作與我們在http://www.CUOXin.com/nufangrensheng/p/3567376.html中的程序清單16-4和程序清單16-5中所示的對因特網域套接字的操作相同。

程序清單17-8 UNIX域套接字的serv_listen函數

#include "apue.h"#include <sys/socket.h>#include <sys/un.h>#include <errno.h>#define    QLEN    10/** Create a server endpoint of a connection.* Return fd if all ok, <0 on error. */intserv_listen(const char *name){    int            fd, len, err, rval;    struct sockaddr_un    un;        /* create a UNIX domain stream socket */    if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)        return(-1);    unlink(name);    /* in case it already exists */    /* fill in socket address structure */    memset(&un, 0, sizeof(un));    un.sun_family = AF_UNIX;    strcpy(un.sun_path, name);    len = offsetof(struct sockaddr_un, sun_path) + strlen(name);    /* bind the name to the descriptor */    if(bind(fd, (struct sockaddr *)&un, len) < 0)    {        rval = -2;        goto errout;    }    if(listen(fd, QLEN) < 0)    /* tell kernel we're a server */    {        rval = -3;        goto errout;    }    return(fd);errout:    err = errno;    close(fd);    errno = err;    return(rval);}

首先,我們調用socket創建一個UNIX域套接字。然后將欲賦予套接字的眾所周知路徑名填入sockaddr_un結構。該結構是調用bind的參數。注意,我們不需要設置某些平臺提供的sun_len字段,操作系統用傳送給bind函數的地址長度設置該字段。

最后調用listen函數以通知內核進程該進程將作為服務器進程等待客戶進程的連接請求。當收到一個客戶進程的連接請求后,服務器進程調用serv_accept函數。

程序清單17-9 UNIX域套接字的serv_accept函數

#include "apue.h"#include <sys/socket.h>#include <sys/un.h>#include <time.h>#include <errno.h>#define STALE    30    /* client's name can't be older than this (sec) *//** Wait for a client connection  to arrive, and accept it.* We also obtain the client's usr ID from the pathname* that it must bind before calling us.* Returns new fd if all ok, <0 on error*/int serv_accept(int listenfd, uid_t *uidptr){    int                   clifd, len, err, rval;    time_t                staletime;    struct sockaddr_un    un;    struct stat           statbuf;        len = sizeof(un);    if((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0)        return(-1);    /* often errno=EINTR, if signal caught */    /* obtain the client's uid from its calling address */    len -= offsetof(struct sockaddr_un, sun_path);    /* len of pathname */    un.sun_path[len] = 0;    /* null terminate */    if(stat(un.sun_path, &statbuf) < 0)    {        rval = -2;        goto errout;    }#ifdef    S_ISSOCK    /* not defined fro SVR4 */    if(S_ISSOCK(statbuf.st_mode) == 0)    {        rval = -3;    /* not a socket */        goto errout;    }#endif    if((statbuf.st_mode & (S_IRWXG | S_IRWXO)) ||           (statbuf.st_mode & S_IRWXU) != S_IRWXU)    {        rval = -4;    /* is not rwx------ */        goto errout;    }        staletime = time(NULL) - STALE;    if(statbuf.st_atime < staletime ||       statbuf.st_ctime < staletime ||       statbuf.st_mtime < staletime)    {        rval = -5;    /* i-node is too old */            goto errout;    }        if(uidptr != NULL)        *uidptr = statbuf.st_uid;    /* return uid of caller */    unlink(un.sun_path);    /* we're done with pathname now */    return(clifd);errout:    err = errno;    close(clifd);    errno = err;    return(rval);    }

服務器進程在調用serv_accept中阻塞以等待一客戶進程調用cli_conn。從accept返回時,返回值是連接到客戶進程的嶄新的描述符。另外,accept函數也經由其第二個參數(指向sockaddr_un結構的指針)返回客戶進程賦予其套接字的路徑名(包含客戶進程ID的名字)。接著,程序在此路徑名結尾處填補null字符,然后調用stat函數。這使我們驗證該路徑名確實是一個套接字,其權限允許用戶-讀、用戶-寫及用戶-執行。我們也驗證與套接字相關聯的3個時間不比當前時間早30秒。(time函數參考http://www.CUOXin.com/nufangrensheng/p/3507715.html)。

如若通過了所有這些檢驗,則可認為客戶進程的身份(其有效用戶ID)是該套接字的所有者。

客戶進程調用cli_conn函數對聯向服務器進程的連接進行初始化。

程序清單17-10 用于UNIX域套接字的cli_conn函數

#include "apue.h"#include <sys/socket.h>#include <sys/un.h>#include <errno.h>#define CLI_PATH    "/var/tmp/"    /* +5 fro pid = 14 chars */#define CLI_PERM    S_IRWXU        /* rwx for user only *//** Create a client endpoint and connect to a server.* Returns fd if all ok, <0 on error. */int cli_conn(const char *name){    int            fd, len, err, rval;    struct sockaddr_un    un;        /* create a UNIX domain stream socket */    if((fd = socket(AF_UNIX, SOCK_STREM, 0)) < 0)        return(-1);    /* fill socket address structure with our address */    memset(&un, 0, sizeof(un));    un.sun_family = AF_UNIX;    sprintf(un.sun_path, "%s%05d", CLI_PATH, getpid());    len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);    unlink(un.sun_path);    /* in case it already exits */    if(bind(fd, (struct sockaddr *)&un, len) < 0)    {        rval = -2;        goto errout;    }    if(chmod(un.sun_path, CLI_PERM) < 0)    {        rval = -3;        goto errout;    }    /* fill socket address structure with server's address */    memset(&un, 0, sizeof(un));    un.sun_family = AF_UNIX;    strcpy(un.sun_path, name);    len = offsetof(struct sockaddr_un, sun_path) + strlen(name);        if(connect(fd, (struct sockaddr *)&un, len) < 0)    {        rval = -4;        goto errout;    }    return(fd);errout:    err = errno;    close(fd);    errno = err;    return(rval);    }

我們調用socket函數創建UNIX域套接字的客戶端進程,然后用客戶端進程專有的名字填入sockaddr_un結構。

我們不讓系統為我們選擇一個默認的地址,原因是這樣處理后,服務器進程不能區分各個客戶進程。于是,我們綁定我們自己的地址,在開發使用套接字的客戶端程序時通常并不采用這一步驟。

我們綁定的路徑名的最后5個字符來自客戶進程ID。我們調用unlink,以防該路徑名已經存在,然后,調用bind將名字賦予客戶進程套接字。這在文件系統中創建了一個套接字文件,所用的名字與被綁定的路徑名一樣。接著,調用chmod關閉除用戶-讀、用戶-寫以及用戶-執行以外的其他權限。在serv_accept中,服務器進程檢驗這些權限以及套接字用戶ID以驗證客戶進程的身份。

然后,我們必須填充另一個sockaddr_un結構,這次用的是服務器進程眾所周知的路徑名。最后,調用connect函數初始化與服務器進程的連接。

本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩精品在线观看网站| 国产精品美腿一区在线看| 亚洲国产精品999| 日韩av在线免播放器| 国产精品视频永久免费播放| 毛片精品免费在线观看| 国产精品国产自产拍高清av水多| 国产精品成人免费视频| 欧美日韩国产丝袜美女| 欧美一区二区三区艳史| 国产日韩在线亚洲字幕中文| 国产精品稀缺呦系列在线| 日韩av在线不卡| 欧美国产日韩一区二区| 亚洲第一网站男人都懂| 国产欧美日韩精品在线观看| 亚洲男人天堂手机在线| 午夜免费在线观看精品视频| 亚洲性线免费观看视频成熟| 中文字幕一区二区三区电影| 中文字幕免费国产精品| 91久久久国产精品| 欧美国产亚洲视频| 亚洲电影免费在线观看| 欧美综合激情网| 欧美日韩免费网站| 日韩av一区在线| 国产亚洲精品va在线观看| 91免费的视频在线播放| 韩日精品中文字幕| 欧美成人精品不卡视频在线观看| 日韩av在线免播放器| 狠狠躁夜夜躁人人爽超碰91| 欧美一区二区.| 97视频在线免费观看| 欧美成人sm免费视频| 欧美亚洲免费电影| 精品视频在线播放免| 中文字幕日韩欧美| 亚洲欧美国产另类| 亚洲人成伊人成综合网久久久| 欧美影院在线播放| 97超级碰碰碰| 欧美福利小视频| 日韩精品免费综合视频在线播放| 欧美国产极速在线| 成人在线激情视频| 狠狠躁夜夜躁人人爽超碰91| 欧美电影在线观看网站| 亚洲香蕉在线观看| 欧美黑人一区二区三区| 91综合免费在线| 亚洲精品成a人在线观看| 国产成人一区三区| 亚洲欧美在线第一页| 亚洲人成在线观看网站高清| 狠狠色噜噜狠狠狠狠97| 欧美性色视频在线| 欧美天天综合色影久久精品| 国产精品视频区1| 欧美高清无遮挡| 久久久久久国产| 中文字幕亚洲图片| 一区二区三区精品99久久| 国产精品白丝jk喷水视频一区| 亚洲激情小视频| 日韩精品视频免费| 亚洲精品小视频| 欧美夜福利tv在线| 成人97在线观看视频| 日韩欧美在线视频日韩欧美在线视频| 色爱精品视频一区| 欧美日韩中文字幕| 亚洲永久免费观看| 日韩成人在线网站| 青草热久免费精品视频| 激情成人在线视频| 91啪国产在线| 国产精品电影久久久久电影网| 欧美日韩ab片| 国产精品成人一区二区三区吃奶| xvideos国产精品| 国产精品久久一区| 亚洲免费人成在线视频观看| 亚洲女人天堂av| 久久91亚洲精品中文字幕| 亚洲乱码av中文一区二区| 日韩av网站大全| 热久久这里只有精品| 日韩中文字幕第一页| 欧美激情视频网址| 国产精品久久久久久久久久尿| 欧美极品欧美精品欧美视频| 国模视频一区二区| 一本一本久久a久久精品综合小说| 欧美激情视频一区二区三区不卡| 中文字幕成人精品久久不卡| 伊人久久大香线蕉av一区二区| 成人疯狂猛交xxx| 91成人在线播放| 亚洲日本欧美中文幕| 懂色av中文一区二区三区天美| 福利一区福利二区微拍刺激| 欧美成人中文字幕在线| 欧美二区在线播放| 91精品视频在线播放| 日韩女优人人人人射在线视频| 色哟哟亚洲精品一区二区| 欧美国产激情18| 亚洲丝袜av一区| 91九色在线视频| 久久影院资源站| 亚洲国产日韩欧美在线99| 国产精品白嫩美女在线观看| 欧美性猛交丰臀xxxxx网站| 91久久嫩草影院一区二区| 日韩欧美成人免费视频| 国产精品久久久久久久av电影| 国产剧情日韩欧美| 日韩女在线观看| 亚洲国产天堂网精品网站| 日韩视频精品在线| 欧美另类极品videosbest最新版本| 欧美日韩一区二区三区| 成人福利视频在线观看| 色悠久久久久综合先锋影音下载| 国内精品久久久久久久久| 98精品国产自产在线观看| 三级精品视频久久久久| 2021久久精品国产99国产精品| 欧美在线精品免播放器视频| 国产欧美日韩中文字幕在线| 精品久久香蕉国产线看观看gif| 日韩视频免费中文字幕| 国产精品免费在线免费| 日韩成人在线免费观看| 亚洲自拍欧美另类| 国产精品a久久久久久| 亚洲一区二区久久久| 国产精品久久久久久久久久久新郎| 色99之美女主播在线视频| 国产精品永久在线| 中文字幕久久久| 欧美激情精品久久久久久大尺度| 69精品小视频| 8050国产精品久久久久久| 日韩精品欧美国产精品忘忧草| 欧美亚洲国产视频小说| 国产在线播放91| 久久亚洲精品中文字幕冲田杏梨| 精品国内产的精品视频在线观看| 亚洲国产精品久久久| 久久久久久久久久久免费精品| 久久综合网hezyo| 高清在线视频日韩欧美| 91在线精品视频| 欧美性生交xxxxx久久久| 粉嫩老牛aⅴ一区二区三区| 日韩精品在线观看视频| 国产ts一区二区| 一个色综合导航| 日韩综合视频在线观看| 中文字幕精品在线| 激情亚洲一区二区三区四区|