使用asio时遇到问题。我的客户端/服务器应用程序只需要同步通信因此,使用来自boost主页的同步示例,我已经设置了两个发送和接收数据的过程。他们的代码如下:
void vReceive(tcp::socket & socket, std::string & szDest){
char szTmp_Buf [BUF_LEN + 1];
szDest = "";
std::cout << "Entering vReceive . . ." << std::endl;
for (;;){
char szBuf [BUF_LEN];
boost::system::error_code error;
uInt uiBytes_Recv = socket.read_some(boost::asio::buffer(szBuf), error);
std::cout << " Read " << uiBytes_Recv << " bytes" << std::endl;
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.
memcpy((void*) szTmp_Buf, (void*) szBuf, uiBytes_Recv );
szTmp_Buf[ uiBytes_Recv ] = '\0';
szDest += szTmp_Buf;
};
std::cout << "Received" << szDest << std::endl;
std::cout << "Leaving vReceive . . ." << std::endl << std::endl;
};
void vSend(tcp::socket & socket, std::string & szSrc){
std::cout << "Entering vSend . . . " << std::endl;
std::cout << "Sending " << szSrc << std::endl;
boost::system::error_code ignored_error;
boost::asio::write(socket, boost::asio::buffer(szSrc), boost::asio::transfer_all(), ignored_error);
std::cout << "Leaving vSend . . . " << std::endl << std::endl;
};
这些过程只是从boost示例中提取的代码行的包装器。
在我的测试应用程序中,客户端调用
std::string szDate;
vReceive(socket, szDate);
vSend(socket, std::string("Chop Suey!") );
vReceive(socket, szDate);
vSend(socket, std::string("Halo"));
并且服务器调用
std::string message = make_daytime_string();
std::string szReceived;
vSend(socket, message);
vReceive(socket, szReceived);
vSend(socket, message);
vReceive(socket, szReceived);
只是为了测试功能。问题是两个应用程序在第一次信息交换后都冻结了,正如我在下面的picture中描述的那样。当 vSend()在服务器端完成时,客户端上的 vReceive()过程似乎没有完成。那么,有没有人有任何想法,可能出现什么问题?
如果有人想要复制问题,我将源完整的源代码上传到同一台服务器,其中图片位于asio_problem.rar文件中(每个帖子我可以有一个超链接作为新成员)。
提前谢谢大家, 丹尼尔。
答案 0 :(得分:1)
我认为你的问题在于:
for (;;){
/* snipped */
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.
/* snipped */
}
您无限循环直到连接关闭(断开循环的唯一方法是从套接字收到EOF错误),但vSend
永远不会关闭套接字。这意味着您客户端中的vReceive
将永远等待,总是期待更多数据。将socket.close()
放在vSend
中应该可以很好地解决问题。
当然,这意味着您的客户端和服务器需要在每次调用vReceive
和vSend
后重新打开套接字。如果这不合适,那么我建议使用发送方的其他一些方法通知接收方不再发送数据。
我不确定您是否对通过线路发送的数据有任何限制,但要么在邮件开头发送“数据长度”值,要么在某种“数据结束”哨兵值最后会给你一个很好的,干净的指示,指示何时停止收听更多数据。
这种方法还有额外的优势,可以让您使用ASIO的read_until
(或类似)功能来处理等待数据结束的逻辑。