C++ 使用C++/boost::asio
使用g++和boost::asio,我试图格式化包含要传输的数据大小的网络消息帧:C++ 使用C++/boost::asio,c++,networking,boost,boost-asio,C++,Networking,Boost,Boost Asio,使用g++和boost::asio,我试图格式化包含要传输的数据大小的网络消息帧: +----------------+------------------------+ | Length | Message string | | 4 bytes | n bytes | +----------------+------------------------+ 使用32字节Linux下asio阻塞tcp echo客户机/服
+----------------+------------------------+
| Length | Message string |
| 4 bytes | n bytes |
+----------------+------------------------+
使用32字节Linux下asio阻塞tcp echo客户机/服务器的示例,我对在帧中传输正确的大小感到厌倦。客户端应该是一台Windows计算机
客户:
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include <stdint.h>
#include <arpa/inet.h>
using boost::asio::ip::tcp;
enum { max_length = 1024 };
int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
return 1;
}
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), argv[1], argv[2]);
tcp::resolver::iterator iterator = resolver.resolve(query);
tcp::socket s(io_service);
s.connect(*iterator);
std::cout << "sizeof uint32_t=" << sizeof(uint32_t) << std::endl;
uint32_t len = 1234;
std::cout << "len=" << len << std::endl;
// uint => char 4
char char_len[4];
char_len[0] = (len >> 0);
char_len[1] = (len >> 8);
char_len[2] = (len >> 16);
char_len[3] = (len >> 24);
std::cout << "char[4] len=["
<< char_len[0] << ',' << char_len[1] << ','
<< char_len[2] << ',' << char_len[3] << ']'
<< std::endl;
// char 4 => uint
uint32_t uint_len = *(reinterpret_cast<uint32_t *>( char_len ));
std::cout << "uint len=" << uint_len << std::endl;
// network bytes order
uint32_t net_len = htonl( len );
std::cout << "net_len=" << net_len << std::endl;
// uint => char 4
char net_char_len[4];
net_char_len[0] = (net_len >> 0);
net_char_len[1] = (net_len >> 8);
net_char_len[2] = (net_len >> 16);
net_char_len[3] = (net_len >> 24);
std::cout << "net char[4] len=["
<< net_char_len[0] << ',' << net_char_len[1] << ','
<< net_char_len[2] << ',' << net_char_len[3] << ']'
<< std::endl;
boost::asio::write(s, boost::asio::buffer(char_len, 4));
char reply[max_length];
size_t reply_length = boost::asio::read(s,
boost::asio::buffer(reply, 1 ));
std::cout << "Reply is: ";
std::cout.write(reply, reply_length);
std::cout << "\n";
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include <stdint.h>
#include <arpa/inet.h>
using boost::asio::ip::tcp;
enum { max_length = 1024 };
int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
return 1;
}
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), argv[1], argv[2]);
tcp::resolver::iterator iterator = resolver.resolve(query);
tcp::socket s(io_service);
s.connect(*iterator);
std::cout << "sizeof uint32_t=" << sizeof(uint32_t) << std::endl;
uint32_t len = 1234;
std::cout << "len=" << len << std::endl;
// uint => char 4
char char_len[4];
char_len[0] = (len >> 0);
char_len[1] = (len >> 8);
char_len[2] = (len >> 16);
char_len[3] = (len >> 24);
std::cout << "char[4] len=["
<< char_len[0] << ',' << char_len[1] << ','
<< char_len[2] << ',' << char_len[3] << ']'
<< std::endl;
// char 4 => uint
uint32_t uint_len = *(reinterpret_cast<uint32_t *>( char_len ));
std::cout << "uint len=" << uint_len << std::endl;
// network bytes order
uint32_t net_len = htonl( len );
std::cout << "net_len=" << net_len << std::endl;
// uint => char 4
char net_char_len[4];
net_char_len[0] = (net_len >> 0);
net_char_len[1] = (net_len >> 8);
net_char_len[2] = (net_len >> 16);
net_char_len[3] = (net_len >> 24);
std::cout << "net char[4] len=["
<< net_char_len[0] << ',' << net_char_len[1] << ','
<< net_char_len[2] << ',' << net_char_len[3] << ']'
<< std::endl;
std::cout << "net char[4] len=["
<< (int)net_char_len[0] << ',' << (int)net_char_len[1] << ','
<< (int)net_char_len[2] << ',' << (int)net_char_len[3] << ']'
<< std::endl;
boost::asio::write(s, boost::asio::buffer( net_char_len, 4));
/*
char reply[max_length];
size_t reply_length = boost::asio::read(s, boost::asio::buffer(reply, 1 ));
std::cout << "Reply is: ";
std::cout.write(reply, reply_length);
std::cout << "\n";
*/
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
客户端无法解码长度,服务器似乎没有收到正确的irt。我遗漏了什么?从您的代码中可以看出,您实际上没有发送网络字节顺序,您的send语句类似于:
boost::asio::write(s,boost::asio::buffer(char_len,4))代码>和char\u len
看起来像是按主机顺序填写的
可能您应该提供日志语句的输出-这可能会让事情更清楚一些…从我在代码中看到的,您实际上没有发送网络字节顺序,您的send语句类似于:boost::asio::write(s,boost::asio::buffer(char_len,4))代码>和char\u len
看起来像是按主机顺序填写的
可能您应该提供日志语句的输出-这可能会让事情更清楚一些…一个问题似乎是客户端发送一些数据,然后希望接收一些数据并将其发送回服务器,但服务器执行两次读取,然后发送一些数据。因此,第二个read()可能会收到0个字节
此外,只要有一些字节可用,read()函数就会读取。在这种情况下,即使客户端执行2 write(),服务器也可以使用第一次读取()读取所有字节,第二次读取()仍将看到0字节。您必须根据协议处理存储在缓冲区中的数据
从len到char_len的转换将无法按预期工作。由于char_len数组包含char,因此无法尝试在屏幕上显示char,但任何低于32的值都无法显示。如果您想显示每个字符的ASCII值,就必须在将它们赋给cout之前将它们转换为int
您只需按原样发送“len”:
但我没有看到任何信息发送到您的样本。我只看到客户端和服务器之间交换了一些长度
这就是我根据代码所能说的
编辑:我把字节顺序留了下来,让响应保持简短。一个问题似乎是客户端发送一些数据,然后想要接收一些数据并将其发送回服务器,但服务器进行了两次读取,然后发送一些数据。因此,第二个read()可能会收到0个字节
此外,只要有一些字节可用,read()函数就会读取。在这种情况下,即使客户端执行2 write(),服务器也可以使用第一次读取()读取所有字节,第二次读取()仍将看到0字节。您必须根据协议处理存储在缓冲区中的数据
从len到char_len的转换将无法按预期工作。由于char_len数组包含char,因此无法尝试在屏幕上显示char,但任何低于32的值都无法显示。如果您想显示每个字符的ASCII值,就必须在将它们赋给cout之前将它们转换为int
您只需按原样发送“len”:
但我没有看到任何信息发送到您的样本。我只看到客户端和服务器之间交换了一些长度
这就是我根据代码所能说的
编辑:我保留了字节顺序,以保持响应简短。我终于找到了出错的地方
服务器代码的底部有一个剩余读取,这阻止了第二个读取正确的字节,如@PRouleau所说
正如@Nim所指出的,客户机也编写了错误的变量
服务器的错误检查不在正确的位置
最后,我得出以下结论:
客户:
sizeof uint32_t=4
len=1234
uint len=1234
net_len=3523477504
net char[4] len=[0,0,4,-46]
服务器:
Started
sizeof uint32_t=4
net len=3523477504
uint len=1234
使用以下代码:
客户:
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include <stdint.h>
#include <arpa/inet.h>
using boost::asio::ip::tcp;
enum { max_length = 1024 };
int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
return 1;
}
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), argv[1], argv[2]);
tcp::resolver::iterator iterator = resolver.resolve(query);
tcp::socket s(io_service);
s.connect(*iterator);
std::cout << "sizeof uint32_t=" << sizeof(uint32_t) << std::endl;
uint32_t len = 1234;
std::cout << "len=" << len << std::endl;
// uint => char 4
char char_len[4];
char_len[0] = (len >> 0);
char_len[1] = (len >> 8);
char_len[2] = (len >> 16);
char_len[3] = (len >> 24);
std::cout << "char[4] len=["
<< char_len[0] << ',' << char_len[1] << ','
<< char_len[2] << ',' << char_len[3] << ']'
<< std::endl;
// char 4 => uint
uint32_t uint_len = *(reinterpret_cast<uint32_t *>( char_len ));
std::cout << "uint len=" << uint_len << std::endl;
// network bytes order
uint32_t net_len = htonl( len );
std::cout << "net_len=" << net_len << std::endl;
// uint => char 4
char net_char_len[4];
net_char_len[0] = (net_len >> 0);
net_char_len[1] = (net_len >> 8);
net_char_len[2] = (net_len >> 16);
net_char_len[3] = (net_len >> 24);
std::cout << "net char[4] len=["
<< net_char_len[0] << ',' << net_char_len[1] << ','
<< net_char_len[2] << ',' << net_char_len[3] << ']'
<< std::endl;
boost::asio::write(s, boost::asio::buffer(char_len, 4));
char reply[max_length];
size_t reply_length = boost::asio::read(s,
boost::asio::buffer(reply, 1 ));
std::cout << "Reply is: ";
std::cout.write(reply, reply_length);
std::cout << "\n";
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include <stdint.h>
#include <arpa/inet.h>
using boost::asio::ip::tcp;
enum { max_length = 1024 };
int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
return 1;
}
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), argv[1], argv[2]);
tcp::resolver::iterator iterator = resolver.resolve(query);
tcp::socket s(io_service);
s.connect(*iterator);
std::cout << "sizeof uint32_t=" << sizeof(uint32_t) << std::endl;
uint32_t len = 1234;
std::cout << "len=" << len << std::endl;
// uint => char 4
char char_len[4];
char_len[0] = (len >> 0);
char_len[1] = (len >> 8);
char_len[2] = (len >> 16);
char_len[3] = (len >> 24);
std::cout << "char[4] len=["
<< char_len[0] << ',' << char_len[1] << ','
<< char_len[2] << ',' << char_len[3] << ']'
<< std::endl;
// char 4 => uint
uint32_t uint_len = *(reinterpret_cast<uint32_t *>( char_len ));
std::cout << "uint len=" << uint_len << std::endl;
// network bytes order
uint32_t net_len = htonl( len );
std::cout << "net_len=" << net_len << std::endl;
// uint => char 4
char net_char_len[4];
net_char_len[0] = (net_len >> 0);
net_char_len[1] = (net_len >> 8);
net_char_len[2] = (net_len >> 16);
net_char_len[3] = (net_len >> 24);
std::cout << "net char[4] len=["
<< net_char_len[0] << ',' << net_char_len[1] << ','
<< net_char_len[2] << ',' << net_char_len[3] << ']'
<< std::endl;
std::cout << "net char[4] len=["
<< (int)net_char_len[0] << ',' << (int)net_char_len[1] << ','
<< (int)net_char_len[2] << ',' << (int)net_char_len[3] << ']'
<< std::endl;
boost::asio::write(s, boost::asio::buffer( net_char_len, 4));
/*
char reply[max_length];
size_t reply_length = boost::asio::read(s, boost::asio::buffer(reply, 1 ));
std::cout << "Reply is: ";
std::cout.write(reply, reply_length);
std::cout << "\n";
*/
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用boost::asio::ip::tcp;
枚举{max_length=1024};
int main(int argc,char*argv[])
{
尝试
{
如果(argc!=3)
{
标准:cerr 16);
char_len[3]=(len>>24);
我终于找到了哪里出了问题
服务器代码的底部有一个剩余读取,这阻止了第二个读取正确的字节,如@PRouleau所说
正如@Nim所指出的,客户机也编写了错误的变量
服务器的错误检查不在正确的位置
最后,我得出以下结论:
客户:
sizeof uint32_t=4
len=1234
uint len=1234
net_len=3523477504
net char[4] len=[0,0,4,-46]
服务器:
Started
sizeof uint32_t=4
net len=3523477504
uint len=1234
使用以下代码:
客户:
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include <stdint.h>
#include <arpa/inet.h>
using boost::asio::ip::tcp;
enum { max_length = 1024 };
int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
return 1;
}
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), argv[1], argv[2]);
tcp::resolver::iterator iterator = resolver.resolve(query);
tcp::socket s(io_service);
s.connect(*iterator);
std::cout << "sizeof uint32_t=" << sizeof(uint32_t) << std::endl;
uint32_t len = 1234;
std::cout << "len=" << len << std::endl;
// uint => char 4
char char_len[4];
char_len[0] = (len >> 0);
char_len[1] = (len >> 8);
char_len[2] = (len >> 16);
char_len[3] = (len >> 24);
std::cout << "char[4] len=["
<< char_len[0] << ',' << char_len[1] << ','
<< char_len[2] << ',' << char_len[3] << ']'
<< std::endl;
// char 4 => uint
uint32_t uint_len = *(reinterpret_cast<uint32_t *>( char_len ));
std::cout << "uint len=" << uint_len << std::endl;
// network bytes order
uint32_t net_len = htonl( len );
std::cout << "net_len=" << net_len << std::endl;
// uint => char 4
char net_char_len[4];
net_char_len[0] = (net_len >> 0);
net_char_len[1] = (net_len >> 8);
net_char_len[2] = (net_len >> 16);
net_char_len[3] = (net_len >> 24);
std::cout << "net char[4] len=["
<< net_char_len[0] << ',' << net_char_len[1] << ','
<< net_char_len[2] << ',' << net_char_len[3] << ']'
<< std::endl;
boost::asio::write(s, boost::asio::buffer(char_len, 4));
char reply[max_length];
size_t reply_length = boost::asio::read(s,
boost::asio::buffer(reply, 1 ));
std::cout << "Reply is: ";
std::cout.write(reply, reply_length);
std::cout << "\n";
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include <stdint.h>
#include <arpa/inet.h>
using boost::asio::ip::tcp;
enum { max_length = 1024 };
int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
return 1;
}
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), argv[1], argv[2]);
tcp::resolver::iterator iterator = resolver.resolve(query);
tcp::socket s(io_service);
s.connect(*iterator);
std::cout << "sizeof uint32_t=" << sizeof(uint32_t) << std::endl;
uint32_t len = 1234;
std::cout << "len=" << len << std::endl;
// uint => char 4
char char_len[4];
char_len[0] = (len >> 0);
char_len[1] = (len >> 8);
char_len[2] = (len >> 16);
char_len[3] = (len >> 24);
std::cout << "char[4] len=["
<< char_len[0] << ',' << char_len[1] << ','
<< char_len[2] << ',' << char_len[3] << ']'
<< std::endl;
// char 4 => uint
uint32_t uint_len = *(reinterpret_cast<uint32_t *>( char_len ));
std::cout << "uint len=" << uint_len << std::endl;
// network bytes order
uint32_t net_len = htonl( len );
std::cout << "net_len=" << net_len << std::endl;
// uint => char 4
char net_char_len[4];
net_char_len[0] = (net_len >> 0);
net_char_len[1] = (net_len >> 8);
net_char_len[2] = (net_len >> 16);
net_char_len[3] = (net_len >> 24);
std::cout << "net char[4] len=["
<< net_char_len[0] << ',' << net_char_len[1] << ','
<< net_char_len[2] << ',' << net_char_len[3] << ']'
<< std::endl;
std::cout << "net char[4] len=["
<< (int)net_char_len[0] << ',' << (int)net_char_len[1] << ','
<< (int)net_char_len[2] << ',' << (int)net_char_len[3] << ']'
<< std::endl;
boost::asio::write(s, boost::asio::buffer( net_char_len, 4));
/*
char reply[max_length];
size_t reply_length = boost::asio::read(s, boost::asio::buffer(reply, 1 ));
std::cout << "Reply is: ";
std::cout.write(reply, reply_length);
std::cout << "\n";
*/
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用boost::asio::ip::tcp;
枚举{max_length=1024};
int main(int argc,char*argv[])
{
尝试
{
如果(argc!=3)
{
标准:cerr 16);
char_len[3]=(len>>24);
std::cout@John,字节转换例程存在于该标题中:那是Linux。我以为客户端应该是Windows,在这种情况下你想要吗?@John,是的,你是对的-我没有看到那一位-顺便说一句,nojhan,如果你想要访问这些转换例程的便携方式,你应该使用:boost/asio/detail/socket_ops.hpp。客户端是应该在Windozz上,但我以前用Linux客户端Linux做过测试。@John,字节转换例程存在于该标题中:那是Linux。我以为客户端应该是Windows,你想这样吗?@John,是的,你说得对-我没看到那一点-顺便说一句,nojhan,如果你需要,你应该使用:boost/asio/detail/socket_ops.hpp想要以可移植的方式访问这些转换例程..客户端应该在Windoz上,但我以前使用Linux客户端Linux进行过测试。我重新阅读了代码示例,最后看到了“message char”。因此我认为您要查找的长度是在第一次调用read()时填充的数据变量中。Yo