boost库实现UDP通信
2019年4月5日
本博客将会介绍如何通过boost库实现局域网内两台主机之间的通信。(跨公网通信的客户端部分修改而来,跨公网通信需要添加一个服务端,但是客户端部分基本一样)。
具体实现方法赫写套接字大致相同,就是创建端点,实现多线程,这里主线程发消息,子线程收消息。
首先创建一个
io_service
服务,建立端点并开启套接字。
using namespace boost::asio;
io_service io;
ip::udp::endpoint send_up;
ip::udp::socket sock(io,ip::udp::endpont(ip::udp::v4(),6699)); //默认绑定的端口是6699,这儿就已经创建了,待会就不需要再sock.open()了
进行通信的类
class communication{
public:
void startWork();
void doWork();
void workLoop();//这儿的workLoop函数是用来实现循环接受消息的。
private:
std::unique_ptr<std::thread> m_work;
}
void communication::startWork(){
m_work.reset(new thread([&](){workLoop();}))
}
void communication::workLoop(){
while(true){
this::thread::sleep_for(std::chrono::milliseconds(100));//反复刷新,同时防阻塞。
doWork();
}
}
void communication::doWork(){
char recv_buff[1024] = {0};
sock.receive_from(buffer(recv_buff,1024),send_up);//接收消息,并将消息输出。
cout<<recv_buff<<endl;
memset(recv_buff,'\0',1024);
}
上面就是接收端的实现,就是每隔100毫秒就接收一次消息,然后将消息打印出来。
下面这个类是用来拼接ip端口地址这些的,可以不要,在主函数里面实现一步步输入。
class remoteEndpoint{
public :
remoteEndpoint(vector<char> in){
string rep = bufferToStr(in);
int idx = rep.find(":");
this->rmIp = rep.substr(0,idx);
string tmp = rep.substr(idx+1,rep.length()-1);
this->rmPort = boost::lexical_cast<int>(tmp);
}
remoteEndpoint(string rep){
int idx = rep.find(":");
this->rmIp = rep.substr(0,idx);
string tmp=rep.substr(idx+1, rep.length()-1);
this->rmPort=boost::lexical_cast<int>(tmp);
}
~remoteEndpoint(){}
string bufferToStr(vector<char> in) {
string str;
for(int i=0; i<in.size(); i++) {
if(in[i]!=0) str+=in[i];
}
return str;
}
string rmEndpoint;
string rmIp;
int rmPort;
}
在主函数里面完成端点的建立以及发送消息
int main(){
communication m_listener;
string tmp;
cout<<"Please inpput another node's ip:port\n";
cin>>tmp;
remoteEndpoint iServerEp = remoteEndpoint(tmp);
send_up = ip::udp::endpoint(ip::address::from_string(iServerEp.rmIp),iServerEp.rmPort);
iServerEp.~remoteEndpoint();
m_listener.startWorking();
while(true){
string input;
cin>>input;
sock.send_to(buffer(input),send_up);
input.clear();
}
}
下面是完整的代码
#include <boost/lexical_cast.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <stdlib.h>
#include <thread>
#include <chrono>
#include <unistd.h>
using namespace boost::asio;
using namespace std;
io_service io;
ip::udp::endpoint send_up;
ip::udp::socket sock(io,ip::udp::endpont(ip::udp::v4(),6699)); //默认绑定的端口是6699,这儿就已经创建了,待会就不需要再sock.open()了
class communication{
public:
void startWork();
void doWork();
void workLoop();//这儿的workLoop函数是用来实现循环接受消息的。
private:
std::unique_ptr<std::thread> m_work;
}
void communication::startWork(){
m_work.reset(new thread([&](){workLoop();}))
}
void communication::workLoop(){
while(true){
this::thread::sleep_for(std::chrono::milliseconds(100));//反复刷新,同时防阻塞。
doWork();
}
}
void communication::doWork(){
char recv_buff[1024] = {0};
sock.receive_from(buffer(recv_buff,1024),send_up);//接收消息,并将消息输出。
cout<<recv_buff<<endl;
memset(recv_buff,'\0',1024);
}
class remoteEndpoint{
public :
remoteEndpoint(vector<char> in){
string rep = bufferToStr(in);
int idx = rep.find(":");
this->rmIp = rep.substr(0,idx);
string tmp = rep.substr(idx+1,rep.length()-1);
this->rmPort = boost::lexical_cast<int>(tmp);
}
remoteEndpoint(string rep){
int idx = rep.find(":");
this->rmIp = rep.substr(0,idx);
string tmp=rep.substr(idx+1, rep.length()-1);
this->rmPort=boost::lexical_cast<int>(tmp);
}
~remoteEndpoint(){}
string bufferToStr(vector<char> in) {
string str;
for(int i=0; i<in.size(); i++) {
if(in[i]!=0) str+=in[i];
}
return str;
}
string rmEndpoint;
string rmIp;
int rmPort;
}
int main(){
communication m_listener;
string tmp;
cout<<"Please inpput another node's ip:port\n";
cin>>tmp;
remoteEndpoint iServerEp = remoteEndpoint(tmp);
send_up = ip::udp::endpoint(ip::address::from_string(iServerEp.rmIp),iServerEp.rmPort);
iServerEp.~remoteEndpoint();
m_listener.startWorking();
while(true){
string input;
cin>>input;
sock.send_to(buffer(input),send_up);
input.clear();
}
}
Previous
cmake
Newer