LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-08-2015, 10:37 PM   #1
sisrnb
LQ Newbie
 
Registered: Dec 2013
Distribution: debian wheezy
Posts: 23

Rep: Reputation: Disabled
Question using AF_UNIX SOCK_DGRAM socket to communicate between one server and multi clients?


Currently I use a link list on server to store all clients' sockaddr_un, and loop the link list when server needs to send msg to all clients.
I have googled for a long time to find a method which doesn't need link list and loop, but I have not find the method I expected.

Today I try binding two clients to same sun_path,
server.c:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#define SERVER_SUN_PATH "/tmp/server_sun_path.0"
#define CLIENT_SUN_PATH "/tmp/client_sun_path.0"

static int Init();
static int Deinit();
static int MsgLoop();

static int  serverSock = -1;

int main(int argc, char *argv[])
{
   int ret = 0;

   ret = Init();
   if (!ret)
   {
      ret = MsgLoop();
   }
   Deinit();

   printf("%s: ret=%d\n", __FUNCTION__, ret);

   return ret;
}

static int Init()
{
   int ret = 0;
   const struct sockaddr_un  serverSockaddr = {AF_UNIX, SERVER_SUN_PATH};
   int optval = 1;

   serverSock = socket(AF_UNIX, SOCK_DGRAM, 0);
   if (-1 == serverSock)
   {
      printf("%s: ERROR! socket: %s\n", __FUNCTION__, strerror(errno));
      ret = -1;
   }
   if (!ret && unlink(SERVER_SUN_PATH) && ENOENT != errno)
   {
      printf("%s: ERROR! unlink: %s\n", __FUNCTION__, strerror(errno));
      ret = -1;
   }
   //if (!ret && -1 == setsockopt(serverSock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(int))) {
   //   printf("%s: ERROR! setsockopt: %s\n", __FUNCTION__, strerror(errno));
   //   ret = -1;
   //}
   if (!ret && bind(serverSock, (struct sockaddr *)&serverSockaddr, sizeof(struct sockaddr_un)))
   {
      printf("%s: ERROR! bind: %s\n", __FUNCTION__, strerror(errno));
      ret = -1;
   }

   if (0 != ret)
   {
      Deinit();
   }

   return ret;
}

static int Deinit()
{
   int ret = 0;

   if (-1 != serverSock)
   {
      if (-1 == close(serverSock))
      {
         printf("%s: ERROR! close: %s\n", __FUNCTION__, strerror(errno));
         ret = -1;
      }
   }
   serverSock = -1;
   if (unlink(SERVER_SUN_PATH) && ENOENT != errno)
   {
      printf("%s: ERROR! unlink: %s\n", __FUNCTION__, strerror(errno));
      ret = -1;
   }

   return ret;
}

static int MsgLoop()
{
   ssize_t  sentSize = 0;
   unsigned char buf[4] = {0x4, 0x3, 0x2, 0x1};
   const struct sockaddr_un  clientSockaddr = {AF_UNIX, CLIENT_SUN_PATH};
   int ret = 0;

   while (!ret)
   {
      sentSize = sendto(serverSock, buf, sizeof(buf), 0,
            (struct sockaddr *)&clientSockaddr, sizeof(struct sockaddr_un));
      if (-1 == sentSize && ECONNREFUSED != errno && ENOENT != errno)
      {
         printf("%s: ERROR! sendto: %s\n", __FUNCTION__, strerror(errno));
         ret = -1;
      }

      printf("sent %d bytes\n", sentSize);
      sleep(1);
   }

   return ret;
}
client.c:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#define SERVER_SUN_PATH "/tmp/server_sun_path.0"
#define CLIENT_SUN_PATH "/tmp/client_sun_path.0"

static int Init();
static int Deinit();
static int MsgLoop();

static int  clientSock = -1;

int main(int argc, char *argv[])
{
   int ret = 0;

   ret = Init();
   if (!ret)
   {
      ret = MsgLoop();
   }
   Deinit();

   printf("%s: ret=%d\n", __FUNCTION__, ret);

   return ret;
}

static int Init()
{
   int ret = 0;
   const struct sockaddr_un  clientSockaddr = {AF_UNIX, CLIENT_SUN_PATH};
   int optval = 1;

   clientSock = socket(AF_UNIX, SOCK_DGRAM, 0);
   if (-1 == clientSock)
   {
      printf("%s: ERROR! socket: %s\n", __FUNCTION__, strerror(errno));
      ret = -1;
   }
   if (!ret && unlink(CLIENT_SUN_PATH) && ENOENT != errno)
   {
      printf("%s: ERROR! unlink: %s\n", __FUNCTION__, strerror(errno));
      ret = -1;
   }
   //if (!ret && -1 == setsockopt(clientSock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int))) {
   //   printf("%s: ERROR! setsockopt: %s\n", __FUNCTION__, strerror(errno));
   //   ret = -1;
   //}
   if (!ret && bind(clientSock, (struct sockaddr *)&clientSockaddr, sizeof(struct sockaddr_un)))
   {
      printf("%s: ERROR! bind: %s\n", __FUNCTION__, strerror(errno));
      ret = -1;
   }

   if (0 != ret)
   {
      Deinit();
   }

   return ret;
}

static int Deinit()
{
   int ret = 0;

   if (-1 != clientSock)
   {
      if (-1 == close(clientSock))
      {
         printf("%s: ERROR! close: %s\n", __FUNCTION__, strerror(errno));
         ret = -1;
      }
   }
   clientSock = -1;
   if (unlink(CLIENT_SUN_PATH) && ENOENT != errno)
   {
      printf("%s: ERROR! unlink: %s\n", __FUNCTION__, strerror(errno));
      ret = -1;
   }

   return ret;
}

static int MsgLoop()
{
   ssize_t  recvedSize = 0;
   unsigned char buf[4];
   struct sockaddr_un serverSockaddr;
   socklen_t serverSockaddrLen;
   int ret = 0;
   int i = 0;

   while (!ret)
   {
      memset(buf, 0x00, sizeof(buf));
      serverSockaddrLen = sizeof(struct sockaddr_un);
      recvedSize = recvfrom(clientSock, buf, sizeof(buf), 0,
            (struct sockaddr *)&serverSockaddr, &serverSockaddrLen);
      if (-1 == recvedSize)
      {
         printf("%s: ERROR! recvfrom: %s\n", __FUNCTION__, strerror(errno));
         ret = -1;
      }

      printf("received %d bytes: ", recvedSize);
      for (i = 0; i < recvedSize; i++) {
         printf("%02x,", buf[i]);
      }
      printf("\n");
   }

   return ret;
}
I compile, run server, run client, and open another terminal and run a second client,
When the second client started, the first running client blocks on recvfrom, the second client is receiving msg.
Using setsockopt doesn't change any thing.
Maybe binding two clients to same sun_path is not workable.

My question is: what's the best way of using AF_UNIX SOCK_DGRAM socket to communicate between one server and multiple clients?

(Sorry for my gramma mistake If there is any)
 
Old 10-09-2015, 03:34 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
I tried to run your server, here's the result:
Code:
zsiga-pc:~/proba/sisrnb$ ./server
sent -1 bytes
sent -1 bytes
 
Old 10-12-2015, 04:11 AM   #3
sisrnb
LQ Newbie
 
Registered: Dec 2013
Distribution: debian wheezy
Posts: 23

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by NevemTeve View Post
I tried to run your server, here's the result:
Code:
zsiga-pc:~/proba/sisrnb$ ./server
sent -1 bytes
sent -1 bytes
Yes, that's OK, I purposely did that.
Run server first, then run client, the output of the server will be changed to:
Code:
sent 4 bytes
 
Old 10-12-2015, 04:47 AM   #4
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
I think one of us doesn't understand how server/client architecture works.
 
Old 10-13-2015, 11:29 PM   #5
sisrnb
LQ Newbie
 
Registered: Dec 2013
Distribution: debian wheezy
Posts: 23

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by NevemTeve View Post
I think one of us doesn't understand how server/client architecture works.
Honestly, I'm not familiar with server/client architecture.
I just want to know: what's the best way of sending a same message from one process to several other processes, using AF_UNIX SOCK_DGRAM socket.
Like broadcast, but unix domain datagram socket doesn't support broadcast.
 
Old 10-14-2015, 03:24 AM   #6
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
The server shouldn't send anything before a client asks it to do so.
Every client has to have an unique address.
 
Old 10-14-2015, 04:54 AM   #7
sisrnb
LQ Newbie
 
Registered: Dec 2013
Distribution: debian wheezy
Posts: 23

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by NevemTeve View Post
The server shouldn't send anything before a client asks it to do so.
But, a process using UDP socket can do broadcast even there is no receiver process.
I want to use unix domain datagram socket to do something like UDP broadcast.

Quote:
Originally Posted by NevemTeve View Post
Every client has to have an unique address.
If each client has an unique address (for unix domain datagram socket address is filename), how can I send a same message to all clients simultaneously.
 
Old 10-14-2015, 05:41 AM   #8
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
Combine the two together: clients that are interested in the messages send the server their subscription message 'Hey, I'm here, send me your info'
 
1 members found this post helpful.
Old 04-11-2016, 04:02 AM   #9
sisrnb
LQ Newbie
 
Registered: Dec 2013
Distribution: debian wheezy
Posts: 23

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by NevemTeve View Post
Combine the two together: clients that are interested in the messages send the server their subscription message 'Hey, I'm here, send me your info'
Thanks for the replies!
Now I know unix datagram socket doesn't support broadcast natively.
 
  


Reply

Tags
client, local, multi, socket, unix



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
cgroup socket(PF_NETLINK, SOCK_DGRAM, 11) = -1 EPROTONOSUPPORT olexandr.klymenko Linux - Kernel 2 12-14-2011 07:34 AM
Question about create a socket(PF_PACKET, SOCK_DGRAM, htons(xx)) arrow0815 Linux - Networking 1 11-13-2010 04:44 PM
Question about create a socket(PF_PACKET, SOCK_DGRAM, htons(xx)) arrow0815 Programming 0 11-11-2010 07:58 AM
Wireless clients can't communicate with AIX server jjhawksjj AIX 0 01-09-2007 08:16 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:40 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration