一种轻量级C++ 网路通信类库实现

论坛 期权论坛 期权     
程序员空间   2019-7-28 23:29   3801   0
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。socket本质是一套编程接口(API),是对TCP/IP协议的封装。因此,网路编程一般也称作socket编程。
在Java平台上和Windows 的Visual C++上 socket编程已经有完整类库实现,然而在Linux或UNIX平台上,还没有统一的实现标准。前段时间一直做Linux平台上的开发,实现了一个轻量级的Socket类库,在这里介绍一下实现方法,供感兴趣的朋友使用,也欢迎各位大侠批评指正。
该类库代码已上传至github仓库中,下载地址为:https://github.com/xiaoba-8/mixnet

实现方法
              该类库中主要的类的关系如下图所示:


Socket类库类图

       Socket——通用Socket访问类,用TCP协议通信;
       ServerSocket——TCP协议通信的服务端类;
       UdpSocket——UDP协议通信访问类;
       UdpServerSocket——UDP协议通信的服务端类;
TcpServerDaemon——一个简易的TCP服务器实现类,可以简化服务端的编程;
ITCPSocketHandler——TcpServerDaemon实现的服务器业务访问接口,用于TCP服务器上业务的实现;
UdpServerDaemon——一个简易的UDP服务器实现类,可以简化服务端的编程;
IUDPSocketHandler——UdpServerDaemon实现的服务器业务访问接口,用于UDP服务器上业务的实现;

类库的安装方法
  • 下载类库实现源代码:https://github.com/xiaoba-8/mixnet
  • 进入类库根文件夹依次执行configure,make, make install

使用方法
TCP协议通信服务端实现代码示例
       服务端实现有两种方式,直接使用ServerSocket创建,或者使用TcpServerDaemon创建,下面分别给出两种方式创建的代码示例。
      
1. 直接使用ServerSocket实现的代码示例
#include
#include
#include
#include
#include

int main(int argc, char *argv[])
{
mix::ServerSocket serverSocket(7000);
serverSocket.SetReuseAddress(true);

mix::Socket *pSocket;

printf("Tcp Server Demo started!\n");

while (true)
{
  try
  {
   pSocket = serverSocket.Accept(5);
  }
  catch (mix::NetException &e)
  {
   continue;
  }
  if (pSocket == NULL) continue;

  pid_t pid = fork();

  if (pid == 0)
  {
   pid = fork();
   if (pid > 0)
   {
    exit(0);
   }
   else if (pid == 0)
   {
    char buffer[500];

    int len = 0;
    int size = 0;
    do
    {
     len = pSocket->Recv(buffer, 500);
     size += len;
    } while (len > 0);

    printf("Received [%d] bytes\n", size);

    memset(buffer, 0, 500);
    sprintf(buffer, "OK, Received [%d] bytes", size);
    std::string response = buffer;

    pSocket->WriteUTF(response);

    pSocket->Close();

    exit(0);
   }
   else
   {
    perror("fork error");
   }
  }
  else if (pid > 0)
  {
   if (waitpid(pid, NULL, 0) != pid)
   {
    perror("waitpid error");
   }
  }
  else
  {
   perror("fork error");
  }
}
return 0;
}



2. 使用TcpServerDaemon实现的代码示例

#include
#include
#include
#include

class TcpServerDemoHandler : public mix::ITCPSocketHandler
{
public:
virtual void Handler(mix::Socket *pSocket)
{
  char buffer[500];

  int len = 0;
  int size = 0;
  do
  {
   len = pSocket->Recv(buffer, 500);
   size += len;
  } while (len > 0);

  printf("Received [%d] bytes\n", size);

  memset(buffer, 0, 500);
  sprintf(buffer, "OK, Received [%d] bytes", size);
  std::string response = buffer;

  pSocket->WriteUTF(response);
  pSocket->Close();
}

virtual std::string GetTaskId() { return "demo"; }
};

int main(int argc, char *argv[])
{
TcpServerDemoHandler tcpHander;

mix::ServerDaemon serverDaemon(NULL, 7000, &tcpHander, true);
printf("Tcp Server Daemon Demo started!\n");

serverDaemon.RunLoop();
return 0;
}


TCP协议通信客户端实现代码示例

#include
#include

int main(int argc, char *argv)
{
mix::Socket socket;

char buffer[1024];
memset(buffer, 'a', 1024);

try
{
  socket.Connect("127.0.0.1", 7000, 5);
  socket.SetWriteTimeout(5);
  socket.SetReadTimeout(5);

  for (int i = 0; i < 2; i++)
  {
   socket.WriteUntil(buffer, 1024);
  }

  socket.ShutdownOutput();
  std::string response = socket.ReadUTF();
  socket.ShutdownInput();
  socket.Close();

  printf("Receive Response From Server: \n   %s\n", response.c_str());
}
catch (mix::NetException &ex)
{
  printf("Error Message: %s\n", ex.what());
}
return 0;
}

UDP协议通信服务端实现代码示例
       服务端实现有两种方式,直接使用UdpServerSocket创建,或者使用UdpServerDaemon创建,下面分别给出两种方式创建的代码示例。
      
1. 直接使用UdpServerSocket实现的代码示例

#include
#include
#include
#include
#include

#define UDP_PACKAGE_MAX_LENGTH 2000
#define UDP_REMOTE_IP_LENGTH 100

int main(int argc, char *argv[])
{
mix::UdpServerSocket serverSocket(7000);
serverSocket.SetReuseAddress(true);

int nRet;
char buffer[UDP_PACKAGE_MAX_LENGTH];
char remoteAddr[UDP_REMOTE_IP_LENGTH];
int remotePort;

printf("Udp Server Demo started!\n");

while (true)
{
  try
  {
   nRet = serverSocket.RecvFrom(buffer, 2000, remoteAddr, &remotePort);
   if (nRet  0)
   {
    exit(0);
   }
   else if (pid == 0)
   {
    char buffer[500];
    int len = nRet;

    printf("Received Pkg length = %d from %s:%d\n", len, remoteAddr, remotePort);

    memset(buffer, 0, 500);
    sprintf(buffer, "OK, Received [%d] bytes", len);
    std::string response = buffer;

    serverSocket.SendTo(response, (const char *)remoteAddr, remotePort);

    exit(0);
   }
   else
   {
    perror("fork error");
   }
  }
  else if (pid > 0)
  {
   if (waitpid(pid, NULL, 0) != pid)
   {
    perror("waitpid error");
   }
  }
  else
  {
   perror("fork error");
  }
}

return 0;
}

2. 使用UdpServerDaemon实现的代码示例

#include
#include
#include
#include

class UdpSocketHandler : public mix::IUDPSocketHandler
{
public:
virtual void Handler(mix::UdpSocket *pSocket, char *pBuffer, int len,
   char *remoteIp, int remotePort)
{
  char buffer[500];

  printf("Received Pkg length = %d from %s:%d\n", len, remoteIp, remotePort);

  memset(buffer, 0, 500);
  sprintf(buffer, "OK, Received [%d] bytes", len);
  std::string response = buffer;

  pSocket->SendTo(response, (const char *)remoteIp, remotePort);
}

virtual std::string GetTaskId() { return "demo"; }
};

int main(int argc, char *argv[])
{
UdpSocketHandler udpHander;
mix::UdpServerDaemon serverDaemon(NULL, 7000, &udpHander, true);

printf("Udp Server Daemon Demo started!\n");
serverDaemon.RunLoop();
return 0;
}

UDP协议通信客户端实现代码示例

#include
#include

#define UDP_REMOTE_IP_LENGTH 100

int main(int argc, char *argv)
{
mix::UdpSocket socket;
char buffer[1024];
memset(buffer, 'a', 1024);

int nRet;
char remoteAddr[UDP_REMOTE_IP_LENGTH];
int remotePort;

try
{
  socket.SendTo(buffer, 1024, "127.0.0.1", 7000);

  memset(buffer, 0, 1024);
  nRet = socket.RecvFrom(buffer, 2000, remoteAddr, &remotePort);

  socket.Close();
  printf("Receive Response From Server: \n   %s\n", buffer);
}
catch (mix::NetException &ex)
{
  printf("Error Message: %s\n", ex.what());
}
return 0;
}


编译方法
可以执行以下命令进行编译,(假设mixnet安装在/usr/local目录下),其中src_xxx需要替换为您要编译的源文件名称,[out_xxx]替换为目标程序名称
g++ -I/usr/local/include -g -O2 [src_xxx].cpp -o [out_xxx]-lmixnet -pthread -Wl,-rpath -Wl,/usr/local/lib

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:10
帖子:2
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP