哎!长叹一声!今天上班很鬼火,被老板骂了一顿,严重的打击了我的自信!哎,鬼火啊,到今天下班以前,才把任务完成了一点点。明天要继续努力哦!总结今天碰到的问题。
首先:今天在做一个视频转发器,用vlc播放器推视频流,通过转发器然后发送到另外一个pc,然后用vlc播放器播放,这些都是基于udp的socket的。
在基于udp的socket的发送数据是,碰到了主要两个问题。
1、关于UDP socket 的10054错误
FD_ZERO(&rfd); // 在使用之前总是要清空 FD_ZERO(&wfd); // 开始使用select FD_SET(PrimaryUDP, &rfd); // 把PrimaryUDP(socket)放入要测试的描述符集中 int maxfdp=PrimaryUDP>PrimaryUDP1?PrimaryUDP+1:PrimaryUDP1+1; int nRet = select(maxfdp, &rfd, 0, NULL, &timeout);// 检测是否有套接口是否可读 //nRet返回的-1,所以这出现问题了,经过WSAGetLastError()返回的是10054 // if (nRet == SOCKET_ERROR) // { // printf("select() %d/n",WSAGetLastError()); // return 1; // } // else if (nRet == 0) // 超时 // { // printf("timeout/n"); // closesocket(PrimaryUDP); // closesocket(PrimaryUDP1); // break; // }
int nRet = select(maxfdp, &rfd, 0, NULL, &timeout);// 检测是否有套接口是否可读 //nRet返回的-1,所以这出现问题了,经过WSAGetLastError()返回的是10054经过查证: 网上说的是winsock自已的bug。在初始化SOCKET时加上底下这段代码,就可以解决以上的问题。
DWORD dwBytesReturned=0; BOOL bNewBehavior=FALSE; DWORD status; status = WSAIoctl(PrimaryUDP, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL); if (SOCKET_ERROR == status) { DWORD dwErr = WSAGetLastError(); if (WSAEWOULDBLOCK == dwErr) { // nothing to do return(FALSE); } else { printf("WSAIoctl(SIO_UDP_CONNRESET) Error: %d\\n", dwErr); return(FALSE); } }2、 SOCKET的发送与接收缓冲区
在我用vlc播放器不断地向转发器发送udp数据包时,经过转发器转发数据,可是在这里出现了一个问题,就是视频流的udp数据包丢失很严重,使的在另外一台电脑的vlc播放器播放视频的时候都是花的,抓取数据包,丢了很多数据包。udp数据包在局域网都丢了这么多数据包,肯定不正常。
减少丢包方法: 1:设置缓冲! 2:使用线程池。
所以我我设置SOCKET的发送与接收缓冲区,经过设置以后,丢包的情况就改善很好了,视频能够正常的播放了。
设置方法为:
int optVal = 32*1024 ;
int optLen = sizeof(int);
setsockopt(PrimaryUDP,SOL_SOCKET,SO_RCVBUF,(char*)&optVal,optLen);
这个是这事socket PrimaryUDP的接受缓冲区为32*1024,即32K
//发送缓冲区
int nSendBuf=32*1024;//设置为32K
setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));
参考文献:
http://blog.csdn.net/wesleyluo/article/details/6149071
http://blog.csdn.net/ccnucjp8136/article/details/4515002