gpt4 book ai didi

C++ tcp socket连接重试方法

转载 作者:行者123 更新时间:2023-11-28 06:17:45 26 4
gpt4 key购买 nike

在开发了一个可以交换一些数据的示例客户端服务器应用程序之后,我试图在其中实现重试机制。目前我的应用程序遵循以下协议(protocol):

  1. 客户端连接到服务器(非阻塞模式),超时 3 秒,重试 2 次。
  2. 开始从客户端发送固定长度的数据。发送有一些错误检查它是否正在发送完整的数据。
  3. 从服务器接收响应(超时:3 秒)并验证。如果收到不正确的响应,则重新发送数据并等待响应。如果失败,请重复此操作两次。

上面的实现代码部分如下所示:

  1. connect() 和 select() 用于打开连接
  2. select() 和 send() 用于数据发送
  3. select() 和 recv() 用于数据接收

现在我根据套接字函数的返回类型进行重试,如果 send() 或 recv() 失败,我将重试相同的方法。但不记得 connect()。

我通过在数据传输之间重新启动服务器来测试这个东西,结果客户端无法与服务器通信并在几次重试后退出,我相信这是因为没有 connect() 调用重试方法。

有什么建议吗?

接收socket数据的示例代码

bool CTCPCommunication::ReceiveSocketData(char* pchBuff, int iBuffLen)
{
bool bReturn = true;

//check whether the socket is ready to receive
fd_set stRead;
FD_ZERO(&stRead);
FD_SET(m_hSocket, &stRead);
int iRet = select(0, &stRead, NULL, NULL, &m_stTimeout);

//if socket is not ready this line will be hit after 3 sec timeout and go to the end
//if it is ready control will go inside the read loop and reads data until data ends or
//socket error is getting triggered continuously for more than 3 secs.
if ((iRet > 0) && (FD_ISSET(m_hSocket, &stRead)))
{
DWORD dwStartTime = GetTickCount();
DWORD dwCurrentTime = 0;

while ((iBuffLen-1) > 0)
{
int iRcvLen = recv(m_hSocket, pchBuff, iBuffLen-1, 0);
dwCurrentTime = GetTickCount();

//receive failed due to socket error
if (iRcvLen == SOCKET_ERROR)
{
if((dwCurrentTime - dwStartTime) >= SOCK_TIMEOUT_SECONDS * 1000)
{
WRITELOG("Call to socket API 'recv' failed after 3 secs continuous retries, error: %d", WSAGetLastError());
bReturn = false;
break;
}
}
//connection closed by remote host
else if (iRcvLen == 0)
{
WRITELOG("recv() returned zero - time to do something: %d", WSAGetLastError());
break;
}

pchBuff += iRcvLen;
iBuffLen -= iRcvLen;
}
}
else
{
WRITELOG("Call to API 'select' failed inside 'ReceiveSocketData', error: %d", WSAGetLastError());
bReturn = false;
}

return bReturn;
}

最佳答案

Currently my application is following below protocol:

  1. Client connects to server (non blocking mode) with 3 secs timeout and with 2 retries.

您无法重试连接。您必须关闭连接尝试失败的套接字,创建一个新套接字,然后再次调用 connect()

  1. Start sending data from client with fixed length. Send has some error checking whether it is sending the complete data or not.

这在阻塞模式下不是必需的:POSIX 标准保证阻塞模式 send() 将发送所有数据,否则会因错误而失败。

  1. Receive response (timeout: 3secs) from server and verify that. If incorrect response received, re-send the data and wait for response. Repeat this for two times if failed.

这是个坏主意。很可能所有数据都会到达,包括所有重试,或者没有。如果您使用此技术,您需要确保您的交易是幂等的。您还需要密切注意实际的超时时间。 3 秒通常是不够的。起点是预期服务时间的两倍。

For the above implementation code sections look likes something below:

   connect() and select() for opening connection
select() and send() for data send
select() and recv() for data receiving

在阻塞模式下您不需要 select()。您可以使用 SO_RCVTIMEO 设置读取超时。

Now I'm making the retries based on return types of the socket functions, and if send() or recv() fails I'm retrying the same methods. But not recalling connect().

I tested the thing by restarting the server in between the data transfer, and as a result client fails to communicate with the server and it quits after several retries, I believe this is happening as because there is no connect() call on retry methods.

如果那是真的,你会得到这样的错误。

关于C++ tcp socket连接重试方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29915901/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com