急问:基于TCP的socket传输媒体流数据问题的解决

最帅的小猪 2014-11-25 02:17:00
说下要实现的功能,基于TCP协议,C/S模式,实现服务端将收到的媒体流数据转发给客户端,客户端拿到数据后组帧再解码播放,过程也就是socket传输数据这块,为了便与测试,我直接将接受到的数据都写到h264文件里。遇到的问题是,在播放h264文件时发现画面都是花屏,貌似是丢包的样子,不知道是不是我的做法有问题,请各位指教一下,不甚感激。
ps:客户端和服务器在同一台电脑上,电脑和摄像机在同一个交换机上。

我的实现思路如下:

数据传输分为以下几个部分:
1. 传输数据大小
2. 分包传输数据
3. 结束传输


给每一步定义一个网络标识:
enum FILETRANSFLAG
{
FTS_SIZE = 1,
FTS_DATA,
FTS_OK
};

数据包的设计
每一步都是分为包头和包体:
struct CPacketHeader
{
FILETRANSFLAG m_nFlag; //标志
int m_nDataLen; //数据包长度
};

以下代码为伪码, 没有考虑出错, 安全等细节,如下:

//发送端;
if (pData != NULL && lDataSize > 0)
{
if (m_connectSocket == INVALID_SOCKET)
{
return;
}

int nRet = 0;
DWORD nSendCount = 0;
DWORD nSendTotalCount = 0;

CPacketHeader header;

//发送数据长度;
header.m_nFlag = FTS_SIZE;
header.m_nDataLen = lDataSize;
nRet = send(m_connectSocket, (LPCSTR)&header, sizeof(CPacketHeader), 0);

while(nSendTotalCount < lDataSize)
{
//发送包头;
header.m_nFlag = FTS_DATA;
header.m_nDataLen = 1024;
nRet = send(m_connectSocket, (LPCSTR)&header, sizeof(CPacketHeader), 0);

//发送数据;
nSendCount = send(m_connectSocket,(char *)pData, 1024, 0);

if (nSendCount == SOCKET_ERROR)
{
break;
}
else
{
nSendTotalCount += nSendCount;
}
}

//发送结束;
header.m_nFlag = FTS_OK;
header.m_nDataLen = 0;
nRet = send(m_connectSocket, (LPCSTR)&header, sizeof(CPacketHeader), 0);
}

//接收端;
long lDataLen = 0;
int nRecvLen = 0;
DWORD nRecvCount = 0;
char revbuf[1024];
CString filename = _T("d:\\recvdata.h264");
hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

while(1)
{
//接收包头;
CPacketHeader header;
nRecvLen = recv(m_sockClient, (LPSTR)(LPCSTR)&header, sizeof(CPacketHeader), 0);

if (nRecvLen == SOCKET_ERROR)
{
return -1;
}

switch(header.m_nFlag)
{
case FTS_SIZE: //数据长度;
{
lDataLen = header.m_nDataLen;
}
break;
case FTS_DATA: //数据;
{
nRecvCount = recv(m_sockClient, revbuf, sizeof(revbuf), 0);

if (nRecvCount == SOCKET_ERROR)
{
break;
}
else
{
::WriteFile(hFile, revbuf, nRecvCount, &nRecvCount, NULL);
}
}
break;
case FTS_OK: //传输结束;
{
//组帧解码播放;
}
break;
default:
break;
}
}

...全文
495 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
Henzox 2014-12-02
  • 打赏
  • 举报
回复
这个网络部分花屏在正常了, recv 每次返回时与你发送的长度不一致很正常(也就是有可能不是头的长度或者 1024 的长度), 可以封闭一个函数 recvn 不接收到指定长度不返回,这样,你才可以指定先接收多长的头部分,然后再接收多长的数据部分。
「已注销」 2014-12-02
  • 打赏
  • 举报
回复
tcp不存在丢包。
最帅的小猪 2014-11-26
  • 打赏
  • 举报
回复
设备出来的视频正常,没有花屏,应该还是数据传输的问题。
jianghandaxue 2014-11-25
  • 打赏
  • 举报
回复
接收过来的裸流写文件,播放不应该出现花屏的吧,你确定你的设备出来的视频的不花屏的吗 你用VLC连接试下是否花屏
版主大哥 2014-11-25
  • 打赏
  • 举报
回复
代码够乱的.... 看你定义的包总长是1024 你可以如下:

const int PACKET_MAX_LEN = 1024;
const int DATA_MAX_LEN = 1024 - 4*sizeof(int);

typedef struct PACKET
{
	int nPacketLen;             //包的实际长度
	int nCmd;                   //包的命令
	int nFlag;                  //是否分包了
	int nDataLen;               //当分包的时候数据的真实长度
	char szData[DATA_MAX_LEN];  //数据
}Packet,*PPacket;

//比如封装一个接口发送
int SendPacket(int nSendSocket,int nCmd,char* pData,int nLen)
{
	int nTempLen = nLen;

	Packet packet;

	memset(&packet,0,sizeof(Packet ));

	packet.nCmd = nCmd;

	packet.nDataLen = nLen;

	while(nTempLen > 0)
	{
		if(nTempLen  > DATA_MAX_LEN)
		{
			packet.nFlag = 0; //分包

			packet.nPacketLen = PACKET_MAX_LEN;

			memcpy(packet.szData,pData + nLen - nTempLen,DATA_MAX_LEN);

			int nSendLen = send(nSendSocket,(char*)&packet,PACKET_MAX_LEN,0);

			//判断nSendLen 是否 = -1 等等....

			assert(nSendLen == PACKET_MAX_LEN); //必须全部发送,可以用while的方法send

			nTempLen -= DATA_MAX_LEN;
		}
		else
		{
			packet.nFlag = 1; //分包结束

			packet.nPacketLen = PACKET_MAX_LEN - DATA_MAX_LEN + nTempLen;

			memcpy(packet.szData,pData + nLen - nTempLen,nTempLen);

			int nSendLen = send(nSendSocket,(char*)&packet,packet.nPacketLen,0);

			//判断nSendLen 是否 = -1 等等....

			assert(nSendLen == packet.nPacketLen); //必须全部发送,可以用while的方法send

                        nTempLen -= nTempLen;
		}
		Sleep(10);  //防止发送太快
	}
	return 0;
}

随手写的,你可以按这种方式分包发出去 收包时,粘包 就判断 int nFlag; //是否分包了 这个去粘包 还有一个实际数据长度..... 我就不写了

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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