boost::asio 通信问题

98440622 2009-06-02 10:49:03
下面的代码在VC9 + Boost 1.36.0下编译并在WinXP + SP2运行通过,但是在运行时发现一个有趣的现象,在调用发送(write_some)函数返回处打印当前时间信息,当收到第一个数据时打印接受到数据的时间发现两个时间只差总是间隔15个毫秒左右的时间,通信波特率是9600bps,那么我的理解是一个字节大概要1毫秒左右时间完成传输,发送和接受的时间差应该也是1ms左右,为什么会有这么大间隔呢?不知道那位朋友遇到过这样的问题,恳请指教:)


int do_serial_test(int argc, char* argv[]) {
using namespace boost::asio;
using namespace boost::posix_time;
using namespace boost::gregorian;

io_service isvr;
serial_port port(isvr);

if (argc != 3) {
std::cout << "Usage : Asio [COM1] [client/server]\n";
return -1;
}

try {
//
// Open COM1.
//
port.open(argv[1]);

//
// Set parameter with 9600bps,8,1,1,none.
//
port.set_option<serial_port_base::baud_rate>(
serial_port_base::baud_rate(9600));
port.set_option<serial_port_base::character_size>(
serial_port_base::character_size(8));
port.set_option<serial_port_base::stop_bits>(
serial_port_base::stop_bits(serial_port_base::stop_bits::one));
port.set_option<serial_port_base::flow_control>(
serial_port_base::flow_control(serial_port_base::flow_control::none));
port.set_option<serial_port_base::parity>(
serial_port_base::parity(serial_port_base::parity::none));

std::string par(argv[2]);
if (par == std::string("client")) {
std::cout << "Client mode started...\n";

//
// Send a plain text.
//
char* text = "Hello Boost::asio::serial_port:)\n";
port.write_some<boost::asio::mutable_buffers_1>(
boost::asio::buffer(text, /*::strlen(text)*/ + 1));
std::cout << to_simple_string(microsec_clock::local_time()) << std::endl;
} else if (par == std::string("server")) {
std::cout << "Server mode started...\n";

for (;;) {
//
// Waitting for a plain reply text.
//
char reply[128] = {0};
size_t reply_size = port.read_some<boost::asio::mutable_buffers_1>(
boost::asio::buffer(reply, 128));
std::cout << to_simple_string(microsec_clock::local_time()) << std::endl;
std::cout << reply << std::endl;
}
} else {
std::cout << "Unknow mode, pls read usage carefully.\n";
}

//
// Close port.
//
port.close();
} catch (std::exception& exp) {
std::cout
<< exp.what()
<< ".\n";
::exit(0);
}

return 0;
}

int main(int argc, char* argv[]) {
return do_serial_test(argc, argv);
}


编译生成asio.exe

在命令行下开启两个实例
asio COM1 server // 负责接收数据
asio COM2 client // 负责发送数据

COM1和COM2互联,保证两个实例在同一个cpu上运行。
...全文
462 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
98440622 2009-06-03
  • 打赏
  • 举报
回复
恩,跟我的想法差不多,正找机器试呢,呵呵

不知道能不能用替换windows标准串口驱动,硬件上实现实时发送应该没问题。
老邓 2009-06-02
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 98440622 的回复:]
E文不好,看不太懂啊:(
[/Quote]

有中文文档的。http://code.google.com/p/boost-doc-zh/
98440622 2009-06-02
  • 打赏
  • 举报
回复
E文不好,看不太懂啊:(
老邓 2009-06-02
  • 打赏
  • 举报
回复
楼主可曾参考过asio的文档?
98440622 2009-06-02
  • 打赏
  • 举报
回复
在windows环境下没办法做到“立即”发送数据?
fuzzy_man 2009-06-02
  • 打赏
  • 举报
回复
串口通信传送的第一个数据造成的中断为了唤醒端口,唤醒后需要等待一定的时间才能正常通信。
pottichu 2009-06-02
  • 打赏
  • 举报
回复
windows 下没办法,呵呵,
linux下能看到驱动代码,可以自己验证。。。
98440622 2009-06-02
  • 打赏
  • 举报
回复
我怀疑应该是windows串口驱动的问题,但是没有确定的证据啊
pottichu 2009-06-02
  • 打赏
  • 举报
回复
串口发送数据的实时性确实比较糟糕。
另外,串口驱动中有缓冲机制,所以数据并不一定是立即发送。
98440622 2009-06-02
  • 打赏
  • 举报
回复
感谢Loaden提供的网址,不过问题还是没能解决。

尝试用Windows API (CreateFile, WriteFile)的方式实现串口发送,发送函数结束后打印本地时间发现仍然存在15ms左右延时,怀疑是windows系统串口驱动问题。


int main(int argc, char* argv[]) {
using namespace boost::posix_time;

HANDLE hCom = ::CreateFile("COM1",
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);

if (hCom == INVALID_HANDLE_VALUE) {
hCom = NULL;
return -1;
}

// Create read overlapped event.
OVERLAPPED osReader;
OVERLAPPED osWriter;

memset((void*)&(osReader), 0, sizeof(OVERLAPPED));
memset((void*)&(osWriter), 0, sizeof(OVERLAPPED));

osReader.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
osWriter.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL || osWriter.hEvent == NULL) {
::CloseHandle(hCom);
return -1;
}

::PurgeComm(hCom,
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

DCB _dcb = {0};
if (!::GetCommState(hCom, &_dcb)) {
::CloseHandle(hCom);
return -1;
}

_dcb.BaudRate = 9600;
_dcb.Parity = NOPARITY;
_dcb.fParity = FALSE;
_dcb.ByteSize = 8;
_dcb.StopBits = 0;
_dcb.fBinary = 0;
_dcb.fDtrControl = DTR_CONTROL_ENABLE;
_dcb.fRtsControl = RTS_CONTROL_ENABLE;
_dcb.fOutxCtsFlow = FALSE;
_dcb.fOutxDsrFlow = FALSE;

if (!::SetCommState(hCom, &_dcb)) {
printf("%d", ::GetLastError());
::CloseHandle(hCom);
return -1;
}

COMMTIMEOUTS _timeouts = {0};
if (!::GetCommTimeouts(hCom, &_timeouts)) {
CloseHandle(hCom);
return -1;
}

_timeouts.ReadIntervalTimeout = 0xffffffff/* 10 */;
_timeouts.ReadTotalTimeoutMultiplier = 0;
_timeouts.ReadTotalTimeoutConstant = 0;
_timeouts.WriteTotalTimeoutMultiplier = 0;
_timeouts.WriteTotalTimeoutConstant = 5000;

if (!::SetCommTimeouts(hCom, &_timeouts)) {
CloseHandle(hCom);
return -1;
}

DWORD _dwStoredFlags = EV_ERR | EV_RLSD;
if (!::SetCommMask(hCom, _dwStoredFlags)) {}

DWORD _dCount = 0;
if (1) {
BOOL _bFlag = ::WriteFile(hCom,
"ABCD", 5, &_dCount, &osWriter);
if (!_bFlag) {
DWORD _dLastError = ::GetLastError();
if (_dLastError == ERROR_IO_PENDING) {
if (::GetOverlappedResult(hCom,
&osWriter, &_dCount, TRUE)) {
std::cout << to_simple_string(microsec_clock::local_time()) << std::endl;
return _dCount;
} else {
return ::GetLastError();
}
} else {
return -1;
}
}
}

return 0;
}

64,632

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧