对于同一台主机间的多个进程间通信,除了使用共享内存,消息队列等方式,使用本地socket也是很高效的一种选择。不同于网络socket,本地socket不需要指定ip地址,也不需要进行网络协议栈等的校验,更加的安全和方便。
关于本地socket的更多介绍,可以参考文章(10条消息) 嵌入式linux网络编程,UNIX域套接字,AF_LOCAL,PF_LOCAL,PF_UNIX,,AF_UNIX,进程间通信机制_nice梦醉天宇的博客-CSDN博客_pf_unix。
现在需要实现一个进程作为服务器,另外两个进程用作客户端,本地socket建立以后,服务器分别对client1和client2发送请求,client1和client2回复当前进程的相关信息给服务器。以下是实现本地socket的demo:
server.c
#define SUCCESS ((uint8)0)
#define FAIL ((uint8)1)
#define MTEXT_LEN ((uint32)8)
#define MAX_RECV_BYTES ((uint32)32)
#define SERVER_SOCKET "/tmp/s_socket"
#define CLIENT_ONE "/tmp/c1_socket"
#define CLIENT_TWO "/tmp/c2_socket"
static uint8 reqdata[MTEXT_LEN] = {0x01,0,0,0,0,0,0,0};
sint32 fd = -1;
static uint8 init(void)
{
uint8 ret = SUCCESS;
int b_reuse = 1;
if(fd < 0)
{
if(access(SERVER_SOCKET,F_OK) == 0)
{
remove(SERVER_SOCKET);
}
fd = socket(AF_UNIX, (sint32)SOCK_DGRAM, 0);
if(fd == -1)
{
ret = FAIL;
}
else
{
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
struct sockaddr_un addr;
(void)memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
(void)strncpy(addr.sun_path, SERVER_SOCKET, (uint32)strlen(SERVER_SOCKET));
if(bind(fd, (struct sockaddr_un*)&addr, (uint32)(sizeof(struct sockaddr_un))) == -1)
{
ret = FAIL;
printf("bind fail!\n");
}
}
}
return ret;
}
static uint8 send_msg1(void)
{
uint8 ret = SUCCESS;
ssize_t numSend;
struct sockaddr_un addr;
(void)memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
(void)strncpy(addr.sun_path, CLIENT_ONE, (uint32)strlen(CLIENT_ONE));
numSend = sendto(fd, reqdata, MTEXT_LEN, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_un));
if(numSend < SUCCESS)
{
printf("send req failed, error: %s\n", strerror(errno));
ret = FAIL;
}
return ret;
}
static uint8 send_msg2(void)
{
uint8 ret = SUCCESS;
ssize_t numSend;
struct sockaddr_un addr;
(void)memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
(void)strncpy(addr.sun_path, CLIENT_TWO, (uint32)strlen(CLIENT_TWO));
numSend = sendto(fd, reqdata, MTEXT_LEN, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_un));
if(numSend < SUCCESS)
{
printf("send req failed, error: %s\n", strerror(errno));
ret = FAIL;
}
return ret;
}
static void recv_msg(void)
{
uint8 recvBuf[MAX_RECV_BYTES];
while(1)
{
(void)memset(recvBuf, 0, sizeof(recvBuf));
if(recvfrom(fd, recvBuf, MAX_RECV_BYTES, 0, NULL, NULL) < 0)
{
printf("recv error!\n");
}
else
{
for(uint8 i=0;i<MAX_RECV_BYTES;i++)
{
printf("recvBuf[%d] = %d\n",i,recvBuf[i]);
}
}
}
}
void send1()
{
uint8 ret = send_msg1();
if(ret == FAIL)
{
printf("send msg1 fail!\n");
sleep(1);
send1();
}
}
void send2()
{
uint8 ret = send_msg2();
if(ret == FAIL)
{
printf("send msg2 fail!\n");
sleep(1);
send2();
}
}
int main(void)
{
uint8 ret = init();
if(ret == FAIL)
{
printf("server init fail!\n");
}
send1();
send2();
recv_msg();
return 0;
}
client1.c
#define SUCCESS ((uint8)0)
#define FAIL ((uint8)1)
#define MTEXT_LEN ((uint32)32)
#define MAX_RECV_BYTES ((uint32)32)
#define CLIENT_ONE "/tmp/c1_socket"
#define SERVER_SOCKET "/tmp/s_socket"
sint32 g_socket = -1;
uint8 respdata[MTEXT_LEN] = {0};
static uint8 init(void)
{
for(uint8 i=0;i<MTEXT_LEN;i++)
{
respdata[i] = i;
}
uint8 ret = SUCCESS;
struct sockaddr_un addr;
int b_reuse = 1;
(void)memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
(void)strncpy(addr.sun_path, CLIENT_ONE, (uint32)strlen(CLIENT_ONE));
if(access(CLIENT_ONE,F_OK) == 0)
{
remove(CLIENT_ONE);
}
g_socket = socket(AF_UNIX, (sint32)SOCK_DGRAM, 0);
if(g_socket == -1)
{
ret = FAIL;
printf("socket init fail!\n");
}
setsockopt(g_socket,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
if(bind(g_socket, (struct sockaddr_un*)&addr, (uint32)(sizeof(struct sockaddr_un))) == -1)
{
ret = FAIL;
printf("bind fail!\n");
}
return ret;
}
static uint8 send_msg(void)
{
uint8 ret = SUCCESS;
ssize_t numSend;
struct sockaddr_un addr;
(void)memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
(void)strncpy(addr.sun_path, SERVER_SOCKET, (uint32)strlen(SERVER_SOCKET));
numSend = sendto(g_socket, respdata, MTEXT_LEN, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_un));
if(numSend < SUCCESS)
{
printf("send req failed, error: %s\n", strerror(errno));
ret = FAIL;
}
return ret;
}
static void recv_msg(void)
{
uint8 recvBuf[MAX_RECV_BYTES];
while(1)
{
(void)memset(recvBuf, 0, sizeof(recvBuf));
if(recvfrom(g_socket, recvBuf, MAX_RECV_BYTES, 0, NULL, NULL) < 0)
{
printf("rcv error!\n");
}
else
{
for(uint8 i=0;i<MAX_RECV_BYTES;i++)
{
printf("recvBuf[%d] = %d\n",i,recvBuf[i]);
}
if(recvBuf[0] == 0x01u)
{
uint8 ret = send_msg();
if(ret != SUCCESS)
{
printf("send errorcode to DM fail!\n");
}
}
}
}
}
int main(void)
{
uint8 ret = init();
if(ret == FAIL)
{
printf("socket init fail!\n");
}
else
{
recv_msg();
}
return 0;
}
client2.c
#define SUCCESS ((uint8)0)
#define FAIL ((uint8)1)
#define MTEXT_LEN ((uint32)32)
#define MAX_RECV_BYTES ((uint32)32)
#define SERVER_SOCKET "/tmp/s_socket"
#define CLIENT_TWO "/tmp/c2_socket"
sint32 g_socket = -1;
uint8 respdata[MTEXT_LEN] = {0};
static uint8 init(void)
{
for(uint8 i=0;i<MTEXT_LEN;i++)
{
respdata[i] = i+MTEXT_LEN;
}
uint8 ret = SUCCESS;
struct sockaddr_un addr;
int b_reuse = 1;
(void)memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
(void)strncpy(addr.sun_path, CLIENT_TWO, (uint32)strlen(CLIENT_TWO));
if(access(CLIENT_TWO,F_OK) == 0)
{
remove(CLIENT_TWO);
}
g_socket = socket(AF_UNIX, (sint32)SOCK_DGRAM, 0);
if(g_socket == -1)
{
ret = FAIL;
printf("socket init fail!\n");
}
setsockopt(g_socket,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
if(bind(g_socket, (struct sockaddr_un*)&addr, (uint32)(sizeof(struct sockaddr_un))) == -1)
{
ret = FAIL;
printf("bind fail!\n");
}
return ret;
}
static uint8 send_msg(void)
{
uint8 ret = SUCCESS;
ssize_t numSend;
struct sockaddr_un addr;
(void)memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
(void)strncpy(addr.sun_path, SERVER_SOCKET, (uint32)strlen(SERVER_SOCKET));
numSend = sendto(g_socket, respdata, MTEXT_LEN, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_un));
if(numSend < SUCCESS)
{
printf("send req failed, error: %s\n", strerror(errno));
ret = FAIL;
}
return ret;
}
static void recv_msg(void)
{
uint8 recvBuf[MAX_RECV_BYTES];
while(1)
{
(void)memset(recvBuf, 0, sizeof(recvBuf));
if(recvfrom(g_socket, recvBuf, MAX_RECV_BYTES, 0, NULL, NULL) < 0)
{
printf("[FIREWALL LOG]rcv error!\n");
}
else
{
for(uint8 i=0;i<MAX_RECV_BYTES;i++)
{
printf("[FIREWALL LOG]recvBuf2[%d] = %d\n",i,recvBuf[i]);
}
if(recvBuf[0] == 0x01u)
{
uint8 ret = send_msg();
if(ret != SUCCESS)
{
printf("[FIREWALL LOG]send errorcode to DM fail!\n");
}
}
}
}
}
int main(void)
{
uint8 ret = init();
if(ret == FAIL)
{
printf("socket init fail!\n");
}
else
{
recv_msg();
}
return 0;
}
标签:addr,socket,void,struct,uint8,ret,C语言,客户端 From: https://www.cnblogs.com/wenssie-xu/p/17126282.html