网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个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
|
|