5、消息隊(duì)列
消息隊(duì)列保存在內(nèi)核中,是一個(gè)由消息組成的鏈表。
(1)創(chuàng)建或訪問消息隊(duì)列
int msgget(key_t key,int msgflg);
(2)操作消息隊(duì)列
int msgsnd(int msqid,const void *msg,size_t nbytes,int msgflg);
msg指向的結(jié)構(gòu)體必須以一個(gè)long int成員開頭,作為msgrcv()的消息類型,必須大于0。nbytes指的是msg指向結(jié)構(gòu)體的大小,但不包括long int部分的大小
ssize_t msgrcv(int msqid,void *msg,size_t nbytes,long msgtype,int msgflg);
如果msgtype是0,就返回消息隊(duì)列中的第一個(gè)消息;如果是正整數(shù),就返回隊(duì)列中的第一個(gè)該類型的消息;如果是負(fù)數(shù),就返回隊(duì)列中具有最小值的第一個(gè)消息,并且該最小值要小于等于msgtype的絕對(duì)值。
(3)控制消息隊(duì)列
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
struct msqid_ds{
struct ipc_perm msg_perm;
…
};
6、Socket
套接字(Socket)是由Berkeley在BSD系統(tǒng)中引入的一種基于連接的IPC,是對(duì)網(wǎng)絡(luò)接口(硬件)和網(wǎng)絡(luò)協(xié)議(軟件)的抽象。它既解決了無名管道只能在相關(guān)進(jìn)程間單向通信的問題,又解決了網(wǎng)絡(luò)上不同主機(jī)之間無法通信的問題。
套接字有三個(gè)屬性:域(domain)、類型(type)和協(xié)議(protocol),對(duì)應(yīng)于不同的域,套接字還有一個(gè)地址(address)來作為它的名字。
域(domain)指定了套接字通信所用到的協(xié)議族,最常用的域是AF_INET,代表網(wǎng)絡(luò)套接字,底層協(xié)議是IP協(xié)議。對(duì)于網(wǎng)絡(luò)套接字,由于服務(wù)器端有可能會(huì)提供多種服務(wù),客戶端需要使用IP端口號(hào)來指定特定的服務(wù)。AF_UNIX代表本地套接字,使用Unix/Linux文件系統(tǒng)實(shí)現(xiàn)。
IP協(xié)議提供了兩種通信手段:流(streams)和數(shù)據(jù)報(bào)(datagrams),對(duì)應(yīng)的套接字類型(type)分別為流式套接字和數(shù)據(jù)報(bào)套接字。流式套接字(SOCK_STREAM)用于提供面向連接、可靠的數(shù)據(jù)傳輸服務(wù)。該服務(wù)保證數(shù)據(jù)能夠?qū)崿F(xiàn)無差錯(cuò)、無重復(fù)發(fā)送,并按順序接收。流式套接字使用TCP協(xié)議。數(shù)據(jù)報(bào)套接字(SOCK_DGRAM)提供了一種無連接的服務(wù)。該服務(wù)并不能保證數(shù)據(jù)傳輸?shù)目煽啃裕瑪?shù)據(jù)有可能在傳輸過程中丟失或出現(xiàn)數(shù)據(jù)重復(fù),且無法保證順序地接收到數(shù)據(jù)。數(shù)據(jù)報(bào)套接字使用UDP協(xié)議。
一種類型的套接字可能可以使用多于一種的協(xié)議來實(shí)現(xiàn),套接字的協(xié)議(protocol)屬性用于指定一種特定的協(xié)議。
(1) 創(chuàng)建套接字
|
int socket(int domain,int type,int protocol); |
對(duì)于SOCK_STREAM和SOCK_DGRAM而言,分別只有一種協(xié)議支持這種類型的套接字。因此protocol可以為0,表示默認(rèn)的協(xié)議。
(2) 綁定套接字
|
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);//將無名套接字sockfd與addr綁定(bind) |
(3) 監(jiān)聽套接字
|
int listen(int sockfd,int backlog);//backlog限定了等待服務(wù)的隊(duì)列的最大長度 |
(4) 等待接受連接
|
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen); |
當(dāng)客戶端程序嘗試連接sockfd套接字時(shí),accept返回一個(gè)新的套接字與客戶端進(jìn)行通信。如果addr不是NULL,那么客戶端的地址將會(huì)保存在addr所指向的結(jié)構(gòu)體中;調(diào)用accept()前必須先將addrlen初始化為addr所指向結(jié)構(gòu)體的大小,accept()返回以后,addrlen將會(huì)被設(shè)置成客戶端套接字地址結(jié)構(gòu)體的實(shí)際大小。然后,通過對(duì)accept()返回的套接字執(zhí)行read()和write()操作即可實(shí)現(xiàn)與客戶端的簡單的通信。
(5) 建立連接(客戶端)
? |
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen); |
connect()在無名套接字sockfd和addr之間建立連接。addr指向的結(jié)構(gòu)體中可以包含服務(wù)器的IP地址和端口號(hào)等信息。
(6) 數(shù)據(jù)傳輸
|
ssize_t send(int sockfd,const void *buf,size_t len,int flags);
ssize_t recv(int sockfd, void *buf, size_t len,int flags); |
(7) 關(guān)閉套接字
(8) 主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換
|
#include <netinet/in.h>
unsigned long int htonl(unsigned long int hostlong); //host to network,long
unsigned short int htons(unsigned short int hostshort);
unsigned long int ntohl(unsigned long int netlong);
unsigned short int ntohs(unsigned short int netshort); |
long型函數(shù)用來轉(zhuǎn)換sockaddr_in.in_addr.s_addr;short型函數(shù)用來轉(zhuǎn)換sockaddr_in.sin_port。
今天的講解就到這里了,想要了解或者學(xué)習(xí)更多、更詳細(xì)的內(nèi)容,歡迎來到我們傳智播客C/C++培訓(xùn)專家(
http://xamj520.com/c/)來咨詢、學(xué)習(xí)。
本文版權(quán)歸傳智播客C++培訓(xùn)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處。謝謝!
作者:傳智播客C/C++培訓(xùn)學(xué)院
首發(fā):http://xamj520.com/c/