来源
研究这个东西是因为,导师的一个项目的甲方要求使用这种方式进行交互,我们这里是一个C++后台,用这种方式去拿到一些配置文件,虽然这种做法后来老师放弃了,但是研究了一天实现出来,贴出来希望能帮到有需要的人
可能遇到的问题
收发的过程就是简单的C++的UDP的通信,唯一可能的问题就是编码上,因为XML大多数指定编码都是UTF-8,也就是多字节字符串,如果我们直接去读取的话,读出来是乱码,所以需要进行一下转换
码来!
XML文件
<?xml version="1.0" encoding="utf-8"?>
<mesh name='sphere你好'>
<bounds>0 0 1 1</bounds>
</mesh>
注意这里有一句中文,
发送端代码
using namespace std;
string read(const char*);
std::string WstringToString(const std::wstring str);
int main()
{
WSADATA wsaData;//初始化
SOCKET SendSocket;
sockaddr_in RecvAddr;//服务器地址
int Port = 7777;//服务器监听地址
string xml_string = read("XMLFile.xml");
char SendBuf[1024];
strcpy(SendBuf, xml_string.c_str());
int BufLen = 1024;//缓冲区大小
//初始化Socket
WSAStartup(MAKEWORD(2, 2), &wsaData);
//创建Socket对象
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//设置服务器地址
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//向服务器发送数据报
printf("Sending a datagram to the receiver...\n");
sendto(SendSocket, SendBuf, BufLen, 0, (SOCKADDR*)&RecvAddr, sizeof(RecvAddr));
cout << "send" << SendBuf << endl;
//发送完成,关闭Socket
printf("finished sending,close socket.\n");
closesocket(SendSocket);
WSACleanup();
printf("Exting.\n");
return 0;
}
std::string WstringToString(const std::wstring str)
{// wstring转string
unsigned len = str.size() * 4;
setlocale(LC_CTYPE, "");
char* p = new char[len];
wcstombs(p, str.c_str(), len);
std::string str1(p);
delete[] p;
return str1;
}
string read(const char* path)
{
char* buf = new char;
string strfile;
ifstream fin(path);
wstring res;
string rres;
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
while (getline(fin, strfile))
{
wstring wb = conv.from_bytes(strfile);//转为宽字符
res += wb;
}
fin.close();
return WstringToString(res);
}
如果不转为宽字符的话,中文会乱码,大家打个断点就看出了,那么上面的代码为什么要把宽字符转为String呢,因为我们在sendto的时候只能发const char *,所以我们需要转换一下
接收解析端代码
using namespace std;
void Read(char*);
int main()
{
WSADATA wsaData;//初始化
SOCKET RecvSocket;
sockaddr_in RecvAddr;//服务器地址
int Port = 7777;//服务器监听地址
char RecvBuf[1024];//发送数据的缓冲区
int BufLen = 1024;//缓冲区大小
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof(SenderAddr);
//初始化Socket
WSAStartup(MAKEWORD(2, 2), &wsaData);
//创建接收数据报的socket
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//将socket与制定端口和0.0.0.0绑定
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(RecvSocket, (SOCKADDR*)&RecvAddr, sizeof(RecvAddr));
//调用Recvfrom函数在绑定的socket上接收数据
int len2recv = recvfrom(RecvSocket, RecvBuf, BufLen, 0, (SOCKADDR*)&SenderAddr, &SenderAddrSize);
cout << RecvBuf << endl;
Read(RecvBuf);
//关闭socket,结束接收数据
closesocket(RecvSocket);
//释放资源,退出
printf("Exiting.\n");
WSACleanup();
return 0;
}
void Read(char* source)
{
int size = sizeof(source);
cout << "Read:\n" << source << endl;
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_string(source);
std::cout << "Load result: " << result.description() << ", mesh name: "
<< doc.child("mesh").attribute("name").value() << std::endl;
}
这里使用的pugi是一个轻量级的XML解析的C++开源库,网上有资料
运行结果截图
发送端:
接收端:
欢迎大家在下方交流讨论,如果帮到了需要的人,点个赞,奥利给!!