首页 > 其他分享 >一个服务器对多个客户端的本地socket通信C语言实现

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

时间:2023-02-16 14:13:57浏览次数:51  
标签:addr socket void struct uint8 ret 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;
}

 

标签:addr,socket,void,struct,uint8,ret,C语言,客户端
From: https://www.cnblogs.com/wenssie-xu/p/17126282.html

相关文章

  • 凤凰架构 - 服务发现、网关路由、客户端负载均衡、流量治理、可靠通讯、可观测性
     一、服务发现 1.所有的远程服务调用都是使用全限定名(FullyQualifiedDomainName,FQDN)、端口号与服务标识所构成的三元组来确定一个远程服务的精确坐标的。全限定名......
  • c语言文件读写
    C语言文件读写算法1.fseek()函数此函数用于移动文件指针到指定位置。例如,要将文件指针移动到文件的第5个字节处,您可以使用以下代码:fseek(fp,5,SEEK_SET);//将文件......
  • C语言学生课程选修管理系统[2023-02-15]
    C语言学生课程选修管理系统[2023-02-15]课程设计题目及要求本课题要求用C语言编写一个学生课程选修管理系统。学生课程选修系统用于学生选修学习课程。系统可以管理若干......
  • flask_openv_video_streaming_来自miguelgrinberg大佬_写pythonsocketio的那个
    E:\song2\树莓派视频流\flask_opencv_video_stream\flask-video-streaming\app.py#!/usr/bin/envpythonfromimportlibimportimport_module#importosfromflaski......
  • flask_socketio_rasip_video_stream_opencv
    E:\song\Flask-SocketIO-Chat-master\run.py#!/bin/envpythonfromappimportcreate_app,socketioapp=create_app(debug=False)if__name__=='__main__':......
  • C语言不显示输入密码
    原文地址:https://www.cnblogs.com/liqinglucky/p/hide_input.html通过C语言实现隐藏密码输入。目标是做到读写用户输入,屏幕不回显。程序隐藏输入参考:C程序实现密码隐秘......
  • C语言:静态变量
    #include<stdio.h>//变量作用域:局部变量全局变量//函数外声明的变量称为全局变量,函数内声明的变量的称为局部变量//变量生存周期:变量的存在时间//静态存储方式:指在......
  • 02. C语言基础知识
    一、注释  注释就是对代码进行解释说明的文字,注释的内容不会参与编译和运行,仅仅是对代码的解释说明。在C语言中注释主要分为以下两类:单行注释://,注释内容从//始到......
  • WebSocket使用
    WebSocket特点:服务器可以主动想客户端推送信息,客户端也可以主动向服务器发送消息,所有浏览器都支持建立在TCP协议上,服务端的实现比较容易与HTTP协议有良好的兼容性数据比......
  • 单链表:用C语言定义单链表结构
    一、单链表公共头文件#ifndef__MYHEAD_H__#define__MYHEAD_H__/*******************************************************************@file:myhead.h*@brief......