tcp的recv函数默认是阻塞的,就是说,假如程序运行到了recv函数处,但是tcp没有收到数据,则程序会卡在recv这里,直到收到数据为止。
一、看下面的例子:
// tcp_setsockopt.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
int main()
{
WSAData wsaData;
int m_socket;
int iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (0 == iRet)
{
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/******Linux 下如下定义:*
timeval t;
t.tv_sec = 10;
t.tv_usec = 0;
setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&t, sizeof(t));
************************/
/********windows下 定义 :*******
int iTimeOut = 10000;
setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&iTimeOut, sizeof(iTimeOut));
********/
if (INVALID_SOCKET != m_socket)
{
sockaddr_in saServer;
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(8080); //注意转化为网络节序
saServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (SOCKET_ERROR != connect(m_socket, (const sockaddr *)&saServer, (int)sizeof(saServer)))
{
while (true)
{
char szBuf[256] = { 0 };
short sRet = recv(m_socket, szBuf, 250, 0);
if (SOCKET_ERROR == sRet)
{
int nError = WSAGetLastError();
}
else if (0 == sRet)//链接断开
{
int nError = WSAGetLastError();
break;
}
else
{
printf("%s\n", szBuf);
}
}
}
}
}
WSACleanup();
return 0;
}
在不使用setsockopt的情况下,假如没有数据进入tcp,那么程序一直卡在recv函数:
只有在接收到数据时,才能走到下一步:
二、现在利用setsockopt函数,给recv函数设置一个超时限制:
int iTimeOut= 1000;//1秒
setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&iTimeOut,sizeof(int));
// tcp_setsockopt.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
int main()
{
WSAData wsaData;
int m_socket;
int iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (0 == iRet)
{
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/******Linux 下如下定义:*
timeval t;
t.tv_sec = 10;
t.tv_usec = 0;
setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&t, sizeof(t));
************************/
/********windows下 定义 :*******/
int iTimeOut = 10000;
setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&iTimeOut, sizeof(iTimeOut));
/********/
if (INVALID_SOCKET != m_socket)
{
sockaddr_in saServer;
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(8080); //注意转化为网络节序
saServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (SOCKET_ERROR != connect(m_socket, (const sockaddr *)&saServer, (int)sizeof(saServer)))
{
while (true)
{
char szBuf[256] = { 0 };
short sRet = recv(m_socket, szBuf, 250, 0);
if (SOCKET_ERROR == sRet)
{
int nError = WSAGetLastError();
}
else if (0 == sRet)//链接断开
{
int nError = WSAGetLastError();
break;
}
else
{
printf("%s\n", szBuf);
}
}
}
}
}
WSACleanup();
return 0;
}
效果:
在10秒内,程序仍然会 阻塞在recv处:
超过10秒,仍然没有数据进来,则返回sRet = -1:
假如收到了新的数据,则界面又会显示数据: