为什么每次send,recv后下次再次执行此操作需要先关闭套接字再连接后才成功?
我封装了套接字,执行获取网页源码的功能
我采取的是tcp协议,阻塞模式的。
这个是我自己定义初始化socket以及连接主机、端口的函数(没问题)
bInitSocket(CString pHost,//主机,域名
int nPort)//端口号
{
//...
//连接服务器
if (connect(m_Socket, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
MessageBox(NULL, "Connect Error!", "Error", 0);
CloseSocket();
return FALSE;
}
//...
}
这个是我自己封装的发送包的方法(没问题)
nPostPackage(const CString strPockage)
{
//....
//发送数据
nSend = send(m_Socket, strNewPockage.GetBuffer(0), strNewPockage.GetLength(), 0);
//...
}
这个是我自己封装的在调用nPostPackage方法后执行接收数据的方法(没问题)
nGetData()
{
while (nRet > 0)
{
//...
// 接收返回数据包
nRet = recv(m_Socket, (LPSTR)arryRecv, sizeof(arryRecv), 0);
//...
}
{}
这个是我自己封装的关闭套接字的方法(没问题)
CloseSocket()
{
try
{
shutdown(m_Socket, 0X02);
closesocket(m_Socket);
WSACleanup();
}
catch (...)
{
MessageBox(NULL, "Close socket fail", "Error", 0);
}
}
**************************
接下来就是我的问题。
我循环(当循环第一次就能nPostPackage和nGetData成功,但是循环第二次的时候就会nGetData返回0个数据)
{
nPostPackage(const CString strPockage);//发送数据包后
nGetData();//接收数据
}
然后我修改成(这个就能成功执行完所有我的循环)
{
bInitSocket(CString pHost,//主机,域名
int nPort);//端口号//初始化并且连接服务器
nPostPackage(const CString strPockage);//发送数据包后
nGetData();//接收数据
CloseSocket();//关闭套接字
}
问题一:为什么修改成这样之后才能成功?
问题二:因为每循环一次都需要连接和关闭套接字,这样性能急剧下降,有没有什么好的办法可以解决此处的性能问题?我只想使用同一个套接字对象,不想创建多个套接字对象。
谢谢。
[解决办法]
貌似没有releasebuff(),我以前也碰到过这个问题,我是因为发送和接受缓冲区大小设置不一样导致的。
[解决办法]
close以后宣告这个连接失效
[解决办法]
第一次nGetData()之后,该函数退出没?修改为
nGetData()
{
while (true)
{
//...
// 接收返回数据包
int nRet = recv(m_Socket, (LPSTR)arryRecv, sizeof(arryRecv), 0);
//...
if(nRet > 0)
{
//todo
}
else()
{}
}
{}
[解决办法]
另外一个问题,一般send之前,会在包头添加四个字节,用来表示本次发送包的大小;
同理,recv之后,包头前四个字节可以表示为int,与recv的长度进行比较。
[解决办法]
要知道,一个连接,除了你自己close以外, 服务器也是可以close的。
你返回0,说明就是服务器已经close了啊,所以你必须重新连接。
至于为何服务器会主动close, 你没有说你连的是什么服务器,说以不好说。
如果你连的是HTTP网站,正如cl_gamer所说,HTTP服务器在给你返回数据后,就会close连接。
[解决办法]
用wireshark抓包来看看,是不是服务端有[FIN,ACK]包发过来,有的话,表明服务端释放了连接.