一个服务器对多个客户端的本地socket通信C语言实现

  对于同一台主机间的多个进程间通信,除了使用共享内存,消息队列等方式,使用本地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;
}

 

posted @ 2023-02-16 13:57  Wenssie_xu  阅读(780)  评论(0编辑  收藏  举报