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

首頁 > 服務器 > Linux服務器 > 正文

Linux進程間通信方式之socket使用實例

2024-09-05 23:04:18
字體:
來源:轉載
供稿:網友

套接字是一種通信機制,憑借這種機制,客戶/服務器系統的開發工作既可以在本地單機上進行,也可以跨網絡進行。
套接字的特性有三個屬性確定,它們是:域(domain),類型(type),和協議(protocol)。套接字還用地址作為它的名字。地址的格式隨域(又被稱為協議族,protocol family)的不同而不同。每個協議族又可以使用一個或多個地址族定義地址格式。

1.套接字的域

域指定套接字通信中使用的網絡介質。最常見的套接字域是AF_INET,它是指Internet網絡,許多Linux局域網使用的都是該網絡,當然,因特網自身用的也是它。其底層的協議——網際協議(IP)只有一個地址族,它使用一種特定的方式來指定網絡中的計算機,即IP地址。

在計算機系統內部,端口通過分配一個唯一的16位的整數來表示,在系統外部,則需要通過IP地址和端口號的組合來確定。

2.套接字類型

流套接字(在某些方面類似域標準的輸入/輸出流)提供的是一個有序,可靠,雙向字節流的連接。

流套接字由類型SOCK_STREAM指定,它們是在AF_INET域中通過TCP/IP連接實現的。他們也是AF_UNIX域中常見的套接字類型。

數據包套接字

與流套接字相反,由類型SOCK_DGRAM指定的數據包套接字不建立和維持一個連接。它對可以發送的數據包的長度有限制。數據報作為一個單獨的網絡消息被傳輸,它可能會丟失,復制或亂序到達。

數據報套接字實在AF_INET域中通過UDP/IP連接實現,它提供的是一種無需的不可靠服務。

3.套接字協議

只要底層的傳輸機制允許不止一個協議來提供要求的套接字類型,我們就可以為套接字選擇一個特定的協議。

先上一個代碼

服務端:

//s_unix.c #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h>  #define UNIX_DOMAIN "/tmp/UNIX.domain" int main(void) {   socklen_t clt_addr_len;   int listen_fd;   int com_fd;   int ret;   int i;   static char recv_buf[1024];    int len;   struct sockaddr_un clt_addr;   struct sockaddr_un srv_addr;   listen_fd=socket(PF_UNIX,SOCK_STREAM,0);   if(listen_fd<0)   {     perror("cannot create communication socket");     return 1;   }    //set server addr_param   srv_addr.sun_family=AF_UNIX;   strncpy(srv_addr.sun_path,UNIX_DOMAIN,sizeof(srv_addr.sun_path)-1);   unlink(UNIX_DOMAIN);   //bind sockfd & addr   ret=bind(listen_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));   if(ret==-1)   {     perror("cannot bind server socket");     close(listen_fd);     unlink(UNIX_DOMAIN);     return 1;   }   //listen sockfd    ret=listen(listen_fd,1);   if(ret==-1)   {     perror("cannot listen the client connect request");     close(listen_fd);     unlink(UNIX_DOMAIN);     return 1;   }   //have connect request use accept   len=sizeof(clt_addr);   com_fd=accept(listen_fd,(struct sockaddr*)&clt_addr,&len);   if(com_fd<0)   {     perror("cannot accept client connect request");     close(listen_fd);     unlink(UNIX_DOMAIN);     return 1;   }   //read and printf sent client info   printf("/n=====info=====/n");   for(i=0;i<4;i++)   {     memset(recv_buf,0,1024);     int num=read(com_fd,recv_buf,sizeof(recv_buf));     printf("Message from client (%d)) :%s/n",num,recv_buf);    }   close(com_fd);   close(listen_fd);   unlink(UNIX_DOMAIN);   return 0; } 

客戶端:

//c_unix.c#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#define UNIX_DOMAIN "/tmp/UNIX.domain"int main(void){  int connect_fd;  int ret;  char snd_buf[1024];  int i;  static struct sockaddr_un srv_addr;//creat unix socket  connect_fd=socket(PF_UNIX,SOCK_STREAM,0);  if(connect_fd<0)  {    perror("cannot create communication socket");    return 1;  }    srv_addr.sun_family=AF_UNIX;  strcpy(srv_addr.sun_path,UNIX_DOMAIN);//connect server  ret=connect(connect_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));  if(ret==-1)  {    perror("cannot connect to the server");    close(connect_fd);    return 1;  }  memset(snd_buf,0,1024);  strcpy(snd_buf,"message from client");//send info server  for(i=0;i<4;i++)    write(connect_fd,snd_buf,sizeof(snd_buf));  close(connect_fd);  return 0;}

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

一、創建socket流程

(1)創建socket,類型為AF_LOCAL或AF_UNIX,表示用于進程通信:

創建套接字需要使用 socket 系統調用,其原型如下:

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

其中,domain 參數指定協議族,對于本地套接字來說,其值須被置為 AF_UNIX 枚舉值;type 參數指定套接字類型,protocol 參數指定具體協議;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];    /* 路徑名 */};

這里面有一個很關鍵的東西,socket進程通信命名方式有兩種。一是普通的命名,socket會根據此命名創建一個同名的socket文件,客戶端連接的時候通過讀取該socket文件連接到socket服務端。這種方式的弊端是服務端必須對socket文件的路徑具備寫權限,客戶端必須知道socket文件路徑,且必須對該路徑有讀權限。

另外一種命名方式是抽象命名空間,這種方式不需要創建socket文件,只需要命名一個全局名字,即可讓客戶端根據此名字進行連接。后者的實現過程與前者的差別是,后者在對地址結構成員sun_path數組賦值的時候,必須把第一個字節置0,即sun_path[0] = 0,下面用代碼說明:

第一種方式:

//name the server socket 	server_addr.sun_family = AF_UNIX;	strcpy(server_addr.sun_path,"/tmp/UNIX.domain");	server_len = sizeof(struct sockaddr_un);	client_len = server_len;

第二種方式:

#define SERVER_NAME @socket_server 
//name the socket   server_addr.sun_family = AF_UNIX;   strcpy(server_addr.sun_path, SERVER_NAME);   server_addr.sun_path[0]=0;   //server_len = sizeof(server_addr);   server_len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);

其中,offsetof函數在#include <stddef.h>頭文件中定義。因第二種方式的首字節置0,我們可以在命名字符串SERVER_NAME前添加一個占位字符串,例如:

#define SERVER_NAME @socket_server  

前面的@符號就表示占位符,不算為實際名稱。

提示:客戶端連接服務器的時候,必須與服務端的命名方式相同,即如果服務端是普通命名方式,客戶端的地址也必須是普通命名方式;如果服務端是抽象命名方式,客戶端的地址也必須是抽象命名方式。

三、綁定

SOCK_STREAM 式本地套接字的通信雙方均需要具有本地地址,其中服務器端的本地地址需要明確指定,指定方法是使用 struct sockaddr_un 類型的變量,將相應字段賦值,再將其綁定在創建的服務器套接字上,綁定要使用 bind 系統調用,其原形如下:

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

其中 socket表示服務器端的套接字描述符,address 表示需要綁定的本地地址,是一個 struct sockaddr_un 類型的變量,address_len 表示該本地地址的字節長度。實現服務器端地址指定功能的代碼如下(假設服務器端已經通過上文所述的 socket 系統調用創建了套接字,server_sockfd 為其套接字描述符):

struct sockaddr_un server_address;server_address.sun_family = AF_UNIX;strcpy(server_address.sun_path, "Server Socket");bind(server_sockfd, (struct sockaddr*)&server_address, sizeof(server_address));

客戶端的本地地址不用顯式指定,只需能連接到服務器端即可,因此,客戶端的 struct sockaddr_un 類型變量需要根據服務器的設置情況來設置,代碼如下(假設客戶端已經通過上文所述的 socket 系統調用創建了套接字,client_sockfd 為其套接字描述符):

struct sockaddr_un client_address;client_address.sun_family = AF_UNIX;strcpy(client_address.sun_path, "Server Socket");

四、監聽

服務器端套接字創建完畢并賦予本地地址值(名稱,本例中為Server Socket)后,需要進行監聽,等待客戶端連接并處理請求,監聽使用 listen 系統調用,接受客戶端連接使用accept系統調用,它們的原形如下:

int listen(int socket, int backlog);int accept(int socket, struct sockaddr *address, size_t *address_len);

其中 socket 表示服務器端的套接字描述符;backlog 表示排隊連接隊列的長度(若有多個客戶端同時連接,則需要進行排隊);address 表示當前連接客戶端的本地地址,該參數為輸出參數,是客戶端傳遞過來的關于自身的信息;address_len 表示當前連接客戶端本地地址的字節長度,這個參數既是輸入參數,又是輸出參數。實現監聽、接受和處理的代碼如下:

#define MAX_CONNECTION_NUMBER 10int server_client_length, server_client_sockfd;struct sockaddr_un server_client_address;listen(server_sockfd, MAX_CONNECTION_NUMBER);while(1){  // ...... (some process code)  server_client_length?。健izeof(server_client_address);  server_client_sockfd = accept(server_sockfd, (struct sockaddr*)&server_client_address, &server_client_length);  // ...... (some process code)}

這里使用死循環的原因是服務器是一個不斷提供服務的實體,它需要不間斷的進行監聽、接受并處理連接,本例中,每個連接只能進行串行處理,即一個連接處理完后,才能進行后續連接的處理。如果想要多個連接并發處理,則需要創建線程,將每個連接交給相應的線程并發處理。

客戶端套接字創建完畢并賦予本地地址值后,需要連接到服務器端進行通信,讓服務器端為其提供處理服務。對于 SOCK_STREAM 類型的流式套接字,需要客戶端與服務器之間進行連接方可使用。連接要使用 connect 系統調用,其原形為

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

其中socket為客戶端的套接字描述符,address表示當前客戶端的本地地址,是一個 struct sockaddr_un 類型的變量,address_len 表示本地地址的字節長度。實現連接的代碼如下:

connect(client_sockfd, (struct sockaddr*)&client_address, sizeof(client_address));

無論客戶端還是服務器,都要和對方進行數據上的交互,這種交互也正是我們進程通信的主題。一個進程扮演客戶端的角色,另外一個進程扮演服務器的角色,兩個進程之間相互發送接收數據,這就是基于本地套接字的進程通信。發送和接收數據要使用 write 和 read 系統調用,它們的原形為:

int read(int socket, char *buffer, size_t len);int write(int socket, char *buffer, size_t len);

其中 socket 為套接字描述符;len 為需要發送或需要接收的數據長度;對于 read 系統調用,buffer 是用來存放接收數據的緩沖區,即接收來的數據存入其中,是一個輸出參數;對于 write 系統調用,buffer 用來存放需要發送出去的數據,即 buffer 內的數據被發送出去,是一個輸入參數;返回值為已經發送或接收的數據長度。例如客戶端要發送一個 "Hello" 字符串給服務器,則代碼如下:

char buffer[10] = "Hello";write(client_sockfd, buffer, strlen(buffer));

交互完成后,需要將連接斷開以節省資源,使用close系統調用,其原形為:

int close(int socket);

不多說了,直接使用,大家一定都會,呵呵!

上面所述的每個系統調用都有 -1 返回值,在調用不成功時,它們均會返回 -1,這個特性可以使得我們用 if - else 或異常處理語句來處理錯誤,為我們提供了很大的方便。

SOCK_DGRAM 數據報式本地套接字的應用場合很少,因為流式套接字在本地的連接時間可以忽略,所以效率并沒有提高,而且發送接收都需要攜帶對方的本地地址,因此很少甚至幾乎不使用。

與本地套接字相對應的是網絡套接字,可以用于在網絡上傳送數據,換言之,可實現不同機器上的進程通信過程。在 TCP/IP 協議中,IP 地址的首字節為 127 即代表本地,因此本地套接字通信可以使用 IP 地址為 127.x.x.x 的網絡套接字來實現。

總結

以上就是本文關于Linux進程間通信方式之socket使用實例的全部內容,希望對大家有所幫助。感謝朋友們對本站的支持。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品国产电影| 亚洲国产一区二区三区在线观看| 欧美视频13p| 国产成人小视频在线观看| 中文字幕久久久| 亚洲天堂网在线观看| 欧美黑人性猛交| 欧美亚洲视频在线看网址| 最近2019年好看中文字幕视频| 一区三区二区视频| 欧美日韩成人在线观看| 欧美国产亚洲精品久久久8v| 青青青国产精品一区二区| 久久这里只有精品99| 91色琪琪电影亚洲精品久久| 欧日韩在线观看| 久久久精品日本| 精品欧美aⅴ在线网站| 国产午夜精品全部视频播放| 国产在线拍偷自揄拍精品| 国产成人精品综合久久久| 国产精品v日韩精品| 国产精品视频白浆免费视频| 国产在线精品自拍| 日韩三级成人av网| 国产精品美女在线| 国产色婷婷国产综合在线理论片a| 亚洲一级黄色av| 91精品国产网站| 国语自产偷拍精品视频偷| 亚洲日韩欧美视频| 97久久精品国产| 日韩国产高清视频在线| www高清在线视频日韩欧美| 欧美在线视频免费播放| 国产精品夜间视频香蕉| 亚洲最大的av网站| 日韩免费观看在线观看| 亚洲成人在线视频播放| 色偷偷综合社区| 久久精品色欧美aⅴ一区二区| 狠狠综合久久av一区二区小说| 亚洲成人av资源网| 精品中文字幕在线| 成人xvideos免费视频| 久久久999国产| 欧美午夜精品久久久久久浪潮| 亚洲综合色激情五月| 欧美精品免费在线观看| 91久久夜色精品国产网站| 亚洲国产欧美久久| 亚洲国产精品女人久久久| 欧美国产精品日韩| 亚洲男人天堂手机在线| 国产亚洲人成a一在线v站| 亚洲图片制服诱惑| 国产精彩精品视频| 国产精品福利在线| 精品电影在线观看| 欧美精品精品精品精品免费| 欧美成人h版在线观看| 国产精品第一页在线| 亚洲激情在线视频| 国产日韩欧美日韩大片| 日韩hd视频在线观看| 亚洲精品国产美女| 日韩av影视综合网| 亚洲v日韩v综合v精品v| 欧美影院久久久| 国产成人精品999| 欧美精品在线免费| 久色乳综合思思在线视频| 欧美成人午夜激情视频| 国产成人精品免费久久久久| 国产综合在线视频| 国产精品日韩电影| 成人有码在线视频| 国产精品亚洲精品| 日韩欧美大尺度| 欧美日韩日本国产| 欧美一级黑人aaaaaaa做受| 日韩av黄色在线观看| 国产精品欧美日韩一区二区| 福利一区福利二区微拍刺激| 日韩亚洲精品电影| 欧美午夜片在线免费观看| 福利精品视频在线| 欧美成人免费观看| 成人国产精品日本在线| 日韩精品在线免费观看| 91网站在线免费观看| 自拍偷拍亚洲精品| 日韩高清人体午夜| 91av在线精品| 亚洲天堂免费视频| 日本免费在线精品| 欧美日韩国内自拍| 亚州av一区二区| 夜夜嗨av色综合久久久综合网| 久久精品99久久久久久久久| 国产97免费视| 亚洲自拍欧美色图| 国产一区二区三区四区福利| 国产欧美va欧美va香蕉在| 亚洲a在线观看| 精品国产一区二区三区四区在线观看| 91精品国产综合久久久久久蜜臀| 91美女福利视频高清| 亚洲欧洲国产精品| 日韩大陆毛片av| 亚洲免费高清视频| 国产精品美女久久久久久免费| 久热精品视频在线| 欧美激情第6页| 欧美日韩国产va另类| 国产欧美精品va在线观看| 欧美高清视频在线播放| 亚洲乱码av中文一区二区| 7777精品视频| 国产丝袜视频一区| 国产精品一区二区三| 日韩美女视频免费在线观看| 国产香蕉一区二区三区在线视频| 日韩国产一区三区| 91久久综合亚洲鲁鲁五月天| 国产精品免费一区二区三区都可以| 国产成人一区二区| 欧美综合国产精品久久丁香| 国产精品普通话| 国产精品91久久久久久| 日本精品视频在线| 日韩中文理论片| 国产精品午夜视频| 亚洲欧美日韩在线高清直播| 欧美日韩国内自拍| 久久久久中文字幕2018| 久久精品国产96久久久香蕉| 久久人人爽人人| 欧美孕妇毛茸茸xxxx| 久久久久久久国产精品视频| 国产欧美精品一区二区| 国产精品揄拍一区二区| 在线成人免费网站| 91精品在线播放| 91在线看www| 国产精品亚洲网站| 亚洲视频一区二区| 日韩av大片在线| 欧美性videos高清精品| 亚洲在线免费观看| 国产v综合ⅴ日韩v欧美大片| 正在播放欧美视频| 亚洲成色999久久网站| 久久av在线看| 国产做受69高潮| 亚洲欧美在线免费| www欧美日韩| 色播久久人人爽人人爽人人片视av| 亚洲人成欧美中文字幕| 欧美激情极品视频| 亚洲国产精品网站| 成人免费激情视频| 亚洲欧美综合区自拍另类| 国产日韩精品在线观看|