setsockopt中SO_LINGER选项的使用

windows平台,vs2010IDE,C++编程语言

  • 问题:socketTool软件建立Server,自编软件实现Client,在退出Client时,Server报下面的异常,如图1所示

图1

原因:

在建立Socket时,使用到了 SO_LINGER 选项,函数如下:

struct linger  so_linger;
so_linger.l_onoff = 1;
so_linger.l_linger = 0;
setsockopt(sock->hSocket,SOL_SOCKET,SO_LINGER, (char *)&so_linger,sizeof(so_linger));		//关闭时直接关闭

linger的值为0,就会出现上面的问题。

解决方法:

关闭该功能,即onOff为0或者linger给大于0的值

  • SO_LINGER

// 以下是转自: 老鱼_新浪博客点击打开链接

SO_LINGER,如果选择此选项, close或 shutdown将等到所有套接字里排队的消息成功发送或到达延迟时间后>才会返回. 否则, 调用将立即返回。

    该选项的参数(option_value)是一个linger结构:
        struct linger {
            int   l_onoff;   
            int   l_linger;  
        };
如果linger.l_onoff值为0(关闭),则清 sock->sk->sk_flag中的SOCK_LINGER位;否则,置该位,并赋sk->sk_lingertime值为 linger.l_linger。

  • 我的工程示例程序
EXPORT_DLL void *  DLL_EXPORT CreateNetMbDevice(char *strServerIP, unsigned short port)
{
	char zero=0;
	char NotZero = 1;
	int BufSize=1500;
	//int nZero=1500;
   
    CMbDevice *dev = new CMbDevice;	

	//MbDeviceInit(dev);		//初始化modbus设备

	CMySocket *sock = new CMySocket;
    //QTcpSocket *socket = new QTcpSocket;
	//sock->hSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	//初始化WSA
	WORD sockVersion = MAKEWORD(2,2);
	WSADATA wsaData;
	if(WSAStartup(sockVersion, &wsaData)!=0)
	{
		delete dev;
		delete sock;
		DllDebugOut("WSAStartup failed:%d", GetLastError());
		return(NULL);
	}

	//sock->hSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	sock->hSocket=socket(AF_INET,SOCK_STREAM,0);
	if(sock->hSocket==INVALID_SOCKET)
	{	
		dev->param = NULL;
		DllDebugOut("Invalid socket \n");
		return(NULL);
	}

#if 0
	// linux下
	struct timeval tv;	
	tv.tv_sec = 0;
	tv.tv_usec = 200 * 1000;
#else
	// windows下
	int tv = SOCKETTIOMEOUT;		// 超时时间
#endif
	setsockopt(sock->hSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));				// 设置网络接收延时
	setsockopt(sock->hSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));
	setsockopt(sock->hSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&NotZero, 1);				// 设置网络非延时传输
	setsockopt(sock->hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&BufSize, sizeof(BufSize));
	setsockopt(sock->hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&BufSize, sizeof(BufSize));		

	// 设置了该功能,则在测试时,退出时SocketTool会报错
	
	struct linger  so_linger;
	so_linger.l_onoff = 1;
	so_linger.l_linger = 0;
	setsockopt(sock->hSocket,SOL_SOCKET,SO_LINGER, (char *)&so_linger,sizeof(so_linger));		//关闭时直接关闭

    strcpy_s(sock->strServerIP,sizeof(sock->strServerIP),strServerIP);

	sock->port = port;

    dev->adu_type	= ADU_TYPE_MBAP;
    dev->pfnRead		= net_read;
    dev->pfnSend		= net_send;   
    dev->retry_times = 3;
    dev->server_addr = 1;    //网络设备不需要该参数
    dev->sem = new CSemaphore(1,1);
    dev->param = sock;

	//CMySocket *sock = (CMySocket *)dev->param;
	SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr(sock->strServerIP);		// 本机地址,服务器在本机开启
    addrSrv.sin_family=AF_INET;
    addrSrv.sin_port=htons(sock->port);// 设置端口号

	if(connect(sock->hSocket, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))	// 连接服务器 应使用非阻塞式调用	
	{
		printf("Socket connect error !");
		closesocket(sock->hSocket);
		delete dev;
		delete sock;
		return(NULL);
	}

	// 测试
	char * sendData = "你好,TCP服务端,我是客户端!\n";
	send(sock->hSocket, sendData, strlen(sendData), 0);

    //connect(socket, SIGNAL(connected()), 0, SLOT(connectedSlot()));
    //socket->SetTimeout(tmo_second);	
    return(dev);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值