天天看點

linux socket程式設計(5):socket IPC

socket IPC與一般網絡通信一緻,也有兩種類型sock_stream 和sock_daram不同的地方在于:

1.網絡通信server端以IP/Port作為服務名,IPC則以socket檔案路徑名作為服務名,socket檔案與一般檔案不同,socket檔案是在程式運作時建立,而不能手動建立。

2.Domain不同,一個是AF_INET,一個是AF_UNIX;使用的位址結構不同,一個是sockaddr_in,一個是sockaddr_un. struct sockaddr_un{int sun_family;char sun_path[108];}

3.用戶端與伺服器一樣可以綁定一個檔案路徑,綁定之後會生成一個socket檔案。此檔案并沒有什麼作用,可以直接删除,通信不會受到影響。

//server端

#include <stdio.h>

#include <stdlib.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <stddef.h>

#include <unistd.h>

int bindSocket(char* servname)

{

    struct sockaddr_un usock;

    int ufd;

    memset(&usock,0,sizeof(sockaddr_un));

    usock.sun_family = AF_UNIX;

    strcpy(usock.sun_path,servname);

    if((ufd = socket(AF_UNIX,SOCK_STREAM,0)) < 0)

    {

        perror("socket() error!");

        exit(-1);

    }

    int len = offsetof(sockaddr_un,sun_path) + strlen(usock.sun_path);

    if(bind(ufd,(sockaddr*)&usock,len) < 0)

    {

        perror("bind() error!");

        exit(-1);

    }

    return ufd;

}

int acceptSocket(int ssock,sockaddr_un *un)

{

    int csock,len;

    len = sizeof(un); //這句話必須有,因為len是傳入傳出參數,在傳入時如果沒有指定大小,有可能傳入上次傳出參數值。

    if((csock = accept(ssock,(sockaddr*)un,(socklen_t*)&len)) < 0)

    {

        perror("accept() error!");

        exit(-1);

    }

    len -= offsetof(sockaddr_un,sun_path);

    un->sun_path[len] = 0;

    printf("client file:%s\n",un->sun_path);

    return csock;

}

int main(void)

{

    char servName[20];

    sprintf(servName,"server");

    int sfd = bindSocket(servName);

    if(listen(sfd,5) < 0)

    {

        perror("listen() error!");

        exit(-1);

    }

    struct sockaddr_un un;

    int cfd = acceptSocket(sfd,&un);

    char buf[100];

    int s = read(cfd,buf,sizeof(buf));

    write(STDOUT_FILENO,buf,s);

}

//用戶端

#include <stdio.h>

#include <sys/socket.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/un.h>

#include <stddef.h>

int cli_connect(const char *name)

{

    int len;

    struct sockaddr_un un;

    memset(&un,0,sizeof(un));

    un.sun_family = AF_UNIX;

    sprintf(un.sun_path,"client%05d",getpid());

    int cfd;

    if((cfd = socket(AF_UNIX,SOCK_STREAM,0)) < 0)

    {

        perror("socket() error");

        exit(-1);

    }

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

    if(bind(cfd,(sockaddr*)&un,len) < 0)

    {

        perror("bind() error");

        exit(-1);

    }

    memset(&un,0,sizeof(un));

    un.sun_family = AF_UNIX;

    sprintf(un.sun_path,name);

    len = offsetof(sockaddr_un,sun_path);

    len += strlen(un.sun_path);

    printf("%s\n",un.sun_path);   

 if(connect(cfd,(sockaddr*)&un,len) < 0)

    {

        perror("connect() error");

        exit(-1);

    }

    return cfd;

}

int main(void)

{

int cfd = cli_connect("qw/server");

char *buf = "hello world!";

if(write(cfd,buf,strlen(buf)) < 0)

perror("error");

return cfd;

}

繼續閱讀