⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 think_net.c

📁 网络编程封装,xcvxxcvxcvxcvxv
💻 C
字号:
#include "think_net.h"

int think_netstart(void)
{
#ifdef __THINK_WINDOWS__
	WSADATA data;
	
	if(WSAStartup(MAKEWORD(2,2),&data)<0){
		think_error(0,"[%s]:WSAStartup error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		return -1;
	}
#endif
	
	return 0;
}
int think_netstop(void)
{
#ifdef __THINK_WINDOWS__
	if(WSACleanup()<0){
		think_error(0,"[%s]:WSACleanup error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		return -1;
	}
#endif

	return 0;
}

THINK_NET *think_netconnect(const char *ip,unsigned short port)
{
	struct sockaddr_in servaddr;
	int sockfd;
	THINK_NET *net;

	bzero(&servaddr,sizeof(struct sockaddr_in));
	servaddr.sin_family=AF_INET;
	servaddr.sin_port=htons(port);
	if((servaddr.sin_addr.s_addr=inet_addr(ip))==INADDR_NONE){
		think_error(0,"[%s]:inet_addr error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		return NULL;
	}
	if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
		think_error(0,"[%s]:socket create error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		return NULL;
	}
	if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(struct sockaddr_in))<0){
		think_error(0,"[%s]:connect error.[%d:%s][%s:%d]",__func__,think_socketerrno,think_strerror(think_socketerrno),ip,port);
		socketclose(sockfd);
		return NULL;
	}
	if((net=malloc(sizeof(THINK_NET)))==NULL){
		think_error(0,"[%s]:malloc error.[%d:%s]",__func__,think_errno,think_strerror(think_errno));
		socketclose(sockfd);
		return NULL;
	}
	memset(net,0x00,sizeof(THINK_NET));
	net->sockfd=sockfd;
	snprintf(net->ip,sizeof(net->ip),"%s",ip);
	net->port=port;

	return net;
}
THINK_NET *think_netlisten(const char *ip,unsigned short port)
{
	struct sockaddr_in servaddr;
	int sockfd;
	struct linger so_linger;
	int option;
	THINK_NET *net;

	bzero(&servaddr,sizeof(struct sockaddr_in));
	servaddr.sin_family=AF_INET;
	servaddr.sin_port=htons(port);
	if(strcmp(ip,"*")==0){
		servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
	}else{
		if((servaddr.sin_addr.s_addr=inet_addr(ip))==INADDR_NONE){
			think_error(0,"[%s]:inet_addr error.[%d:%s][%s:%d]",__func__,think_socketerrno,think_strerror(think_socketerrno),ip,port);
			return NULL;
		}
	}
	if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
		think_error(0,"[%s]:socket create error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		return NULL;
	}
	so_linger.l_onoff=1;
	so_linger.l_linger=0;
	if(setsockopt(sockfd,SOL_SOCKET,SO_LINGER,(void *)&so_linger,sizeof(so_linger))<0){
		think_error(0,"[%s]:setsockopt error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		socketclose(sockfd);
		return NULL;
	}
	option=1;
	if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(void *)&option,sizeof(option))<0){
		think_error(0,"[%s]:setsockopt error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		socketclose(sockfd);
		return NULL;
	}
	option=1;
	if(setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,(void *)&option,sizeof(option))<0){
		think_error(0,"[%s]:setsockopt error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		socketclose(sockfd);
		return NULL;
	}
	if(bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))<0){
		think_error(0,"[%s]:bind error.[%d:%s][%s:%d]",__func__,think_socketerrno,think_strerror(think_socketerrno),ip,port);
		socketclose(sockfd);
		return NULL;
	}
	if(listen(sockfd,5)<0){
		think_error(0,"[%s]:listen error.[%d:%s][%s:%d]",__func__,think_socketerrno,think_strerror(think_socketerrno),ip,port);
		socketclose(sockfd);
		return NULL;
	}
	if((net=malloc(sizeof(THINK_NET)))==NULL){
		think_error(0,"[%s]:malloc error.[%d:%s]",__func__,think_errno,think_strerror(think_errno));
		socketclose(sockfd);
		return NULL;
	}
	memset(net,0x00,sizeof(THINK_NET));
	net->sockfd=sockfd;
	snprintf(net->ip,sizeof(net->ip),"%s",ip);
	net->port=port;

	return net;
}
THINK_NET *think_netaccept(THINK_NET *net)
{
	struct sockaddr_in addr;
	socklen_t addrlen;
	int sockfd;
	char *p;
	THINK_NET *client;

	addrlen=sizeof(addr);
	if((sockfd=accept(net->sockfd,(struct sockaddr *)&addr,&addrlen))<0){
		think_error(0,"[%s]:accept error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		return NULL;
	}
	if((p=inet_ntoa(addr.sin_addr))==NULL){
		think_error(0,"[%s]:inet_ntoa error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		return NULL;
	}
	if((client=malloc(sizeof(THINK_NET)))==NULL){
		think_error(0,"[%s]:malloc error.[%d:%s]",__func__,think_errno,think_strerror(think_errno));
		socketclose(sockfd);
		return NULL;
	}
	memset(client,0x00,sizeof(THINK_NET));
	client->sockfd=sockfd;
	snprintf(client->ip,sizeof(client->ip),"%s",p);
	client->port=ntohs(addr.sin_port);

	return client;
}

int think_netrecv(THINK_NET *net,void *buf,unsigned int siz,int flags)
{
	int n,nbytes;

	for(nbytes=0;siz>0;nbytes+=n,siz-=n){
		if((n=recv(net->sockfd,(char *)buf+nbytes,siz,0))<=0){
			think_error(0,"[%s]:read error![%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
			return -1;
		}
		if(!(flags & THINK_NET_WAIT))
			return n;
	}

	return nbytes;
}
int think_netsend(THINK_NET *net,const void *buf,unsigned int len,int flags)
{
	int n,nbytes;

	for(nbytes=0;len>0;nbytes+=n,len-=n){
		if((n=send(net->sockfd,(char *)buf+nbytes,len,0))<=0){
			think_error(0,"[%s]:write error![%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
			return -1;
		}
		if(!(flags & THINK_NET_WAIT))
			return n;
	}

	return nbytes;
}
int think_netadd(THINK_NETLIST **netlist,THINK_NET *net)
{
	THINK_NETLIST *head,*tail;
	THINK_NETLIST *p;

	if((p=malloc(sizeof(THINK_NETLIST)))==NULL){
		think_error(0,"[%s]:malloc error.[%d:%s]",__func__,think_errno,think_strerror(think_errno));
		return -1;
	}
	p->net=net;
	p->prior=NULL;
	p->next=NULL;
	if(*netlist==NULL){
		p->prior=p;
		p->next=p;
		*netlist=p;
	}else{
		head=*netlist;
		tail=(*netlist)->prior;
		p->prior=tail;
		tail->next=p;
		p->next=head;
		head->prior=p;
	}

	return 0;
}

int think_netdel(THINK_NETLIST **netlist,THINK_NET *net)
{
	THINK_NETLIST *p;

	if((p=think_netfind(*netlist,net))==NULL){
		think_error(0,"[%s]:net not found.",__func__);
		return -1;
	}
	p->net=NULL;

	return 0;
}
THINK_NETLIST *think_netfind(THINK_NETLIST *netlist,THINK_NET *net)
{
	THINK_NETLIST *p;
	
	if(netlist==NULL)
		return NULL;
	p=netlist;
	do{
		if(p->net==net)
			return p;
		p=p->next;
	}while(p!=netlist);

	return NULL;
}
int think_netclean(THINK_NETLIST **netlist)
{
	THINK_NETLIST *next,*prior;
	THINK_NETLIST *p;

	if(*netlist==NULL)
		return 0;
	/* netclean */
	p=*netlist;
	do{
		if(p==*netlist && p->net==NULL){
			if(p==p->next){
				*netlist=NULL;
				free(p);
				return 0;
			}else{
				*netlist=p->next;
				next=p->next;
				prior=p->prior;
				prior->next=next;
				next->prior=prior;				
				free(p);
				p=*netlist;
				continue;
			}
		}
		if(p->net!=NULL){
			p=p->next;
			if(p==*netlist)
				break;
			continue;
		}
		next=p->next;
		prior=p->prior;
		prior->next=next;
		next->prior=prior;
		free(p);
		p=next;
		if(p==*netlist)
			break;
	}while(1);

	return 0;
}

int think_netselect(THINK_NETLIST **netlist,int timeout)
{
	fd_set fdrset,fdwset,fdeset;
	int maxfd;
	THINK_NET *net;
	THINK_NETLIST *p;
	struct timeval t,*pt;
	int r;

	think_netclean(netlist);
	if(*netlist==NULL)
		return 0;
	FD_ZERO(&fdrset);
	FD_ZERO(&fdwset);
	FD_ZERO(&fdeset);
	maxfd=0;
	p=*netlist;
	do{
		net=p->net;
		if(net->flags & THINK_NET_READ)
			FD_SET(net->sockfd,&fdrset);
		if(net->flags & THINK_NET_WRITE)
			FD_SET(net->sockfd,&fdwset);
		if(net->flags & THINK_NET_ERROR)
			FD_SET(net->sockfd,&fdeset);
		maxfd=net->sockfd>maxfd?net->sockfd:maxfd;
		p=p->next;
	}while(p!=*netlist);
	if(timeout<0)
		pt=NULL;
	else{
		pt=&t;
		t.tv_sec=0;
		t.tv_usec=timeout;
	}
	if((r=select(maxfd+1,&fdrset,&fdwset,&fdeset,pt))<0){
		think_error(0,"[%s]:select error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		return -1;
	}
	if(r==0)
		return 0;
	p=*netlist;
	do{
		net=p->net;
		if(FD_ISSET(net->sockfd,&fdrset))
			net->flags|=THINK_NET_READ;
		if(FD_ISSET(net->sockfd,&fdwset))
			net->flags|=THINK_NET_WRITE;
		if(FD_ISSET(net->sockfd,&fdeset))
			net->flags|=THINK_NET_ERROR;
		p=p->next;
	}while(p!=*netlist);

	return r;
}

int think_netclose(THINK_NET *net)
{
	THINK_NET_BUFLIST *p;

	socketclose(net->sockfd);
	/* free rlist */
	while(net->rlist){
		p=net->rlist;
		if(p==p->next){
			free(p);
			break;
		}
		p->next->prior=p->prior;
		p->prior->next=p->next;
		net->rlist=p->next;
		free(p);
	}
	
	/* free wlist */
	while(net->wlist){
		p=net->wlist;
		if(p==p->next){
			free(p);
			break;
		}
		p->next->prior=p->prior;
		p->prior->next=p->next;
		net->wlist=p->next;
		free(p);
	}
	free(net);

	return 0;
}
int think_netsendtobuflist(THINK_NET *net,const void *buf,unsigned int len)
{
	THINK_NET_BUFLIST *p,*head,*tail;
	int pos,n;
	char *buffer;

	for(pos=0;pos<len;pos+=n,net->nwbytes+=n){
		n=len-pos>THINK_NET_BUFSIZE?THINK_NET_BUFSIZE:len-pos;
		if((buffer=malloc(n))==NULL){
			think_error(0,"[%s]:malloc error![%d:%s]",__func__,think_errno,think_strerror(think_errno));
			return -1;
		}
		memcpy(buffer,buf,n);
		if((p=malloc(sizeof(THINK_NET_BUFLIST)))==NULL){
			think_error(0,"[%s]:malloc error![%d:%s]",__func__,think_errno,think_strerror(think_errno));
			free(buffer);
			return -1;
		}
		memset(p,0x00,sizeof(THINK_NET_BUFLIST));
		p->buf=(char *)buffer;
		p->pos=0;
		p->len=n;
		p->prior=NULL;
		p->next=NULL;
		if(net->wlist==NULL){
			p->next=p;
			p->prior=p;
			net->wlist=p;
		}else{
			head=net->wlist;
			tail=net->wlist->prior;
			p->prior=tail;
			p->next=head;
			tail->next=p;
			head->prior=p;
		}
	}

	return 0;
}
int think_netrecvtobuflist(THINK_NET *net)
{
	THINK_NET_BUFLIST *p,*head,*tail;
	char *buf;
	int n;

	if((buf=malloc(THINK_NET_BUFSIZE))==NULL){
		think_error(0,"[%s]:malloc error![%d:%s]",__func__,think_errno,think_strerror(think_errno));
		return -1;
	}
	if((n=think_netrecv(net,buf,THINK_NET_BUFSIZE,0))<=0){
		think_errorerror();
		free(buf);
		return -1;
	}
	if((p=malloc(sizeof(THINK_NET_BUFLIST)))==NULL){
		think_error(0,"[%s]:malloc error![%d:%s]",__func__,think_errno,think_strerror(think_errno));
		free(buf);
		return -1;
	}
	memset(p,0x00,sizeof(THINK_NET_BUFLIST));
	p->buf=buf;
	p->pos=0;
	p->len=n;
	p->prior=NULL;
	p->next=NULL;
	if(net->rlist==NULL){
		p->prior=p;
		p->next=p;
		net->rlist=p;
	}else{
		head=net->rlist;
		tail=net->rlist->prior;
		p->prior=tail;
		p->next=head;
		tail->next=p;
		head->prior=p;
	}
	net->nrbytes+=n;

	return 0;
}

int think_netsendfrombuflist(THINK_NET *net)
{
	THINK_NET_BUFLIST *p,*prior,*next;
	char *buf;
	int n,pos,len;

	buf=net->wlist->buf;
	len=net->wlist->len;
	pos=net->wlist->pos;
	if((n=think_netsend(net,buf+pos,len,0))<=0)
		return -1;
	net->nwbytes-=n;
	len-=n;
	pos+=n;
	net->wlist->len=len;
	net->wlist->pos=pos;
	if(len>0)
		return 0;
	p=net->wlist;
	if(p==p->next){
		free(p->buf);
		free(p);
		net->wlist=NULL;
	}else{
		prior=p->prior;
		next=p->next;
		prior->next=next;
		next->prior=prior;
		net->wlist=next;
		free(p->buf);
		free(p);
	}

	return 0;
}
int think_netrecvfrombuflist(THINK_NET *net,void *buf,unsigned int siz)
{
	THINK_NET_BUFLIST *p,*prior,*next;
	int n,len;

	for(len=0;len<siz;len+=n,net->nrbytes-=n){
		p=net->rlist;
		if(!p)
			break;
		n=siz-len>p->len?p->len:siz-len;
		memcpy((char *)buf+len,p->buf+p->pos,n);
		p->len-=n;
		p->pos+=n;
		if(p->len==0){
			if(p==p->next){
				free(p->buf);
				free(p);
				net->rlist=NULL;
			}else{
				prior=p->prior;
				next=p->next;
				prior->next=next;
				next->prior=prior;
				net->rlist=next;
				free(p->buf);
				free(p);
			}
		}
	}

	return len;
}
int think_netselectbybuflist(THINK_NETLIST **netlist,int timeout)
{
	fd_set fdrset,fdwset,fdeset;
	int maxfd;
	THINK_NET *net;
	THINK_NETLIST *p;
	struct timeval t,*pt;
	int r;
	
	think_netclean(netlist);
	if(*netlist==NULL)
		return 0;
	FD_ZERO(&fdrset);
	FD_ZERO(&fdwset);
	FD_ZERO(&fdeset);
	maxfd=0;
	p=*netlist;
	do{
		net=p->net;
		net->flags&=~THINK_NET_READ;
		net->flags&=~THINK_NET_WRITE;
		net->flags&=~THINK_NET_ERROR;
		FD_SET(net->sockfd,&fdrset); /* read */
		if(net->wlist)
			FD_SET(net->sockfd,&fdwset); /* write */
		FD_SET(net->sockfd,&fdeset); /* error */
		maxfd=net->sockfd>maxfd?net->sockfd:maxfd;
		p=p->next;
	}while(p!=*netlist);
	if(timeout<0)
		pt=NULL;
	else{
		pt=&t;
		t.tv_sec=0;
		t.tv_usec=timeout;
	}
	if((r=select(maxfd+1,&fdrset,&fdwset,&fdeset,pt))<0){
		think_error(0,"[%s]:select error.[%d:%s]",__func__,think_socketerrno,think_strerror(think_socketerrno));
		return -1;
	}
	if(r==0)
		return 0;
	p=*netlist;
	do{
		net=p->net;
		if(FD_ISSET(net->sockfd,&fdrset))
			net->flags|=THINK_NET_READ;
		if(FD_ISSET(net->sockfd,&fdwset))
			net->flags|=THINK_NET_WRITE;
		if(FD_ISSET(net->sockfd,&fdeset))
			net->flags|=THINK_NET_ERROR;
		p=p->next;
	}while(p!=*netlist);
	
	return r;
}
int think_netpeekfrombuflist(THINK_NET *net,void *buf,unsigned int siz)
{
	THINK_NET_BUFLIST *p;
	int n,len;
	
	len=0;
	p=net->rlist;
	do{
		n=siz-len>p->len?p->len:siz-len;
		memcpy((char *)buf+len,p->buf+p->pos,n);
		len+=n;
		if(len==siz)
			break;
		p=p->next;
	}while(p!=net->rlist);
	
	return len;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -