UDP相关逻辑在udp.h/cpp文件中。
发送
直接上代码
class UDPSend : public Thread //继承自Thread,线程相关信息略
{
public:
UDPSend();
~UDPSend(); //释放资源
int Init(); //初始化socket
void run();
void Stop();
int AddMessage(const std::string & sIP, const int iPort, const std::string & sMessage); //将信息放到内部queue中。
//每一个消息的内容接收端的IP,端口,消息
struct QueueData
{
std::string m_sIP;
int m_iPort;
std::string m_sMessage;
};
private:
void SendMessage(const std::string & sIP, const int iPort, const std::string & sMessage); //真正的将消息投递出去
private:
Queue<QueueData *> m_oSendQueue;
int m_iSockFD;
bool m_bIsEnd;
bool m_bIsStarted;
};
UDPSend :: UDPSend() : m_iSockFD(-1), m_bIsEnd(false), m_bIsStarted(false)
{
}
UDPSend :: ~UDPSend()
{
while (!m_oSendQueue.empty())
{
QueueData * poData = m_oSendQueue.peek();
m_oSendQueue.pop();
delete poData;
}
}
int UDPSend :: Init()
{
if ((m_iSockFD = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
return -1;
}
return 0;
}
void UDPSend :: Stop()
{
if (m_bIsStarted)
{
m_bIsEnd = true;
join();
}
}
void UDPSend :: SendMessage(const std::string & sIP, const int iPort, const std::string & sMessage)
{
struct sockaddr_in addr;
int addr_len = sizeof(struct sockaddr_in);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(iPort);
addr.sin_addr.s_addr = inet_addr(sIP.c_str());
int ret = sendto(m_iSockFD, sMessage.data(), (int)sMessage.size(), 0, (struct sockaddr *)&addr, addr_len);
if (ret > 0)
{
BP->GetNetworkBP()->UDPRealSend(sMessage);
}
}
void UDPSend :: run()
{
m_bIsStarted = true;
while(true)
{
QueueData * poData = nullptr;
m_oSendQueue.lock();
bool bSucc = m_oSendQueue.peek(poData, 1000);
if (bSucc)
{
m_oSendQueue.pop();
}
m_oSendQueue.unlock();
if (poData != nullptr)
{
SendMessage(poData->m_sIP, poData->m_iPort, poData->m_sMessage);
delete poData;
}
if (m_bIsEnd)
{
PLHead("UDPSend [END]");
return;
}
}
}
int UDPSend :: AddMessage(const std::string & sIP, const int iPort, const std::string & sMessage)
{
m_oSendQueue.lock();
if ((int)m_oSendQueue.size() > UDP_QUEUE_MAXLEN)
{
BP->GetNetworkBP()->UDPQueueFull();
//PLErr("queue length %d too long, can't enqueue", m_oSendQueue.size());
m_oSendQueue.unlock();
return -2;
}
QueueData * poData = new QueueData;
poData->m_sIP = sIP;
poData->m_iPort = iPort;
poData->m_sMessage = sMessage;
m_oSendQueue.add(poData);
m_oSendQueue.unlock();
return 0;
}
发送从整体上看就是一个多生产者但消费者的模型。其内部数据使用指针(这个待讨论:是否有必要使用指针,不使用指针的话资源拷贝消耗分析等有待进一步讨论)
接收
class UDPRecv : public Thread
{
public:
//传递网络部分指针,与paxos网络部分关联起来(DFNetWork 继承自NetWork)
UDPRecv(DFNetWork * poDFNetWork);
~UDPRecv();
int Init(const int iPort); //创建socket,设置属性并绑定
//检测绑定socket的pollin事件,接收信息并将接收信息放入整个网络处理逻辑中(NetWork->OnReceiveMessage)
void run();
void Stop();
private:
DFNetWork * m_poDFNetWork;
int m_iSockFD;
bool m_bIsEnd;
bool m_bIsStarted;
};
UDPRecv :: UDPRecv(DFNetWork * poDFNetWork)
: m_poDFNetWork(poDFNetWork), m_iSockFD(-1), m_bIsEnd(false), m_bIsStarted(false)
{
}
UDPRecv :: ~UDPRecv()
{
if (m_iSockFD != -1)
{
close(m_iSockFD);
m_iSockFD = -1;
}
}
void UDPRecv :: Stop()
{
if (m_bIsStarted)
{
m_bIsEnd = true;
join();
}
}
int UDPRecv :: Init(const int iPort)
{
if ((m_iSockFD = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
return -1;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(iPort);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
int enable = 1;
setsockopt(m_iSockFD, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
if (bind(m_iSockFD, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
return -1;
}
return 0;
}
void UDPRecv :: run()
{
m_bIsStarted = true;
char sBuffer[65536] = {0};
struct sockaddr_in addr;
socklen_t addr_len = sizeof(struct sockaddr_in);
memset(&addr, 0, sizeof(addr));
while(true)
{
if (m_bIsEnd)
{
PLHead("UDPRecv [END]");
return;
}
struct pollfd fd;
int ret;
fd.fd = m_iSockFD;
fd.events = POLLIN;
ret = poll(&fd, 1, 500);
if (ret == 0 || ret == -1)
{
continue;
}
int iRecvLen = recvfrom(m_iSockFD, sBuffer, sizeof(sBuffer), 0,
(struct sockaddr *)&addr, &addr_len);
//printf("recvlen %d, buffer %s client %s\n",
//iRecvLen, sBuffer, inet_ntoa(addr.sin_addr));
BP->GetNetworkBP()->UDPReceive(iRecvLen);
if (iRecvLen > 0)
{
m_poDFNetWork->OnReceiveMessage(sBuffer, iRecvLen);
}
}
}
OK上面的所有部分就是UDP相关的所有逻辑