Local sockets are a special type of socket, different from TCP/UDP sockets. Even if TCP/UDP communicates at a local address, it still needs to go through the system network protocol stack. Strictly speaking, local sockets provide a means of cross-process calls from a single host, which reduces the complexity and efficiency of protocol stack implementation. Much higher than TCP/UDP sockets. Local sockets are IPC, which is an implementation of local inter-process communication.
The role of local sockets: local inter-process communication,
which can realize communication between related processes and communication between processes that are not related.
The local socket implementation process is similar to that of network sockets, and generally uses the TCP communication process.
Address structure comparison (local vs. network)
struct sockaddr_in {
__kernel_sa_family_t sin_family; /* Address family */ 地址结构类型
__be16 sin_port; /* Port number */ 端口号
struct in_addr sin_addr; /* Internet address */ IP地址
};
struct sockaddr_un {
__kernel_sa_family_t sun_family; /* AF_UNIX */ 地址结构类型
char sun_path[UNIX_PATH_MAX]; /* pathname */ socket文件名(含路径)
};
Comparison of programming ideas (local vs. network)
Local socket—inter-process communication process
Service-Terminal
1. Create a listening socket
int lfd = socket(af_local, sock_stream, 0);
first parameter: AF_UNIX, AF_LOCAL2. The listening socket is bound to the local socket file -> server side
struct sockaddr_un addr;
// After the binding is successful, the socket file in the specified sun_path will automatically generate
bind(lfd, addr, len) ;3.
Listen(lfd, 100);4. Wait for and accept the connection request
struct sockaddr_un cliaddr;
int connfd = accept(lfd, cliaddr, len);5. Communication
to receive data: read/recv
to send data: write/send6. Close the connection
close();
client
1. Create a communication socket
int fd = socket(af_local, sock_stream, 0);2. The listening socket is bound to the local IP port
struct sockaddr_un addr;
// After the binding is successful, the socket file in the specified sun_path will automatically generate
bind(fd, addr, len);3. Connect to the server
struct sockaddr_un serveraddr;
connect(fd, serveraddr, sizeof(serveraddr));4. Communication
to receive data: read/recv
and send data: write/send5. Close the connection
Code
/* server.c */
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <stddef.h>
#include "wrap.h"
#define SERV_ADDR "serv.socket"
int main(void)
{
int lfd, cfd, len, size, i;
struct sockaddr_un servaddr, cliaddr;
char buf[4096];
lfd = Socket(AF_UNIX, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path, SERV_ADDR);
len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path); /* servaddr total len */
unlink(SERV_ADDR); /* 确保bind之前serv.sock文件不存在,bind会创建该文件 */
Bind(lfd, (struct sockaddr *)&servaddr, len); /* 参3不能是sizeof(servaddr) */
Listen(lfd, 20);
printf("Accept ...\n");
while (1) {
len = sizeof(cliaddr); //AF_UNIX大小+108B
cfd = Accept(lfd, (struct sockaddr *)&cliaddr, (socklen_t *)&len);
len -= offsetof(struct sockaddr_un, sun_path); /* 得到文件名的长度 */
cliaddr.sun_path[len] = '\0'; /* 确保打印时,没有乱码出现 */
printf("client bind filename %s\n", cliaddr.sun_path);
while ((size = read(cfd, buf, sizeof(buf))) > 0) {
for (i = 0; i < size; i++)
buf[i] = toupper(buf[i]);
write(cfd, buf, size);
}
close(cfd);
}
close(lfd);
return 0;
}
/* client.c */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <stddef.h>
#include "wrap.h"
#define SERV_ADDR "serv.socket"
#define CLIE_ADDR "clie.socket"
int main(void)
{
int cfd, len;
struct sockaddr_un servaddr, cliaddr;
char buf[4096];
cfd = Socket(AF_UNIX, SOCK_STREAM, 0);
bzero(&cliaddr, sizeof(cliaddr));
cliaddr.sun_family = AF_UNIX;
strcpy(cliaddr.sun_path,CLIE_ADDR);
len = offsetof(struct sockaddr_un, sun_path) + strlen(cliaddr.sun_path); /* 计算客户端地址结构有效长度 */
unlink(CLIE_ADDR);
Bind(cfd, (struct sockaddr *)&cliaddr, len); /* 客户端也需要bind, 不能依赖自动绑定*/
bzero(&servaddr, sizeof(servaddr)); /* 构造server 地址 */
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path, SERV_ADDR);
len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path); /* 计算服务器端地址结构有效长度 */
Connect(cfd, (struct sockaddr *)&servaddr, len);
while (fgets(buf, sizeof(buf), stdin) != NULL) {
write(cfd, buf, strlen(buf));
len = read(cfd, buf, sizeof(buf));
write(STDOUT_FILENO, buf, len);
}
close(cfd);
return 0;
}