《IPC之unix domain socket》

版权声明:copyright@xxdk2017 https://blog.csdn.net/u011583798/article/details/78502026

1.socket_server.h

#ifndef RKIPC_SOCKET_SERVER_H_
#define RKIPC_SOCKET_SERVER_H_

#include <unistd.h>

// SocketServer, use to receive message from client
// TODO, only support only one connection
class SocketServer {
public:
  SocketServer() {
    fd_ = -1;
    client_fd_ = -1;
  }

  virtual ~SocketServer() {
    Disconnect();

    if (fd_ >= 0) {
      close(fd_);
      fd_ = -1;
    }
  }

  // Create a server endpoint of a connection.
  // Returns true if socket fd is OK.
  bool Listen(const char* server_name);

  void Disconnect(void) {
    if (client_fd_ >= 0) {
      close(client_fd_);
      client_fd_ = -1;
    }
  }

  // Wait a client connection
  bool Accept(void);

  // Receive messages from the client
  bool Receive(char* buf, size_t len);

  static const int kMaxConnection;

private:
  int fd_;
  int client_fd_;
};


#endif // RKIPC_SOCKET_SERVER_H_

2.socket_server.cpp

#include "socket_server.h"

#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stddef.h>
#include <errno.h>

#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>

const int SocketServer::kMaxConnection = 8;

bool SocketServer::Listen(const char* server_name) {
  assert(server_name != NULL);
  assert(fd_ < 0);

  printf("SocketServer: Listen to %s.\n", server_name);
	// address family(AF)
	// protcal family(PF)
	// AF_UNIX = AF_LOCAL
  int fd = socket(AF_UNIX, SOCK_STREAM, 0);
  if (fd < 0) {
    printf("SocketServer: Create server socket failed.\n");
    return false;
  }

  struct sockaddr_un sun;
  unlink(server_name);
  memset(&sun, 0, sizeof(sun));
	// AF_UNIX = AF_LOCAL
  sun.sun_family = AF_UNIX;
  strcpy(sun.sun_path, server_name);
  // UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,
  // 这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回
  int len = offsetof(struct sockaddr_un, sun_path) + strlen(server_name);
  if (int ret = bind(fd, (struct sockaddr *)&sun, len) < 0) {
    printf("SocketServer: Bind socket failed, ret=%d.\n", ret);
    close(fd);
    return false;
  }

  if (listen(fd, kMaxConnection) < 0) {
    printf("SocketServer: Listen socket failed.\n");
    close(fd);
    return false;
  }

  fd_ = fd;
  return true;
}

bool SocketServer::Accept(void) {
  assert(client_fd_ < 0);

  printf("SocketServer: Wait a client connection.\n");

  int client_fd = -1;
  struct sockaddr_un sun;
  int len = sizeof(sun);
  while (1) {
    client_fd = accept(fd_, (struct sockaddr *)&sun, (socklen_t *)&len);
    if (client_fd < 0) {
      if (EINTR == errno) {
        printf("SocketServer: Accept failed by EINTR, continue.\n");
        continue;
      } else {
        printf("SocketServer: Accept failed, errno=%d.\n", errno);
        return false;
      }
    }
    break;
  }

  len -= offsetof(struct sockaddr_un, sun_path);
  sun.sun_path[len] = 0;

  // Don't check stat which maybe cause call stat failed.
  // Comment these codes to work round this bug.
  //
  // struct stat statbuf;
  // if (int ret = stat(sun.sun_path, &statbuf)) {
  //   close(client_fd);
  //   printf("SocketServer: Call stat failed, ret=%d.\n", ret);
  //   return false;
  // }

  // if (!S_ISSOCK(statbuf.st_mode)) {
  //   printf("SocketServer: Invalid socket.\n");
  //   close(client_fd);
  //   return false;
  // }

  // unlink(sun.sun_path);
  client_fd_ = client_fd;
  return true;
}

bool SocketServer::Receive(char* buf, size_t len) {
  assert(buf != NULL);
  assert(len > 0);

  printf("SocketServer: Ready to receive message from client.\n");

  const int received_bytes = recv(client_fd_, buf, len, 0);
  if (received_bytes < -2) {
    printf("SocketServer: Failed to reveived data.\n");
    return false;
  }

  printf("SocketServer: Reveived a message: %s.\n", buf);
  return true;
}

3.socket_client.h

#ifndef RKIPC_SOCKET_CLIENT_H_
#define RKIPC_SOCKET_CLIENT_H_

#include <unistd.h>

class SocketClient {
public:
  SocketClient() {
    fd_ = -1;
  }

  virtual ~SocketClient() {
    Disconnect();
  }

  // Create a client endpoint and connect to a server.
  // If success the client socket fd will be save in fd_
  // and return true else retrun false.
  bool Connect(const char* server_name);

  // Disconnect the connection to server socket.
  void Disconnect(void) {
    if (fd_ > 0) {
      close(fd_);
      fd_ = -1;
    }
  }

  // Send a message to the connected server.
  bool Send(const char* msg);

private:
  int fd_;
};


#endif // RKIPC_SOCKET_CLIENT_H_

4.socket_client.cpp

#include "socket_client.h"

#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stddef.h>

#include <sys/un.h>
#include <sys/socket.h>

bool SocketClient::Connect(const char* server_name) {
  assert(server_name != NULL);
  assert(fd_ < 0);

  int fd = socket(AF_UNIX, SOCK_STREAM, 0);
  if (fd < 0) {
    printf("SocketClient: Create socket failed.\n");
    return false;
  }

  // Fill socket address structure with our address.
  struct sockaddr_un sun;
  memset(&sun, 0, sizeof(sun));
  sun.sun_family = AF_UNIX;
  sprintf(sun.sun_path, "/tmp/socket/ipc%05d.sock", getpid());
  int len = offsetof(struct sockaddr_un, sun_path) + strlen(sun.sun_path);
  unlink(sun.sun_path);
  if (bind(fd, (struct sockaddr *)&sun, len) < 0) {
    printf("SocketClient: Bind socket failed.\n");
    close(fd);
    return false;
  }

  // Fill socket address structure with server's address.
  memset(&sun, 0, sizeof(sun));
  sun.sun_family = AF_UNIX;
  strcpy(sun.sun_path, server_name);
  len = offsetof(struct sockaddr_un, sun_path) + strlen(server_name);
  if (connect(fd, (struct sockaddr *)&sun, len) < 0) {
    printf("SocketClient: Bind server socket failed.\n");
    close(fd);
    return false;
  }

  fd_ = fd;
  return true;
}

bool SocketClient::Send(const char* msg) {
  assert(msg != NULL);
  assert(fd_ >= 0);

  int len = strlen(msg);
  printf("SocketClient: Send a message to server: %s.\n", msg);
  int send_bytes = send(fd_, msg, len, 0);
  if (send_bytes < -1) {
    printf("SocketClient: Send message to server failed.\n");
    return false;
  }

  return true;
}



猜你喜欢

转载自blog.csdn.net/u011583798/article/details/78502026