读书人

socket中的拥塞和非阻塞

发布时间: 2013-03-28 10:20:24 作者: rapoo

socket中的阻塞和非阻塞
本帖最后由 oyljerry 于 2013-03-15 17:44:35 编辑 我用的UDP。


m_hSock = socket(AF_INET, SOCK_DGRAM, 0);
if(INVALID_SOCKET == m_hSock)
{
g_log.Write(_T("创建socket失败..."),GetLastError());
return FALSE;
}
//设置socket为非阻塞模式
u_long iMode = 1;
if (SOCKET_ERROR == ioctlsocket(m_hSock, FIONBIO, &iMode))
{
g_log.Write(_T("设置非阻塞socket失败..."),GetLastError());
return FALSE;
}

BOOL opt = TRUE;
setsockopt(m_hSock,SOL_SOCKET,SO_REUSEADDR, (char *)&opt,sizeof (opt));

g_log.Write(_T("socket为:"),m_hSock);
ZeroMemory(&m_AddrDst,sizeof(SOCKADDR_IN));
m_AddrDst.sin_family = AF_INET;
m_AddrDst.sin_addr.s_addr = inet_addr(m_IpAddress);
m_AddrDst.sin_port = htons(UDP_COMMON_PORT);
if (0 != connect(m_hSock,(sockaddr*)&m_AddrDst,sizeof(SOCKADDR_IN)))
{
g_log.Write(_T("连接socket失败..."),GetLastError());
return FALSE;
}
设置了socket为非阻塞。
然后我变开始发送信息和接收信息。
发送和接收信息的函数为:
BOOL UDP_Send(SOCKET nSocket,LPVOID lPdata,int nLen,sockaddr_in* addr)
{
int nSendLen = 0;
int nRet = 0;
while(nLen > nSendLen)
{
nRet = sendto(nSocket,(char*)lPdata+nSendLen,nLen - nSendLen,0,(sockaddr*)addr,sizeof(struct sockaddr_in));
if (SOCKET_ERROR == nRet)
{
if(10035 == GetLastError())
{
Sleep(2);
continue;
}
g_log.Write(_T("发送信息失败..."),GetLastError());
return FALSE;
}
nSendLen += nRet;
}
return TRUE;
}

BOOL UDP_Recv(SOCKET nSocket,LPVOID lPdata,int nLen,sockaddr_in* addr)
{
int nRecvLen = 0;
int nRet = 0;
int nAddLen = sizeof(struct sockaddr_in);
while (nLen > nRecvLen)
{
nRet = recvfrom(nSocket,(char*)lPdata+nRecvLen,nLen - nRecvLen,0,(sockaddr*)addr,&nAddLen);
if (SOCKET_ERROR == nRet)
{
if(10035 == GetLastError())
{
Sleep(2);
continue;
}
g_log.Write(_T("接收信息失败..."),GetLastError());
return FALSE;
}
nRecvLen += nRet;
}
return TRUE;
}
我在来个循环接收:
while(TRUE)
{
bRes = UDP_Recv(m_hSock,(char*)&Msg,sizeof(Msg),&sockAddr);
if (FALSE == bRes)
{
break;
}
if(NET_FLAG != Msg.dwNetFlag)
{
m_bRecv = FALSE;
break;
}

switch(Msg.dwCMD)
{

case NETCMD_NETWORK_DEVREBOOT_RESP:
m_bRecv = TRUE;
return;
case NETCMD_NETWORK_FACTORYRES_RESP:
m_bRecv = TRUE;
return;
case NETCMD_NETWORK_DEVPRARM_RESP:
m_bRecv = TRUE;
return;
case DEV_UDPMSG_DEVNTP_RESP:
m_bRecv = TRUE;
return;
default:
return;
}

}

按照道理来讲,这个应该不会出现阻塞现象啊,为什么我的会出现阻塞现象呢?有一个信息就是服务器没有收到我发送的信息,但是我这边表示发送成功(有人说是放到缓冲区了,主机没接收)。但是应该不至于我的recvfrom函数阻塞吧。大神们,能看出来是什么原因么,或者说可能引发的因素!
[解决办法]
1.可能是服务器绑定监听的端口,不是客户端指定的接受端口。
2.UDP本身就不保证对方一定能收到包

bRes = UDP_Recv(m_hSock,(char*)&Msg,sizeof(Msg),&sockAddr);


if (FALSE == bRes)
{
break;
}


可以在这个里面加上一句调试信息,看看你的recvform是不是阻塞的

bRes = UDP_Recv(m_hSock,(char*)&Msg,sizeof(Msg),&sockAddr);
if (FALSE == bRes)
{
TRACE(_T("recieve nothing..."));
break;
}

[解决办法]
那别人调好的例子用吧,不用自己从头写,还得调试,很多socket例子,应该有你要的:
http://download.csdn.net/detail/geoff08zhang/4571358
[解决办法]
m_hSock = socket(AF_INET, SOCK_DGRAM, 0);
你这里是用了UDP方式的,但是下面的一句却是connect,connect是TCP协议来的,你这不能混用了
if (0 != connect(m_hSock,(sockaddr*)&m_AddrDst,sizeof(SOCKADDR_IN)))
{
g_log.Write(_T("连接socket失败..."),GetLastError());
return FALSE;
}
[解决办法]
可以connect,只是这样你只能收到对方的消息,不能接收来自其他地址和端口的消息了
是不是UDP_Recv函数里面死循环了
[解决办法]
引用:
m_hSock = socket(AF_INET, SOCK_DGRAM, 0);
你这里是用了UDP方式的,但是下面的一句却是connect,connect是TCP协议来的,你这不能混用了
if (0 != connect(m_hSock,(sockaddr*)&m_AddrDst,sizeof(SOCKADDR_IN)))
{
……
对的。这个地方咋可以用connect呢
[解决办法]
Quote: 引用:

引用:
m_hSock = socket(AF_INET, SOCK_DGRAM, 0);
你这里是用了UDP方式的,但是下面的一句却是connect,connect是TCP协议来的,你这不能混用了
if (0 != connect(m_hSock,(sockaddr*)&m_AddrDst,sizeof(SOCKADDR_IN)))
……[/quote

udp connect 是没问题的,指定目的ip,后续直接发送数据。不用不停的断开和连接,减少开销。

楼主用了connect,直接用recv和send就行了,再去指定目的地址是多余呢。
具体阻塞可以跟踪下。

也可用netstat检测下udp连接的情况看看

读书人网 >VC/MFC

热点推荐