UNIX域套接字
域套接字作为进程间通信的一种手段,值得我们研究一下。
域套接字实现本地进程间通信,同样有服务端和客户端之分。一个进程作为客户端,另一个进程作为服务端。这个和TCP socket类似,但是不一样。域套接字不经过底层网络。数据结构使用的是struct sockaddr_un。对于这个结构,重点便是填充sun_family和sun_path,sun_path是文件路径。调用的socket接口也是socket、bind、listen、accept、connect、close这些,实际用起来可以看一下细节。
#include <sys/un.h>
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
服务端通信过程
1、socket()建立socket对象,指定协议类型为AF_LOCAL或者AF_UNIX
2、bind()绑定socket对象和socket类型的文件“server socket”
warnning:这里需要关注一下“server socket”这个文件。网络编程中,绑定的是ip和port,但是这里需要绑定的是socket类型的文件,如果在绑定之前,这个文件已经存在,则绑定会失败,因此,需要在bind之前和close之后,删除这个文件。
3、llisten()监听socket对象
4、accept()等待连接
5、read、write读写连接的socket对象,进行数据通信
6、close关闭连接的socket对象
客户端通信过程
1、socket()建立socket对象,指定协议类型为AF_LOCAL或者AF_UNIX
2、connet()连接服务端
3、连接成功开始数据通信
4、通信完成,close关闭socket
服务端代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define MAX_SIZE 1024
#define SOCKET_BACKLOG 1
#define SOCKET_STR "server_socket"
#define EXIT_STR "exit"
/* server */
int main()
{
int serFd,serConFd;
int cli_len, nBytes;
struct sockaddr_un serAddr;
struct sockaddr_un cliAddr;
char msg[MAX_SIZE];
unlink(SOCKET_STR);
serFd = socket(AF_LOCAL, SOCK_STREAM, 0);
memset(&serAddr, 0, sizeof(struct sockaddr_un));
serAddr.sun_family = AF_LOCAL;
strcpy(serAddr.sun_path, SOCKET_STR);
bind(serFd, (struct sockaddr*)&serAddr, sizeof(struct sockaddr_un));
listen(serFd, SOCKET_BACKLOG);
cli_len = sizeof(struct sockaddr_un);
printf("server is waiting for connection...\n");
serConFd = accept(serFd, (struct sockaddr*)&cliAddr, &cli_len);
printf("server-client connect established...\n");
while(1){
memset(msg, 0, MAX_SIZE);
nBytes = read(serConFd, msg, MAX_SIZE);
if (nBytes>0){
printf("server recv:%s\n", msg);
if (!strcmp(msg, EXIT_STR)) break;
}
}
close(serConFd);
unlink(SOCKET_STR);
}
客户端代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define MAX_SIZE 1024
#define SOCKET_BACKLOG 1
#define SOCKET_STR "server_socket"
#define EXIT_STR "exit"
/* client */
int main()
{
int cliFd, iRet;
struct sockaddr_un serAddr;
char msg[MAX_SIZE];
cliFd = socket(AF_LOCAL, SOCK_STREAM, 0);
memset(&serAddr, 0, sizeof(struct sockaddr_un));
serAddr.sun_family = AF_LOCAL;
strcpy(serAddr.sun_path, SOCKET_STR);
iRet = connect(cliFd, (struct sockaddr*)&serAddr, sizeof(struct sockaddr_un));
if (-1 == iRet)
exit(0);
printf("server-client connect established...\n");
while(1){
memset(msg, 0, MAX_SIZE);
fgets(msg, MAX_SIZE, stdin);
if (msg[0] != '\n')
msg[strlen(msg)-1] = '\0';
write(cliFd, msg, strlen(msg));
if (!strcmp(msg, EXIT_STR)) break;
}
close(cliFd);
exit(0);
}
结果截图: