linux 系統下使用socket進行本地進程間通訊

轉自:https://blog.csdn.net/baidu_24553027/article/details/54912724服務器

 

使用套接字除了能夠實現網絡間不一樣主機間的通訊外,還能夠實現同一主機的不一樣進程間的通訊,且創建的通訊是雙向的通訊。socket進程通訊與網絡通訊使用的是統一套接口,只是地址結構與某些參數不一樣。網絡

其主要流程以下:併發

 

代碼實現以下:

客戶端:dom

  1.  
    //client
  2.  
    #include<stdio.h>
  3.  
    #include<string.h>
  4.  
    #include<sys/types.h>
  5.  
    #include<sys/socket.h>
  6.  
    #include<sys/un.h>
  7.  
    #define UNIX_DOMAIN "/home/zhangmiaoling/test/socket/UNIX.domain"
  8.  
    int main(){
  9.  
    int connect_fd;
  10.  
    int ret;
  11.  
    char send_buff[1024];
  12.  
    int i;
  13.  
    static struct sockaddr_un srv_addr;
  14.  
    // creat unix socket
  15.  
    connect_fd=socket(PF_UNIX,SOCK_STREAM, 0);
  16.  
    if(connect_fd<0){
  17.  
    perror( "cannot creat socket");
  18.  
    return -1;
  19.  
    }
  20.  
    srv_addr.sun_family=AF_UNIX;
  21.  
    strcpy(srv_addr.sun_path,UNIX_DOMAIN);
  22.  
    //connect server
  23.  
    ret=connect(connect_fd,(struct sockaddr*)&srv_addr, sizeof(srv_addr));
  24.  
    if (ret<0){
  25.  
    perror( "cannot connect server");
  26.  
    close(connect_fd);
  27.  
    return -1;
  28.  
    }
  29.  
    memset(send_buff,0,1024);
  30.  
    strcpy(send_buff,"message from client");
  31.  
    //send info server
  32.  
    write(connect_fd,send_buff, sizeof(send_buff));
  33.  
    close(connect_fd);
  34.  
    return 0;
  35.  
    }

服務器端:
  1.  
    //server
  2.  
    #include<stdio.h>
  3.  
    #include<sys/socket.h>
  4.  
    #include<sys/types.h>
  5.  
    #include<sys/un.h>
  6.  
    #define UNIX_DOMAIN "/home/zhangmiaoling/test/socket/UNIX.domain"
  7.  
     
  8.  
    int main(){
  9.  
     
  10.  
    socklen_t clt_addr_len;
  11.  
    int listen_fd;
  12.  
    int com_fd;
  13.  
    int ret;
  14.  
    int i;
  15.  
    static char rcv_buff[1024];
  16.  
    int len;
  17.  
    struct sockaddr_un clt_addr;
  18.  
    struct sockaddr_un srv_addr;
  19.  
    listen_fd=socket(AF_UNIX,SOCK_STREAM, 0);
  20.  
    if(listen_fd<0){
  21.  
    perror( "connect creat communication socket");
  22.  
    }
  23.  
    // set srv_addr param
  24.  
    srv_addr.sun_family=AF_UNIX;
  25.  
    strncpy(srv_addr.sun_path,UNIX_DOMAIN,sizeof(srv_addr.sun_path)-1);
  26.  
    unlink(UNIX_DOMAIN);
  27.  
    //bind sockfd&addr
  28.  
    ret=bind(listen_fd,(struct sockaddr*)&srv_addr, sizeof(srv_addr));
  29.  
    if(ret<0){
  30.  
    perror( "cannot bind server socket");
  31.  
    close(listen_fd);
  32.  
    unlink(UNIX_DOMAIN);
  33.  
    return -1;
  34.  
    }
  35.  
    //listen sockfd
  36.  
    ret=listen(listen_fd, 1);
  37.  
    if(ret<0){
  38.  
    perror( "cannot listen sockfd");
  39.  
    close(listen_fd);
  40.  
    unlink(UNIX_DOMAIN);
  41.  
    return -1;
  42.  
    }
  43.  
    //have connect requst use accept
  44.  
    len= sizeof(clt_addr);
  45.  
    com_fd=accept(listen_fd,(struct sockaddr*)&clt_addr,&len);
  46.  
    if(com_fd<0){
  47.  
    perror( "cannot accept requst");
  48.  
    close(listen_fd);
  49.  
    unlink(UNIX_DOMAIN);
  50.  
    return -1;
  51.  
    }
  52.  
    //read and printf client send info
  53.  
    printf("\n******info********\n");
  54.  
    //for(i=0,i<4,i++){
  55.  
    for(i=0;i<4;i++){
  56.  
    memset(rcv_buff,0,1024);
  57.  
    int num = read(com_fd,rcv_buff,sizeof(rcv_buff));
  58.  
    printf("message from client %d : %s\n",num,rcv_buff);
  59.  
    }
  60.  
    close(com_fd);
  61.  
    close(listen_fd);
  62.  
    unlink(UNIX_DOMAIN);
  63.  
    return 0;
  64.  
     
  65.  
    }

一. 建立socketsocket

   建立socket,類型爲AF_LOCAL或AF_UNIX,表示用於進程通訊:函數

調用函數socket(),其原型以下:ui

int socket(int domain, int type, int protocol);spa

參數:.net

domain:指定協議族,對於本地套接字來講,值必須設置爲AF_UNIX枚舉值;線程

type:指定套接字類型,能夠被設置爲SOCK_STREAM(流式套接字)活SOCK_DGRAM(數據報式套接字)

protocol:指定具體的協議,應被設置爲0

返回值爲生成的套接字描述符。

對於本地套接字來講,流式套接字(SOCK_STREAM)是一個有順序的、可靠的雙向字節流,至關於在本地進程之間創建起一條數據通道;數據報式套接字(SOCK_DGRAM)至關於單純的發送消息,在進程通訊過程當中,理論上可能會有信息丟失、複製或者不按前後次序到達的狀況,但因爲其在本地通訊,不經過外界網絡,這些狀況出現的機率很小。

二. 設置socket參數

   SOCK_STREAM式本地套接字的通訊雙方均須要有本地地址,其中服務器端的本地地址須要明確指定,指定方法是使用struct sockaddr_un類型的變量

struct sockaddr_un{

  sa_family_t    sun_family;        // AF_UNIX

  char    sun_path[UNIX_PATH_MAX];  // 路徑名

}

三. 綁定

    綁定要使用 bind 系統調用,其原形以下:    

int bind(int socket, const struct sockaddr *address, size_t address_len);

參數

socket:服務端套接字描述符

address:須要綁定的服務端本地地址

address_len:本地地址的字節長度

 

四. 監聽

    服務器端套接字建立完畢並賦予本地地址值(名稱,本例中爲CAN_SERVICE)後,須要進行監聽,等待客戶端鏈接並處理請求,監聽使用 listen 系統調用,接受客戶端鏈接使用accept系統調用,它們的原形以下:
int listen(int socket, int backlog);
int accept(int socket, struct sockaddr *address, size_t *address_len);
參數

socket:表示服務器端的套接字描述符;

backlog 表示排隊鏈接隊列的長度(如有多個客戶端同時鏈接,則須要進行排隊);

address 表示當前鏈接客戶端的本地地址,該參數爲輸出參數,是客戶端傳遞過來的關於自身的信息;

address_len 表示當前鏈接客戶端本地地址的字節長度,這個參數既是輸入參數,又是輸出參數。實現監聽、接受和處理。

五. 鏈接

    客戶端須要socket系統調用connect()鏈接到服務端,其函數原型以下:

int connect(int socket, const struct sockaddr *address, size_t address_len);
參數

socket:客戶端的套接字描述符

address:當前客戶端的本地地址,是一個 struct sockaddr_un 類型的變量

address_len:表示本地地址的字節長度

五. 數據交互

    不管客戶端仍是服務器,都要和對方進行數據上的交互。一個進程扮演客戶端的角色,另一個進程扮演服務器的角色,兩個進程之間相互發送接收數據,這就是基於本地套接字的進程通訊。

    循環讀取客戶端發送的消息,當客戶端沒有發送數據時會阻塞直到有數據到來。若是想要多個鏈接併發處理,須要建立線程,將每一個鏈接交給相應的線程併發處理。接收到數據後,進行相應的處理,將結果返回給客戶端。發送和接收數據要使用 write 和 read 系統調用,它們的原形爲:int read(int socket, char *buffer, size_t len);int write(int socket, char *buffer, size_t len);

相關文章
相關標籤/搜索