日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

5高并发服务器:socket IPC

發布時間:2024/9/27 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 5高并发服务器:socket IPC 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  • socket IPC

  • socket API原本是為網絡通訊設計的,但后來在socket的框架上發展出一種IPC機制,就是UNIX Domain Socket。雖然網絡socket也可用于同一臺主機的進程間通訊(通過loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要經過網絡協議棧,不需要打包拆包、計算校驗和、維護序號和應答等,只是將應用層數據從一個進程拷貝到另一個進程。這是因為,IPC機制本質上是可靠的通訊,而網絡協議是為不可靠的通訊設計的。UNIX Domain Socket也提供面向流和面向數據包兩種API接口,類似于TCPUDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不會丟失也不會順序錯亂。

    UNIX Domain Socket是全雙工的,API接口語義豐富,相比其它IPC機制有明顯的優越性,目前已成為使用最廣泛的IPC機制,比如X Window服務器和GUI程序之間就是通過UNIX Domain Socket通訊的。

    使用UNIX DomainSocket的過程和網絡socket十分相似,也要先調用socket()創建一個socket文件描述符,address family指定為AF_UNIXtype可以選擇SOCK_DGRAMSOCK_STREAMprotocol參數仍然指定為0即可。

    UNIX Domain Socket與網絡socket編程最明顯的不同在于地址格式不同,用結構體sockaddr_un表示,網絡編程的socket地址是IP地址加端口號,而UNIX Domain Socket的地址是一個socket類型的文件在文件系統中的路徑,這個socket文件由bind()調用創建,如果調用bind()時該文件已存在,則bind()錯誤返回。

    ???以下程序將UNIXDomain socket綁定到一個地址。

    size =offsetof(struct sockaddr_un,sun_path) + strlen(un.sun_path);

    offsetof查看第二個參數在前者內的偏移量

    案例說明:

    server.c

    #include <stdlib.h>

    #include <stdio.h>

    #include <stddef.h>

    #include <sys/socket.h>

    #include <sys/un.h>

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <unistd.h>

    #include <errno.h>

    #include <ctype.h>

    ?

    #define QLEN 10

    /*

    ?* Create a server endpoint of a connection.

    ?* Returns fd if all OK, <0 on error.

    ?*/

    int serv_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);

    }

    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;

    ???}

    ???if (S_ISSOCK(statbuf.st_mode) == 0) {

    ???????rval = -3; /* not a socket */

    ???????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);

    }

    int main(void)

    {

    ???int lfd, cfd, n, i;

    ???uid_t cuid;

    ???char buf[1024];

    ???lfd = serv_listen("foo.socket");

    ???if (lfd < 0) {

    ???????switch (lfd) {

    ???????????case -3:perror("listen"); break;

    ???????????case -2:perror("bind"); break;

    ???????????case -1:perror("socket"); break;

    ???????}

    ???????exit(-1);

    ???}

    ???cfd = serv_accept(lfd, &cuid);

    ???if (cfd < 0) {

    ???????switch (cfd) {

    ???????????case -3:perror("not a socket"); break;

    ???????????case -2:perror("a bad filename"); break;

    ???????????case -1:perror("accept"); break;

    ???????}

    ???????exit(-1);

    ???}

    ???while (1) {

    r_again:

    ???????n = read(cfd, buf, 1024);

    ???????if (n == -1) {

    ???????????if (errno == EINTR)

    ???????????????goto r_again;

    ???????}

    ???????else if (n == 0) {

    ???????????printf("the other side has been closed.\n");

    ???????????break;

    ???????}

    ???????for (i = 0; i < n; i++)

    ???????????buf[i] = toupper(buf[i]);

    ???????write(cfd, buf, n);

    ???}

    ???close(cfd);

    ???close(lfd);

    ???return 0;

    }

    client.c

    #include <stdio.h>

    #include <stdlib.h>

    #include <stddef.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <unistd.h>

    #include <sys/socket.h>

    #include <sys/un.h>

    #include <errno.h>

    #define CLI_PATH "/var/tmp/" /* +5 for pid = 14 chars */

    /*

    ?* 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_STREAM, 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 exists */

    ???if (bind(fd, (struct sockaddr *)&un, len) < 0) {

    ???????rval = -2;

    ???????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);

    }

    int main(void)

    {

    ???int fd, n;

    ???char buf[1024];

    ???fd = cli_conn("foo.socket");

    ???if (fd < 0) {

    ???????switch (fd) {

    ???????????case -4:perror("connect"); break;

    ???????????case -3:perror("listen"); break;

    ???????????case -2:perror("bind"); break;

    ???????????case -1:perror("socket"); break;

    ???????}

    ???????exit(-1);

    ???}

    ???while (fgets(buf, sizeof(buf), stdin) != NULL) {

    ???????write(fd, buf, strlen(buf));

    ???????n = read(fd, buf, sizeof(buf));

    ???????write(STDOUT_FILENO, buf, n);

    ???}

    ???close(fd);

    ???return 0;

    }

    ?

    總結

    以上是生活随笔為你收集整理的5高并发服务器:socket IPC的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。