关于如何使用阻塞socket来从服务器拿数据请参考: http://blog.csdn.net/lcl_data/article/details/7325065
修改阻塞socket到非阻塞的socket的注意事项:
1.非阻塞的socket的是在阻塞的socket的基础上设置标识而成。
2.使用非阻塞的socket的时候要注意,send完命令之后不能立即recv,这个时候数据还没到,需要用select来判断数据有效与否 或者先sleep一段时间。
3.关于socket的recv,他每次会把接受到的数据填充进recvBuff里面,填充长度为返回值(假设recvBytes )。如果在recv之前recvBuff里面有数据,recv只会把recvBuff里面长度为 recvBytes 的部分数据重写,后面的不予理会。
参考: socket::select : http://www.cnblogs.com/ggzss/archive/2011/08/25/2153746.html
bool WSScocket::CanRead(int sec_timeout)
{
fd_set fdread;
int ret;
struct timeval tv ;
FD_ZERO(&fdread);
FD_SET(m_sock, &fdread);
tv.tv_sec = sec_timeout;
tv.tv_usec = 0;
ret = select(0, &fdread, NULL, NULL, &tv);
return ret > 0;
}
void WSScocket::SetNoBlock()
{
unsigned long ulnoblock = 1;
ioctlsocket(m_sock,FIONBIO,&ulnoblock);
}
#include "stdafx.h"
#include "socket.h"
#include <iostream>
#include <string>
char sendBuf[] = "GET /config HTTP/1.1\r\n\r\n";
char recvBuf[4096*4];
int _tmain(int argc, _TCHAR* argv[])
{
WSScocket socket;
if(socket.Init() == 0)
{
if (!socket.Create(AF_INET,SOCK_STREAM,IPPROTO_IP))
{
return -1;
}
if(!socket.Connect("150.245.177.81",80))
{
return -1;
}
int sendCount = socket.Send(sendBuf,sizeof(sendBuf),0);
if(sendCount != sizeof(sendBuf))
{
return -1;
}
std::string receive;
socket.SetNoBlock();
//Sleep(1000);
int recvBytes = 0;
do
{
if(!socket.CanRead(3)) break;
recvBytes = socket.Recv(recvBuf,sizeof(recvBuf),0);
if(recvBytes == SOCKET_ERROR || recvBytes == 0) // 0 means socket close.
{
break;
}
receive += std::string(recvBuf,recvBytes);
std::cout<<recvBuf<<std::endl;
} while (recvBytes > 0);
socket.Close();
socket.Clean();
std::cout<<receive<<std::endl;
}
return 0;
}
LCL_data原创于CSDN blog,转载请注明。