socket通讯可靠性

wula0010 2019-06-28 06:41:32
写了一个socket通信程序,客户端和服务端要来回传递多个消息,发送、接收如下:

/*-------------------------------------------------------------------
SOCKETROUTE.C——阻塞模式下使用的常用子程序
(c)by 浅墨浓香,2015.6.25
---------------------------------------------------------------------*/
#include <windows.h>
#include "Message.h"
#include "SocketRoute.h"

#pragma comment(lib,"Ws2_32.lib")

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 在规定的时间内等待数据到达
// 输入:dwTime = 需要等待的时间(微秒)
// 返回值:0 ——超时而返回
// SOCKET_ERROR ——出错而返回
// X(x>0) ——就绪的套接字数量
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int WaitData(SOCKET sock, DWORD dwTime)
{
FD_SET fds;
TIMEVAL tv;

fds.fd_count = 1;
fds.fd_array[0] = sock;

tv.tv_sec = 0;
tv.tv_usec = dwTime;

return select(0, &fds, NULL, NULL, &tv);
}

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 接收规定字节的数据,如果缓冲区中的数据不够则等待
// 返回:FALSE,连接中断或发生错误
// TRUE,成功
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
BOOL RecvData(SOCKET sock, char* pBuffer, int nBytes)
{
int nStartTime;
int nRet,nRecv;

nStartTime = GetTickCount();
nRecv = 0;

while ((GetTickCount()-nStartTime)<10*1000) //查看是否超时
{
nRet = WaitData(sock, 100 * 1000); //等待数据100ms
if (SOCKET_ERROR == nRet) //连接错误
return FALSE;

if (0 == nRet) //超时
break;

do
{
//接收数据,直至收完指定的字节数
nRecv += recv(sock, pBuffer + nRecv, nBytes - nRecv, 0);

if (nRecv == SOCKET_ERROR || nRecv == 0)
return FALSE;

if (nRecv == nBytes)
return TRUE;

} while (nRecv < nBytes);
}
return TRUE;
}

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 接收一个符合规范的数据包
// 参数: pBuffer用来接收数据的缓冲区
// nBytes 数据区最大的空间
// 返回: FALSE——失败
// TRUE ——成功
//注意:这里的nBytes不要指要接收的字节数,只是用来判断缓冲区是否只够大
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

BOOL RecvPacket(SOCKET sock, char* pBuffer, int nBytes)
{
MSGSTRUCT* pMsgStruct;
int iRet;

pMsgStruct = (MSGSTRUCT*)pBuffer;

//接收数据包头部并检测数据是否正常
iRet = RecvData(sock, pBuffer, sizeof(MSGHEAD));

if (iRet) //如果成功接收数据
{
if (pMsgStruct->MsgHead.cbSize <= sizeof(MSGHEAD) ||
pMsgStruct->MsgHead.cbSize > nBytes)
return FALSE;

//接收余下的数据
iRet = RecvData(sock, pBuffer + sizeof(MSGHEAD), pMsgStruct->MsgHead.cbSize - sizeof(MSGHEAD));
}
return iRet;
}


程序调试没有问题,可是真正跑起来后,发现总是出现发送或接收失败的情况,而且还是在同一个机器上,如果真部署到实际网络中,我觉得出现错误的可能性更大,那该怎么处理才能让tcp通讯更可靠呢?
...全文
188 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
YapingXin 2019-07-02
  • 打赏
  • 举报
回复
楼上的回答真经典
赵4老师 2019-07-01
  • 打赏
  • 举报
回复
不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊! http://bbs.csdn.net/topics/380167545
轻箬笠 2019-06-29
  • 打赏
  • 举报
回复
说实话,自己写的tcp通讯组件总有各种问题。如果追求速度,找个别人写好的开源库吧
636f6c696e 2019-06-29
  • 打赏
  • 举报
回复
可以参考下下面的错误处理方式: https://blog.csdn.net/qq_24637797/article/details/48342857 不过建议你先加打印确认下失败时候的errno是什么,如果是我说的那两个,忽略即可,其他的errno先定位下原因
636f6c696e 2019-06-29
  • 打赏
  • 举报
回复
接收发送失败是正常的,系统一旦有中断,recv、send函数就会出现返回失败,errno一般是EAGAIN或者EINTERUPT,这时候只要加可靠性重试就行了
老葱1# 2019-06-29
  • 打赏
  • 举报
回复
tcp 的内容很多,许多设置都会影响运行, 绝不是正确调用了 select recv send 就 ok 了。
老葱1# 2019-06-29
  • 打赏
  • 举报
回复
nRecv += recv(sock, pBuffer + nRecv, nBytes - nRecv, 0); if (nRecv == SOCKET_ERROR || nRecv == 0) // 这里明显逻辑错误 , 都已经 += , 还能当作这次的返回判断 return FALSE; 整个代码,错误处理不仔细, 若是作为通用的代码还有很多问题:select 与 recv 不匹配, recv 可能会一致等待( 没设置 tcp timedout ) ....
gouyanfen 2019-06-28
  • 打赏
  • 举报
回复
刚好,我测试博客,发了一个我写的SOCKET通信类的接收函数,正常在工程中使用,实际使用中没有什么问题,你可以参考一下
gouyanfen 2019-06-28
  • 打赏
  • 举报
回复
本机传送会不可靠?那是不可能的,你的数据流没有处理好

70,021

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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