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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

UNIX再学习 -- 网络IPC:套接字

發布時間:2025/3/15 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UNIX再学习 -- 网络IPC:套接字 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、基本概念

1、編程接口

什么是伯克利套接字(Berkeley Socket)?

美國加利福尼亞大學比克利分校于 1983年發布 4.2 BSD Unix 系統。其中包含一套用 C 語言編寫的應用程序開發庫。該庫既可用于在同一臺計算機上實現進程間通信,也可用于在不同計算機上實現網絡通信。當時的 Unix 還受 AT&T 的專利保護,因此直到 1989 年,伯克利大學才能自由發布他們的操作系統和網絡庫,而后者即被稱為伯克利套接字應用編程接口(Berkeley Socker APIs)。 伯克利套接字接口的實現完全基于 TCP/IP 協議,因此它是構建一切互聯網應用的基石。幾乎所有現代操作系統都或多或少有一些源自伯克利套接字接口的實現。它已成為應用程序連接互聯網的標準接口。

什么是套接字?

套接字(socket)的本意是指電源插座,這里將其引申為一個基于 TPC/IP 協議可實現基本網絡通信功能的邏輯對象。 機器與機器的通信,或者進程與進程的通信,在這里都可以被抽象地看作是套接字與套接字的通信。 應用程序編寫者無需了解網絡協議的任何細節,更無需知曉系統內核和網絡設備的運作機制,只要把想發送的數據寫入套接字,或從套接字中讀取想接收的數據即可。 從這個意義上講,套接字就相當于一個文件描述符,而網絡就是一種特殊的文件,面向網絡的編程與面向文件的編程已沒有分別,而這恰恰是 unix 系統一切皆文件思想的又一例證。

什么是套接字的異構性?

如前所述,套接字是對 ISO/OSI 網絡協議模型中傳輸及其以下諸層的邏輯抽象,是對 TCP/IP 網絡通信協議的高級封裝,因此無論所依賴的是什么硬件,所運行的什么操作系統所使用的是什么編程語言,只要是基于套接字構建的應用程序,只要是在互聯網環境中通信,就不會存在任何障礙。

2、通信模式

單播模式

每個數據包發送單個目的主機,目的地址指明單個接收者。 服務器可以及時響應客戶機的請求。 服務器可以針對不同客戶的不同請求提供個性化的服務。 網絡中傳輸的信息量與請求該信息的用戶量成正比,當請求該信息的用戶量較大時,網絡中將出現多份內容相同的信息流,此時帶寬就成了限制傳輸質量的瓶頸。

廣播模式

一臺主機向網上的所有其它主機發送數據。 無需路徑選擇,設備簡單,維護方便,成本低廉。 服務器不用向每個客戶機單獨發送數據,流量負載極低。 無法針對具體客戶的具體要求,及時提供個性化的服務。 網絡無條件地復制和轉發每一臺主機產生的信息,所有的主機可以收到所有的信息,而不管是否需要,網絡資源利用率低,帶寬浪費嚴重。 禁止廣播包穿越路由器,防止在更大范圍內泛濫。

多播模式

網絡中的主機可以向路由器請求加入或退出某個組,路由器和交換機有選擇地復制和轉發數據,只將組內數據轉發給那些加入組的主機。 需要相同信息的客戶機只要加入同一個組即可共享同一份數據,降低了服務器和網絡的流量負載。 既能一次將數據傳輸給多個有需要的主機,又能保證不影響其他不需要的主機。 多播包可以穿越路由器,并在穿越中逐漸衰減。 缺乏糾錯機制,丟包錯包在所難免。

3、綁定與連接

如前所述,套接字是一個提供給程序員使用的邏輯對象,它表示對 ISO/OSI 網絡協議模型中傳輸層及其以下諸層的的抽象。但真正發送和接收數據的畢竟是那些實實在在的物理設備。這就需要在物理設備和邏輯對象之間建立一種關聯,使后續所有針對這個邏輯對象的操作,最終都能反映到實際的物理設備上。建立這種關聯關系的過程就叫做綁定。
綁定只是把套接字對象和一個代表自己的物理設備關聯起來。但為了實現通信還需要把自己的物理設備與對方的物理設備關聯起來。只有這樣才能建立一種以物理設備為媒介的,跨越不同進程甚至機器的,多個套接字對象之間的聯系。建立這種聯系的過程就叫做連接

二、常用函數

1、函數 socket:創建套接字

#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol); 返回值:成功返回套接字描述符,失敗返回 -1

(1)參數解析

domain:通信域,即地址族,可取以下值: ? ? AF_LOCAL/AF_UNIX ? 本地通信,即進程間通信 (重點) ? ? AF_INET ? ? ? ? ? ? ? ? ? ? ? 基于 IPv4 的網絡通信 ?(重點) ? ? AF_INET6 ? ? ? ? ? ? ? ? ? ? 基于 IPv6 的網絡通信 ? ? AF_PACKET ? ? ? ? ? ? ? ? ?基于底層包接口的網絡通信 type:套接字類型,可取以下值: ? ? SOCK_STREAM ? ? ? ??流式套接字,即使用 TCP 協議的套接字。有序的、可靠的、雙向的、面向連接的字節流。 ? ? SOCK_DGRAM ? ? ? ? ?數據報套接字,即使用 UDP 協議的套接字。固定長度的、無連接的、不可靠的報文傳遞。 ? ? SOCK_RAW ? ? ? ? ? ? ??原始套接字,即使用 IP 協議的套接字。 ? ? SOCK_SEQPACKET ? ?固定長度的、有序的、可靠的、面向連接的報文傳遞。 protocol:特殊協議,通常不用,取 0 即可。表示為給定的域和套接字類型選擇默認協議。當對同一域和套接字類型支持多個協議時,可以使用 protocol 選擇一個特定協議。 下圖列出了為因特網域套接字定義的協議:

(2)函數解析

socket 函數所返回的套接字描述符類似于文件描述符,Unix 系統把網絡也看成是文件,發送數據即寫文件,接收數據即讀文件,一切皆文件。 雖然套接字描述符本質上是一個文件描述符,但不是所有參數為文件描述符的函數都可以接受套接字描述符。 下圖總結了到目前為止所討論的大多數以文件描述符為參數的函數使用套接字描述符的行為。未指定和由實現定義的行為通常意味著該函數對套接字描述符無效。例如,lseek 不能以套接字描述符為參數,因為套接字不支持文件偏移量的概念。

(3)示例說明

int sockfd = socket (AF_LOCAL, SOCK_DGRAN, 0); if (sockfd == -1)perror ("socket"), exit (1);int sockfd = socket (AF_INET, SOCK_STREAM, 0); if (sockfd == -1)perror ("socket"), exit (1);int sockfd = socket (AF_INET, SOCK_DGRAN, 0); if (sockfd == -1)perror ("socket"), exit (1);

2、函數 shutdown:禁止套接字

套接字通信是雙向的??梢圆捎?shutdown 函數來禁止一個套接字的 I/O。 #include<sys/socket.h> int shutdown(int sockfd, int how); 返回值:若成功則返回0,出錯則返回-1. 如果 how 是 SHUT_RD (關閉讀端),那么無法從套接字讀取數據;如果 how 是 SHUT_WR (關閉寫端),那么無法使用套接字發送數據。如果 how 是 SHUT_RDWR ,則既無法讀取數據,又無法發送數據。 能夠關閉(close)套接字,為什么還要使用 shutdown 呢?這里有若干個理由。
首先,只有最后一個活動引用關閉時,close 才釋放網絡端點。這意味著,如果復制一個套接字(如采用 dup),套接字直到關閉了最后一個引用它的文件描述符之后才會被釋放。而 shutdown 允許使一個套接字處于不活動狀態,和引用它的文件描述符數目無關。
其次,有時可以很方便地關閉套接字雙向傳輸中的一個方向。

3、地址結構

套接字接口庫通過地址結構定位一個通信主體,可以是一個文件,可以是一臺遠程主機,也可以是執行自己。基本地址結構,本身沒有實際意義,僅用于泛型化參數。

為使不同格式地址能夠傳入到套接字函數,地址會被強制轉換成一個通用的地址結構 sockaddr

struct sockaddr{ sa_family_t sa_family; //地址族 char sa_data[]; //地址值 ... };

本地地址結構,用于 AF_LOCAL/AF_UNIX 域的本地通信

#include <sys/un.h> struct sockaddr_un {sa_family_t sun_family; //地址族(AF)LOCAL)char sun_path[]; //踏破戒指文件路徑 };

網絡地址結構,用于 AF_INET 域的 IPv4 網絡通信

#include <netinet/in.h> struct sockaddr_in {sa_family_t sin_family; //地址族(AF_INET)in_port_t sin_port; //端口號struct in_addr sin_addr; //IP地址 };struct in_addr {in_addr_t s_addr; };typedef unit16_t in_port_t; //無符號短整型 typedef unit32_t in_addr_t; //無符號長整型

與IPv4因特網域(AF_INET)相比,IPv6因特網域(AF_INET6)套接字使用如下結構sockaddr_in6表示

struct in6_addr{ unit8_t s6_addr[16]; //IPv6地址 }struct sockaddr_in6{ sa_family_t sin6_family; //地址family in_port_t sin6_port; //端口地址 uint32_t sin6_flowinfo; //流量等級和flow信息 struct in6_addr sin6_addr; //IPv6地址 uint32_t sin6_scope_id; //set of interfaces for scope }; 如前所述,通過 IP 地址可以定位網絡上的一臺主機,但一臺主機上可能同時又多個網絡應用在運行,究竟想跟哪個網絡應用通信呢?這就需要靠所謂的端口號來區分,因為不同的網絡應用會使用不同的端口號。用 IP 地址定位主機,再用端口號定位運行子啊這臺主機上的一個具體的網絡應用,這樣一種對通信主體的描述才是唯一確定的。 套接字接口庫中的端口號被定義為一個 16 位的無符號整數,其值介于 0 到 65535,其中 0 到 1024 已被系統和一些網絡服務占據,比如 21 端口用于 ftp 服務、23端口用于 telnet服務。80端口用于 www 服務等,因此一般應用程序最好選擇 1024 以上的端口號,以避免和這些服務沖突。 網絡應用與單機應用不同,經常需要在具有不同硬件架構和操作系統的計算機之間交換數據,因此編程語言里一些多字節數據類型的字節序問題就是需要特別予以關注。
這就涉及到大小端問題,參看:C語言再學習-- 大端小端詳解(轉)
假設一臺小端機器里有一個 32 位整數:0x1234 5678,它在內存中按照小端字節序低位低地址的規則存放:

現在,這個整數通過網絡被傳送到一臺大端機器里,內存中的形態不會有絲毫差別,但在大端機器看來地址越低的字節數位應該越高,因此它會把這 4 個字節解讀為:0x7856 3412,而這顯然有悖于發送端的初衷。
?為了避免字節序帶來的麻煩,套接字接口庫規定凡是在網絡中交換的多字節整數(short、int、long、long long 和它們的 unsigned 版本)一律采用網絡字節序傳輸。 而所謂網絡字節序,其實就是大端字節序。也就是說,發數據時,先從主機字節序轉成網絡字節序,然后發送;收數據時,先從網絡字節序轉成主機字節序,然后使用。
網絡地址結構 sockaddr_in 中表示端口號的 sin_port 成員和表示 IP 地址的 sin_addr.s_addr 成員,分別為 2 字節和 4 字節的無符號整數,同樣需要用網絡字節序來表示。 struct sockaddr_in add; addr.sin_family = AF_INET; addr.sin_port = htons (8888); addr.sin_addr.s_addr = inet_addr (192.168.182.48);其中 htons 函數將一個 16 位整數形式的端口號從主機序轉成網絡序(小端轉大端),而 inet_addr 函數則將一個點分十進制字符串形式的 IP 地址轉成網絡序的 32 位整數形式

4、將套接字和地址結構綁定

將套接字對象和自己的地址結構綁定在一起 #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 返回值:成功返回 0,失敗返回 -1

(1)參數解析

sockfd:套接字描述符 addr:自己的地址結構 addrlen:地址結構長度(以字節為單位)

(2)函數解析

套接字接口庫中的很多函數都用到地址結構,但為了同時支持不同的地址結構類型,其參數往往都會選擇更一般化的 sockaddr 類型的指針,使用時需要強制類型轉換。例如: struct sockaddr_un_addr; addr.sun_family = AF_LOCAL; strcpy (addr.sun+path, "mysock"); if (bind (sockfd, (struct sockaddr*)&addr, sizeof (addr)) == -1)perror ("bind"), exit (1);在上面例子中,將套接字綁定到一個本地文件上,此后所有針對這個本地文件的操作都可以反映到這個套接字之上。

struct sockaddr_in addr; addr.sun_family = AF_INET; addr.sin_port = htons (8888); addr.sin_addr.s_addr = int_addr ("192.168.182.48"); if (bind (sockfd, (struct sockaddr*)&addr, sizeof (addr)) == -1)perror ("bind"), exit (1);在上面例子中,將套接字綁定到一個 IP 和端口上,此后所有針對這個 IP 和端口的操作都可以反映到這個套接字之上。

struct sockaddr_in addr; addr.sun_family = AF_INET; addr.sin_port = htons (8888); addr.sin_addr.s_addr = INADDR_ANY; if (bind (sockfd, (struct sockaddr*)&addr, sizeof (addr)) == -1)perror ("bind"), exit (1);在上面的例子中,IP 地址使用了 INADDR_ANY 宏,該宏的值被定義為 0,表示任意 IP。這樣的綁定操作主要用于服務器,假設服務器主機配置了多個 IP 地址,無論客戶機用哪個 IP 地址發起通信,服務器套接字都能感覺到。 查看?/usr/include/netinet/in.h 可看到關于 INADDR_ANY 定義: #define INADDR_ANY ((in_addr_t) 0x00000000)

(3)擴展

可以調用函數 getsockname 來發現綁定到一個套接字地址。
#include<sys/socket.h> int getsockname(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp); //成功則返回0,出錯則返回-1. 調用 getsockname 之前,設置 alenp 為一個指向整數的指針,該整數指向緩沖區 sockaddr 的大小。返回時,該整數會被設置成返回地址的大小。如果該地址和提供的緩沖區長度不匹配,則將其截斷而不報錯。如果當前沒有綁定到該套接字的地址,其結果沒有定義。

如果套接字已經和對方連接,調用 getpeername 來找到對方的地址。
#include<sys/socket.h> int getpeername(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp); //成功則返回0,出錯則返回-1.

5、建立連接

將套接字對象和對方的地址結構連接在一起 #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen); 返回值:成功返回 0,失敗返回 -1

(1)參數解析

sockfd:套接字描述符 addr:對方的地址結構 addlen:地址結構長度(以字節為單位)

(2)函數解析

struct sockaddr_un addr; addr.sun_family = AF_LOCAL; strcpy (addr.sun_path, "mysock"); if (connect (sockfd, (strcut sockaddr*)&addr, sizeof (addr)) == -1)perror ("connect"), exit (1);
struct sockaddr_in addr; addr.sun_family = AF_INET; addr.sin_port = htons (8888); addr.sin_addr.s_addr = inet_addr ("192.168.182.48"); if (connect (sockfd, (strcut sockaddr*)&addr, sizeof (addr)) == -1)perror ("connect"), exit (1);

6、通過套接字發送字節流

#include <unistd.h> ssize_t write(int sockfd, const void *buf, size_t count); 返回值:成功返回實際發送的字節數(0 表示未發送),失敗返回 -1

(1)參數解析

sockfd:套接字描述符 buf:內存緩沖區 count:期望發送的字節數

(2)函數解析

ssize_t written = write (sockfd, text, towrite); if (written== -1)perror ("write"), exit (1);

7、通過套接字接收字節流

#include <unistd.h> ssize_t read(int fd, void *buf, size_t count); 返回值:成功返回實際接收的字節數(0表示連接關閉),失敗返回 -1

(1)參數解析

sockfd:套接字描述符 buf:內存緩沖區 count:期望讀取的字節數

(2)函數解析

ssize_t readed = read (sockfd, text, toread); if (readed == -1)perror ("read"), exit (1);

8、關閉套接字

關閉處于打開狀態的套接字描述符 #include <unistd.h> int close (int sockfd); 返回值:成功返回 0,失敗返回 -1

(1)參數解析

sockfd:套接字描述符

(2)函數解析

if (close (sockfd) == -1)perror ("close"), exit (1);

9、字節序轉換

參看:C語言再學習-- 大端小端詳解(轉)
將主機或網絡字節序的長短整數轉換為網絡或主機字節序
#include <arpa/inet.h> uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort); 返回值:返回網絡或主機字節序的長短整數 htonl() ? ? //32位無符號整型的主機字節順序到網絡字節順序的轉換(小端->>大端)
htons()
? ? //16位無符號短整型的主機字節順序到網絡字節順序的轉換 ?(小端->>大端)
ntohl() ?
? //32位無符號整型的網絡字節順序到主機字節順序的轉換 ?(大端->>小端)
ntohs()
? ? //16位無符號短整型的網絡字節順序到主機字節順序的轉換 ?(大端->>小端)
注,主機字節順序,X86一般多為小端(little-endian),網絡字節順序,即大端(big-endian); h表示“主機”字節序,n 表示“網絡字節序,l 表示“長”整數,s 表示“短”整數。 舉個例子: //示例一 #include <stdio.h> #icnlude <arpa/inet.h> int main (void) { union { short i; char a[2]; }u; u.a[0] = 0x11; u.a[1] = 0x22; printf ("0x%x\n", u.i); //0x2211 為小端 0x1122 為大端 printf ("0x%.x\n", htons (u.i)); //大小端轉換 return 0; } 輸出結果: 0x2211 0x1122

10、IP地址轉換

(1)點分十進制字符串->網絡字節序 32 位無符號整數

#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> in_addr_t inet_addr(const char *cp); 返回值:返回網絡字節序 32 位無符號整數形式的 IP 地址

《1》參數解析

cp:點分十進制字符串形式的 IP 地址

《2》示例說明

struct sockaddr_in addr; addr.sin_addr.s_addr = inet_addr ("1292.168.182.48");

(2)點分十進制字符串->網絡字節序 32 位無符號整數

#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int inet_aton(const char *cp, struct in_addr *inp); 返回值:成功返回 0,失敗返回 -1

《1》參數解析

cp:點分十進制字符串形式的 IP 地址 inp:輸出包含網絡字節序 32 位無符號整數形式 IP 地址的 in_addr 結構

《2》示例說明

struct sockaddr_in addr; if (inet_aton ("192.168.182.48", &addr.sin_addr) == -1)perror ("inet_aton"), exit (1);

(3)網絡字節序 32 位無符號整數->點分十進制字符串

#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> char *inet_ntoa(struct in_addr in); 返回值:返回點分十進制字符串形式的 IP 地址

《1》參數解析

in:包含網絡字節序 32 位無符號整數形式 IP 地址的 in_addr 結構

《2》示例說明

struct sockaddr_in addr; if (inet_ntoa ("192.168.182.48", &addr.sin_addr) == -1)perror ("inet_ntoa"), exit (1); printf ("%s\n", inet_ntoa (addr.sin_addr));

(4)函數 inet_ntop 和 inet_pton

需要說明一下,上面講的這兩個函數 inet_addr 和 inet_ntoa,用于二進制地址格式與點分十進制字符表示(a.c.b.d)之間的相互轉換。但是這些函數僅適用于 IPv4 地址。有兩個新函數 inet_ntop 和 inet_pton 具有相似的功能,而且同時支持 IPv4 地址和 IPv6 地址。#include<arpa/inet.h> const char *inet_ntop(int domain, const void *restrict addr, char *restrict str, socklen_t size); 返回值:若成功,返回地址字符串指針;若出錯,返回NULL。 int inet_pton(int domain, const char *restrict str, void *restrict addr); 返回值:若成功,返回 1;若格式無效,返回 0;若出錯,返回 -1 函數 inet_ntop 將網絡字節序的二進制地址轉換成文本字符串格式inet_pton 將文本字符串格式轉換成網絡字節序的二進制地址。參數 domian 僅支持兩個值:AF_INET 和 AF_INET6。 舉個例子: #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include<arpa/inet.h> int main(void){ char addr_p[16]; struct in_addr addr_n; if(inet_pton(AF_INET, "192.168.1.2",&addr_n) < 0){ perror("inet_pton"); return -1; } printf("address:%x\n",addr_n.s_addr); if(inet_ntop(AF_INET, &addr_n,addr_p,(socklen_t)sizeof(addr_p)) == NULL){ perror("inet_ntop"); return -1; } printf("address:%s\n",addr_p); } 輸出結果: address:201a8c0 address:192.168.1.2

三、通信編程

1、進程間通信

(1)基于套接字實現進程間通信的編程模型


(2)步驟解析

創建套接字時使用 AF_LOCAL 域。 int sockfd = socket (AF_LOCAL, ...);
準備地址結構時使用 sockaddr_un 結構體類型
struct sockaddr_un addr; addr.sun_family = AF_LOCAL; strcpy (addr.sun_path, "mysock");
套接字文件如不再用需要顯示刪除
unlink ("mysock");

(3)示例說明

//服務器 sockA.c #include <stdio.h> #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int main() {int sockfd = socket (AF_LOCAL, SOCK_DGRAM, 0);if (sockfd == -1){perror ("socket");exit (EXIT_FAILURE);}struct sockaddr_un addr;addr.sun_family = AF_LOCAL;strcpy (addr.sun_path, "mysock");if (bind (sockfd, (struct sockaddr*)&addr, sizeof (addr)) == -1){perror ("bind");unlink("mysock");exit (EXIT_FAILURE);}char text[1024];ssize_t readed = read (sockfd, text, 1024);if (readed == -1){perror ("read");unlink("mysock");exit (EXIT_FAILURE);}printf("客戶機發送內容:%s\n", text);if (close (sockfd) == -1){perror ("close");exit (EXIT_FAILURE);}unlink("mysock");return 0; } //客戶機 sockB.c #include <stdio.h> #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int main() {int sockfd = socket (AF_LOCAL, SOCK_DGRAM, 0);if (sockfd == -1){perror ("socket");exit (EXIT_FAILURE);}struct sockaddr_un addr;addr.sun_family = AF_LOCAL;strcpy (addr.sun_path, "mysock");if (connect (sockfd, (struct sockaddr*)&addr, sizeof (addr)) == -1){perror ("connect");exit (EXIT_FAILURE);}char text[1024] = "你好,服務器";ssize_t written = write (sockfd, text, strlen(text));if (written == -1){perror ("write");exit (EXIT_FAILURE);}if (close (sockfd) == -1){perror ("close");exit (EXIT_FAILURE);}return 0; } 輸出結果:在一個終端執行: # ./sockA 客戶機發送內容:你好,服務器在另一個終端執行: # ./sockB

2、網絡通信

(1)基于套接字實現網絡通信的編程模型


(2)步驟解析

創建套接字時使用 AF_INET 域 int sockfd = socket (AF_INET, ...);
準備地址結構時使用 sockaddr_in 結構體類型
—服務器 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (8888); addr.sin_addr.s_addr = INADDR_ANY; —客戶機 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (8888); addr.sin_addr.s_addr = inet_addr ("129.168.182.48"); —客戶機連接本機服務器可以使用本地環回地址 addr.sin_addr.s_addr = inet_addr ("127.0.0.1");

(3)示例說明

//服務器 sockNetA.c #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> int main() {int sockfd = socket (AF_INET, SOCK_DGRAM, 0);if (sockfd == -1){perror ("socket");exit (EXIT_FAILURE);}struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons (8888);addr.sin_addr.s_addr = INADDR_ANY;if (bind (sockfd, (struct sockaddr*)&addr, sizeof (addr)) == -1){perror ("bind");exit (EXIT_FAILURE);}char text[1024];ssize_t readed = read (sockfd, text, 1024);if (readed == -1){perror ("read");exit (EXIT_FAILURE);}printf("客戶機發送內容:%s\n", text);if (close (sockfd) == -1){perror ("close");exit (EXIT_FAILURE);}return 0; } //客戶機 sockNetB.c #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> int main() {int sockfd = socket (AF_INET, SOCK_DGRAM, 0);if (sockfd == -1){perror ("socket");exit (EXIT_FAILURE);}struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons (8888);addr.sin_addr.s_addr = inet_addr("127.0.0.1");if (connect (sockfd, (struct sockaddr*)&addr, sizeof (addr)) == -1){perror ("connect");exit (EXIT_FAILURE);}char text[1024] = "你好,服務器";ssize_t written = write (sockfd, text, strlen(text));if (written == -1){perror ("write");exit (EXIT_FAILURE);}if (close (sockfd) == -1){perror ("close");exit (EXIT_FAILURE);}return 0; } 輸出結果:在一個終端執行: # ./sockNetA 客戶機發送內容:你好,服務器在另一個終端執行: # ./sockNetB


總結

以上是生活随笔為你收集整理的UNIX再学习 -- 网络IPC:套接字的全部內容,希望文章能夠幫你解決所遇到的問題。

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