當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > socket進(jìn)程間通信方式大總結(jié),還有典型實(shí)例哦
socket在主機(jī)間和進(jìn)程間使用,方法類似,主要區(qū)別是進(jìn)程間通信使用的是sockaddr_un,而主機(jī)間的通信使用的是sockadd_in。
每個(gè)套接字都有其自己的地址格式,對(duì)于AF_UNIX域套接字來說,它的地址由結(jié)構(gòu)sockaddr_un來描述,該結(jié)構(gòu)定義在頭文件sys/un.h中,它的定義如下:
struct sockaddr_un {
__kernel_sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
對(duì)于AF_INET域套接字來說,它的地址結(jié)構(gòu)由sockaddr_in來描述,它至少包括以下幾個(gè)成員:
struct sockaddr_in {
__kernel_sa_family_t sin_family; /* Address family */
__be16 sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
使用socket作為進(jìn)程間通信方式,有什么注意事項(xiàng)?
(1) Server
a. 創(chuàng)建一個(gè)server socket
創(chuàng)建的socket是AF_UNIX域的。
b. 設(shè)置Server的地址
利用bind函數(shù)。
注意:地址一般通過一個(gè)字符串來標(biāo)識(shí),一般的做法是通過一個(gè)Linux路徑來實(shí)現(xiàn);注意使用之前必須要把該路徑unlink掉,否則可能出現(xiàn)bind失敗的情況。
c. 開始監(jiān)聽
利用listen函數(shù)。
注意:最大監(jiān)聽的長度為128.
d. 接收連接
利用accept函數(shù)。
注意:accept函數(shù)默認(rèn)為阻塞模式。有一個(gè)可以設(shè)置非阻塞的為accept4函數(shù);
在accept函數(shù)阻塞的過程中,一些信號(hào)對(duì)打斷accept的阻塞,這是正常現(xiàn)象。因此如果要設(shè)置一直阻塞,需要考慮這種情況。
e. 接收數(shù)據(jù)
利用recv()函數(shù)
注意:recv函數(shù)是在accept新生成的socket上接收消息。recv()函數(shù)可以工作在阻塞模式,也可以工作在非阻塞模式。一般都是阻塞模式。新生成的socket注意要關(guān)閉。
(2) client
a. 創(chuàng)建
注意域?yàn)锳F_UNIX。
b. 連接服務(wù)器:connect調(diào)用
注意:connect為非阻塞模式,需要增加重試機(jī)制保證可靠性。
c. 發(fā)送數(shù)據(jù):send
注意:該調(diào)用可以是阻塞的,也可以是非阻塞的,最好設(shè)置為非阻塞模式,默認(rèn)為阻塞模式。另外,可以調(diào)用setsockopt()來設(shè)置阻塞時(shí)長。level:SOL_SOCKET,SO_SNDTIMEO。
例子如下:
server
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct sockaddr SA;
int main(int argc, const char *argv[])
{
//1.定義變量
int sockfd, clientfd;
socklen_t addrlen = sizeof(SA);
struct sockaddr_un addr;
ssize_t nbytes;
char buf[32] = {0};
//2.創(chuàng)建本地套接字接口
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sockfd < 0){
perror("socket err");
exit(-1);
}
//3.填充本地地址信息
bzero(&addr, addrlen);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "unix_sock");
//4.綁定本地套接字
remove("unix_sock");
if(bind(sockfd, (struct sockaddr *)&addr, addrlen) < 0){
perror("bind err");
exit(-1);
}
//5.監(jiān)聽套接字
if(listen(sockfd, 5) < 0){
perror("listen err");
exit(-1);
}
//6.接收連接
clientfd = accept(sockfd, NULL, NULL);
while(1)
{
//7.接收客戶端數(shù)據(jù)
nbytes = recv(clientfd, buf, 32, 0);
if(nbytes < 0){
perror("recv err");
exit(-1);
}else if (nbytes == 0) {
printf("peer exit\n");
break;
}else{
printf("recv data = %s\n", buf);
}
}
//8.關(guān)閉套接字
close(clientfd);
close(sockfd);
}
client
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct sockaddr SA;
int main(int argc, const char *argv[])
{
//1.定義變量
int sockfd;
socklen_t addrlen = sizeof(SA);
struct sockaddr_un addr;
char buf[32] = {0};
//2.創(chuàng)建本地套接字接口
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sockfd < 0){
perror("socket err");
exit(-1);
}
//3.填充服務(wù)器的地址信息
bzero(&addr, addrlen);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "unix_sock");
//4.連接服務(wù)器
if(connect(sockfd, (struct sockaddr *)&addr, addrlen) < 0){
perror("connect err");
exit(-1);
}
//5.收發(fā)數(shù)據(jù)
while (1) {
gets(buf);
send(sockfd, buf, 32, 0);
}
//6.關(guān)閉套接字
close(sockfd);
}