wow-socket文件说明

这篇文章详细描述了Wow-socket库中关于网络套接字的操作,包括打开、关闭、连接、绑定、监听、接受、发送数据以及设置/获取socket参数等功能,以及获取连接目标地址和本地地址信息的方法。
摘要由CSDN通过智能技术生成

wow-socket文件说明

  • 项目地址:https://gitee.com/wow-iot/wow-iot7
  • 本文件的的功能主要用于socket操作,主要涉及打开、关闭、连接(支持IP与域名方式)、监听、接收、发送消息、接收消息、获取/设置参数、获取本地/对象信息;

打开与关闭

int wow_socket_open(SocketType_E eType)
{
	switch(eType){
		case SOCKET_TYPE_TCP:
			return socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
		case SOCKET_TYPE_UDP:
			return socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
		default:
			break;
	}
	
	return PARAM_INPUT_ARG_INVALID;
}

void wow_socket_close(int nSktfd)
{
	CHECK_RET_VOID(nSktfd >= 0);

	shutdown(nSktfd,SHUT_RDWR);
	close(nSktfd);
}

连接(支持IP与域名方式)

int wow_socket_connect(int nSktfd,const char *pcAddr, uint16_t u16Port,uint32_t u32TimeoutMs)
{
	CHECK_RET_VAL_P(nSktfd >= 0 ,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");
	(void)u32TimeoutMs;
	int ret = -1;

	
	struct sockaddr_in saddr;
	bzero(&saddr, sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(u16Port);

	if(pcAddr && _host_is_ip(pcAddr) == 0){
		inet_pton(AF_INET,pcAddr, &saddr.sin_addr); 
		
		struct hostent *he;
		he = gethostbyname(pcAddr);///<耗时 尽可能不使用
		CHECK_RET_VAL(he,-1);
		memcpy(&saddr.sin_addr, he->h_addr, sizeof(struct in_addr));
	}else{
		saddr.sin_addr.s_addr = pcAddr? inet_addr(pcAddr):INADDR_ANY;
	}
	
	ret = connect(nSktfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
	if((ret == 0) ||  (ret < 0 && errno == EISCONN)){//EISCONN 已建立连接
		return 0;
	} 
	else if (ret < 0 && errno == EINPROGRESS){//非阻塞模式下
		//判断链接是否成功
		fd_set wset;
		struct timeval tv;
		tv.tv_sec  = u32TimeoutMs *1000;
		tv.tv_usec = u32TimeoutMs%1000 *1000;
		FD_ZERO(&wset);
		FD_SET(nSktfd, &wset);

		ret = select(nSktfd+1, NULL, &wset, NULL,&tv);
		CHECK_RET_VAL_P_A(ret > 0 ,-SYSTEM_SELECT_FAILED, "select false!\n");
		if(FD_ISSET(nSktfd, &wset)){
			int err = -1;
			socklen_t len = sizeof(int);
			ret = getsockopt(nSktfd,  SOL_SOCKET, SO_ERROR ,&err, &len);
			CHECK_RET_VAL_P_A(ret == 0 ,-SOCKET_GET_OPT_FAILED, "select sockfd not set");
		}
		return 0;
	}
	
	return -WOW_FAILED;
}

绑定(默认本机任意地址)

	int wow_socket_bind(int nSktfd,const char *pcAddr, uint16_t u16Port)
	{
		CHECK_RET_VAL_P(nSktfd >= 0 ,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");

		int  ret = 0;
		
	///<端口地址释放后立即生效 支持端口重载
	///<端口复用最常用的用途应该是防止服务器重启时之前绑定的端口还未释放或者程序突然退出而系统没有释放端口
	#ifdef SO_REUSEADDR
		int reuseaddr = 1;
		ret = setsockopt(nSktfd, SOL_SOCKET, SO_REUSEADDR, (int *)&reuseaddr, sizeof(reuseaddr));
		CHECK_RET_VAL_P_A(ret == 0,-SOCKET_SET_OPT_FAILED,"reuse addr failed!\n");
	#endif

	#ifdef SO_REUSEPORT
		int reuseport = 1;
		ret = setsockopt(nSktfd, SOL_SOCKET, SO_REUSEPORT, (int *)&reuseport, sizeof(reuseport));
		CHECK_RET_VAL_P_A(ret == 0,-SOCKET_SET_OPT_FAILED,"reuse port failed!\n");
	#endif

		struct sockaddr_in saddr;
		/*为TCP链接设置IP和端口等信息*/
		bzero(&saddr, sizeof(saddr));
		saddr.sin_family = AF_INET;
		saddr.sin_addr.s_addr = pcAddr? inet_addr(pcAddr):INADDR_ANY;
		saddr.sin_port = htons(u16Port);

		/*地址与socket绑定bind*/
		return bind(nSktfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
		
	}

监听

int wow_socket_listen(int nSktfd, size_t snMaxc)
{
	CHECK_RET_VAL_P(nSktfd >= 0 ,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");

	if(snMaxc == 0){
		char *ptr;
		if((ptr = getenv("LISTENQ")) != NULL){
			snMaxc = atoi(ptr);
		}else{
			snMaxc = 1024;
		}

	}
	return listen(nSktfd, snMaxc);
	
}

等待接收

int wow_socket_accept(int nSktfd,char *pcAddr, uint16_t* u16Port)
{
	CHECK_RET_VAL_P(nSktfd >= 0 ,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");

	struct sockaddr_in saddr = {0};
	socklen_t len = sizeof(struct sockaddr_in);

	int fd = accept(nSktfd, (struct sockaddr *)&saddr, &len);
	CHECK_RET_VAL(fd > 0,-SOCKET_ACCEPT_FAILED);
	
///<减少反应延迟
#ifdef TCP_NODELAY	
	int enable = 1;
	setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&enable, sizeof(enable));
#endif

	if(pcAddr){
		strcpy(pcAddr,inet_ntoa(saddr.sin_addr)); 
	}
	if(u16Port){
		*u16Port = ntohs(saddr.sin_port);
	} 

	return fd;
}

接收信息

int wow_socket_trecv(int nSktfd, uint8_t* pu8Data, size_t snSize)
{
	CHECK_RET_VAL_P(nSktfd >= 0 && snSize > 0,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");
	CHECK_RET_VAL_P(pu8Data , -PARAM_INPUT_DATA_IS_NULL ,"param input data invalid!\n");

	//read(nSktfd,pu8Data,snSize);
	int real = recv(nSktfd, pu8Data, snSize, MSG_DONTWAIT);

	if (real >= 0) return real;
	if (errno == EINTR || errno == EAGAIN) return real;
	
	return -WOW_FAILED;
}
int wow_socket_urecv(int nSktfd,char *pcAddr, uint16_t* u16Port,uint8_t* pu8Data, size_t snSize)
{
	CHECK_RET_VAL_P(nSktfd >= 0 && snSize > 0,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");
	CHECK_RET_VAL_P(pu8Data && pcAddr && u16Port, -PARAM_INPUT_DATA_IS_NULL ,"param input data invalid!\n");

	struct sockaddr_in saddr = {0};
	socklen_t  len = sizeof(struct sockaddr_in);
	int ret = recvfrom(nSktfd, pu8Data,snSize, 0, (struct sockaddr*)&saddr, &len);

	if (ret >= 0){
		if(pcAddr){
			strcpy(pcAddr,inet_ntoa(saddr.sin_addr)); 
		}
		if(u16Port){
			*u16Port = ntohs(saddr.sin_port);
		} 
		return ret;
	}
	if (errno == EINTR || errno == EAGAIN) return 0;
	
	return -WOW_FAILED;
}

发送信息

int wow_socket_tsend(int nSktfd,const uint8_t* pu8Data, size_t snSize)
{
	CHECK_RET_VAL_P(nSktfd >= 0 && snSize > 0,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");
	CHECK_RET_VAL_P(pu8Data , -PARAM_INPUT_DATA_IS_NULL ,"param input data invalid!\n");

	//write(nSktfd,pu8Data,snSize);
	int real = send(nSktfd, pu8Data,snSize, MSG_NOSIGNAL);

	if (real >= 0) return real;
	if (errno == EINTR || errno == EAGAIN) return real;
	
	return -WOW_FAILED;;
}

int wow_socket_usend(int nSktfd,const char *pcAddr, uint16_t u16Port,const uint8_t* pu8Data, size_t snSize)
{
	CHECK_RET_VAL_P(nSktfd >= 0 && snSize > 0,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");
	CHECK_RET_VAL_P(pu8Data && pcAddr && u16Port, -PARAM_INPUT_DATA_IS_NULL ,"param input data invalid!\n");;

	struct sockaddr_in saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_addr.s_addr = inet_addr(pcAddr);
	saddr.sin_port = htons(u16Port);

	int ret  = sendto(nSktfd, pu8Data, snSize, 0, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
	if (ret  >= 0) return ret;
	if (errno == EINTR || errno == EAGAIN) return ret;
	
	return -WOW_FAILED;
}

设置/获取socket参数

int wow_socket_setopt(int nSktfd, SocketCtrl_E eCtrl, ...)
{
	CHECK_RET_VAL_P(nSktfd >= 0 && eCtrl < SOCKET_CTRL_MAX,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");

	va_list args;
	va_start(args, eCtrl);

	switch (eCtrl)
	{
	case SOCKET_CTRL_SET_BLOCK://设置阻塞模式
		{
			int block = (int)va_arg(args, int);
			va_end(args);
			
			if (block){
				fcntl(nSktfd, F_SETFL, fcntl(nSktfd, F_GETFL) & ~O_NONBLOCK);
			} else{
				fcntl(nSktfd, F_SETFL, fcntl(nSktfd, F_GETFL) | O_NONBLOCK);
			} 
		}
		break;
	case SOCKET_CTRL_GET_BLOCK://获取阻塞模式
		{
			int* block = (int*)va_arg(args, int*);
			va_end(args);
			
			CHECK_RET_VAL_P(block, -PARAM_INPUT_DATA_IS_NULL,"param input data invalid!\n");
			*block = (fcntl(nSktfd, F_GETFL) & O_NONBLOCK)? 0 : 1;
		}
		break;
	case SOCKET_CTRL_SET_TCP_NODELAY://设置 nodelay 功能 1 表示打开,0 表示关闭
		{
			int nagle = (int)va_arg(args, int);
			va_end(args);
			int ret = setsockopt(nSktfd, IPPROTO_TCP, TCP_NODELAY, (char*)&nagle, sizeof(int));
			CHECK_RET_VAL_P_A(ret == 0, -SOCKET_SET_OPT_FAILED,"setsockopt false!\n");
		}
		break;
	case SOCKET_CTRL_GET_TCP_NODELAY://获取 nodelay 功能
		{
			// the penable
			int* nagle = (int*)va_arg(args, int*);
			va_end(args);
			CHECK_RET_VAL_P(nagle, -PARAM_INPUT_DATA_IS_NULL,"param input data invalid!\n");

			
			int enable = 0;
			socklen_t len = sizeof(enable);
			int ret = getsockopt(nSktfd, IPPROTO_TCP, TCP_NODELAY, (char*)&enable, &len);
			CHECK_RET_VAL_P_A(ret == 0, -SOCKET_GET_OPT_FAILED,"getsockopt false!\n");
			
			*nagle = enable;
		}
		break;
	case SOCKET_CTRL_SET_RECV_BUFF_SIZE://设置读缓冲区大小
		{
			int size = (int)va_arg(args, int);
			va_end(args);
			
			int ret = setsockopt(nSktfd, SOL_SOCKET, SO_RCVBUF, (char*)&size, sizeof(int));
			CHECK_RET_VAL_P_A(ret == 0, -SOCKET_SET_OPT_FAILED,"setsockopt false!\n");
		}
		break;
	case SOCKET_CTRL_GET_RECV_BUFF_SIZE://获取读缓冲区大小
		{
			int* size = (int*)va_arg(args, int*);
			va_end(args);
			CHECK_RET_VAL_P(size, -PARAM_INPUT_DATA_IS_NULL,"param input data invalid!\n");

			int  real = 0;
			socklen_t len = sizeof(real);
			int ret = getsockopt(nSktfd, SOL_SOCKET, SO_RCVBUF, (char*)&real, &len);
			CHECK_RET_VAL_P_A(ret == 0, -SOCKET_GET_OPT_FAILED,"getsockopt false!\n");

			*size = real;
		}
		break;
	case SOCKET_CTRL_SET_SEND_BUFF_SIZE://设置写缓冲区大小 
		{
			int size = (int)va_arg(args, int);
			va_end(args);
			
			int ret = setsockopt(nSktfd, SOL_SOCKET, SO_SNDBUF, (char*)&size, sizeof(int));
			CHECK_RET_VAL_P_A(ret == 0, -SOCKET_SET_OPT_FAILED,"setsockopt false!\n");
		}
		break;
	case SOCKET_CTRL_GET_SEND_BUFF_SIZE://获取写缓冲区大小 
		{
			int* size = (int*)va_arg(args, int*);
			va_end(args);
			CHECK_RET_VAL_P(size, -PARAM_INPUT_DATA_IS_NULL,"param data input invalid!\n");

			int  real = 0;
			socklen_t len = sizeof(real);
			int ret = getsockopt(nSktfd, SOL_SOCKET, SO_SNDBUF, (char*)&real, &len);
			CHECK_RET_VAL_P_A(ret == 0, -SOCKET_GET_OPT_FAILED,"getsockopt false!\n");

			*size = real;
		}
		break;
	case SOCKET_CTRL_SET_KEEPALIVE:
		{
			int enable = (int)va_arg(args, int);
			va_end(args);
			
			int ret = setsockopt(nSktfd, SOL_SOCKET, SO_KEEPALIVE, (char*)&enable, sizeof(int));
			CHECK_RET_VAL_P_A(ret == 0, -SOCKET_SET_OPT_FAILED,"setsockopt false!\n");
		}
		break;
	case SOCKET_CTRL_SET_TCP_KEEPINTVL:
		{
			int intvl = (int)va_arg(args, size_t);
			va_end(args);
			
			int ret = setsockopt(nSktfd, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&intvl, sizeof(int));
			CHECK_RET_VAL_P_A(ret == 0, -SOCKET_SET_OPT_FAILED,"setsockopt false!\n");
		}
		break;
	default:
		return -WOW_FAILED;
	}


	return 0;
}

获取连接目标地址信息

int wow_socket_peerName(int nSktfd,char *pcAddr, uint16_t* u16Port)
{
	int ret = -1;
	
	CHECK_RET_VAL_P(nSktfd >= 0,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");
	CHECK_RET_VAL_P(pcAddr && u16Port, -PARAM_INPUT_DATA_IS_NULL ,"param input data invalid!\n");


	struct sockaddr_in saddr;
	socklen_t len = sizeof(struct sockaddr_in);
	memset(&saddr, 0, len);

	ret = getpeername(nSktfd , (struct sockaddr *)&saddr, &len);
	CHECK_RET_VAL_P_A(ret==0,-1,"getpeername false!");

	strcpy(pcAddr,inet_ntoa(saddr.sin_addr)); 
	*u16Port = ntohs(saddr.sin_port);

	return 0;
}

获取本地地址信息

int wow_socket_localName(int nSktfd,char *pcAddr, uint16_t* u16Port)
{
	CHECK_RET_VAL_P(nSktfd >= 0,-PARAM_INPUT_ARG_INVALID,"param input arg invalid!\n");
	CHECK_RET_VAL_P(pcAddr && u16Port, -PARAM_INPUT_DATA_IS_NULL ,"param input data invalid!\n");

	struct sockaddr_in saddr = {0};
	socklen_t len = sizeof(struct sockaddr_in);
	int  ret = getsockname(nSktfd, (struct sockaddr *)&saddr,&len);
	CHECK_RET_VAL_P_A(ret == 0,-1,"getsockname fasle!\n");
	
	strcpy(pcAddr,inet_ntoa(saddr.sin_addr)); 
	*u16Port = ntohs(saddr.sin_port);

	return 0;
}
  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值