SOCKS5代理(源码)

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


SOCKS5是个代理服务器协议。

我这里有个可用的基本实现,下面列出的代码不包含框架和辅助功能,仅包含客户端连接建立后的处理,没有认证(因为用的是IP地址限制,连接建立之前就审查过了)。

实现不完整,不支持BIND,FTP协议可以使用PASV绕开这个问题。

没有给出实现的函数基本看名字就可以猜出功能。

头文件:

cpp 复制代码
//servicethreadsocks.h
//SOCKS协议的处理

#ifndef servicethreadsocks_h
#define servicethreadsocks_h

//SOCKS协议处理线程
DWORD ServiceThreadSocks(LPDWORD lpdwParam);

//版本标识/方法选择
STATE SocksMethodSelect(SOCKET s,char * buf,int buflen,int * cmd,int * method);

//方法选择
BYTE SelectMethod(BYTE * msg);

//方法:00
//接收用户请求(方法00)
STATE SocksRecvRequest00(SOCKET s,char * buf,int buflen,int * cmd);

//命令01(CONNECT)处理(方法00)
STATE SocksCmd01Method00(LPDWORD lpdwParam,SOCKADDR_IN *);

//命令03(UDP ASSOCIATE)处理(方法00)
STATE SocksCmd03Method00(LPDWORD lpdwParam,SOCKADDR_IN *);

#endif//servicethreadsocks_h

实现文件:

cpp 复制代码
//servicethreadsocks.cpp

#include "stdafx.h"
#include "mystd.h"

//SOCKS协议处理线程
DWORD ServiceThreadSocks(LPDWORD lpdwParam)
{
//--线程参数处理------------------------
	int cdindex;//连接数据索引
	struct ServiceData * servicedata;

	cdindex=((struct ThreadUserData *)lpdwParam)->index;
	servicedata=((struct ThreadUserData *)lpdwParam)->servicedata;
//--------------------------------------
	struct ConnectionData * cd;
	struct LogStruct * logs;

	cd=&servicedata->connectiondataarray.pconnectiondata[cdindex];
	if(-1!=cd->log)
	{
		logs=servicedata->memlogfile.logstruct+cd->log;
	}
	else
	{
		logs=NULL;
	}
//----------------------------------------
	struct ConfigInfo * pci;
	pci=&servicedata->serviceconfigfiledata.configarray[cd->serviceindex];

	int method;
	char host[256];
	SOCKADDR_IN sa;
	char resp[10];

	//构造错误应答
	resp[0]=5;//版本
	//resp[1]=//应答
	resp[2]=0;//保留
	resp[3]=1;//IPV4
	memset(resp+4,0,6);

	//退出?
	if(CONNECTIONDATA_CMD_QUIT==cd->cmd)
	{
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return (DWORD)-1;
	}

	//版本标识/方法选择过程,method返回选中的方法
	//隐含调用SelectMethod选择一个方法
	if(1!=SocksMethodSelect(cd->sdc.s,cd->sdc.buf,BUFFERSIZE,&cd->cmd,&method))
	{
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return (DWORD)-2;
	}

	//方法子协商结果,仅支持无认证(方法0x00)
	switch(method)
	{
	case 0x00://无认证
		break;
	case 0xff://没有可接受的方法
	default:
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return (DWORD)-3;
	}
	
	//接收用户请求
	if(1!=SocksRecvRequest00(cd->sdc.s,cd->sdc.buf,BUFFERSIZE,&cd->cmd))
	{
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return (DWORD)-4;
	}
	//记录日志
	if(-1!=cd->log)
	{
		time(&logs->timestart);
	}
	//取得目标主机
	switch((BYTE)cd->sdc.buf[3])
	{
	case 0x01://IP V4
		memcpy(&(sa.sin_addr.S_un.S_addr),cd->sdc.buf+4,4);
		sa.sin_family=AF_INET;
		memcpy(&sa.sin_port,cd->sdc.buf+8,2);
		if(-1!=cd->log)
		{
			strcpy(logs->domainname,inet_ntoa(sa.sin_addr));
		}
		break;
	case 0x03://domain name
		if(cd->sdc.buf[4]>=256)
		{
			resp[1]='\x01';
			send(cd->sdc.s,resp,10,0);
			closesocket(cd->sdc.s);
			if(-1!=cd->log)
			{
				logs->state=LOGSTRUCT_STATE_NOUSE;
			}
			cd->state=CONNECTION_NOUSE;
			return (DWORD)-5;
		}
		memcpy(host,cd->sdc.buf+5,cd->sdc.buf[4]);
		host[cd->sdc.buf[4]]='\0';
		if(1!=GetAddrByHost(sa.sin_addr.S_un.S_addr,host))
		{
			resp[1]='\x04';
			send(cd->sdc.s,resp,10,0);
			closesocket(cd->sdc.s);
			if(-1!=cd->log)
			{
				logs->state=LOGSTRUCT_STATE_NOUSE;
			}
			cd->state=CONNECTION_NOUSE;
			return (DWORD)-5;
		}
		sa.sin_family=AF_INET;
		memcpy(&sa.sin_port,cd->sdc.buf+4+1+cd->sdc.buf[4],2);
		if(-1!=cd->log)
		{
			strcpy(logs->domainname,host);
		}
		break;
	case 0x04://IP V6
	default:
		resp[1]='\x08';
		send(cd->sdc.s,resp,10,0);//0x08,地址类型不支持
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return (DWORD)-6;
		break;
	}
	//转移至命令处理,在命令处理内部结束所有操作
	switch(method)
	{
	case 0x00://无认证
		switch(cd->sdc.buf[1])
		{
		case 0x01://CONNECT
			if(pci->isenablesocksconnect)
				SocksCmd01Method00(lpdwParam,&sa);
			else
			{
				resp[1]='\x02';//请求因不符合规则而被拒绝
				send(cd->sdc.s,resp,10,0);
				closesocket(cd->sdc.s);
				if(-1!=cd->log)
				{
					logs->state=LOGSTRUCT_STATE_NOUSE;
				}
				cd->state=CONNECTION_NOUSE;
			}
			break;
		case 0x03://UDP ASSOCIATE
			if(-1!=cd->log)
			{
				mystrcat(logs->domainname,256," - UDP ASSOCIATE",FALSE);
			}
			SocksCmd03Method00(lpdwParam,&sa);
			break;
		case 0x02://BIND
			//直接下落
		default:
			resp[1]='\x07';//命令未实现
			send(cd->sdc.s,resp,10,0);
			closesocket(cd->sdc.s);
			if(-1!=cd->log)
			{
				logs->state=LOGSTRUCT_STATE_NOUSE;
			}
			cd->state=CONNECTION_NOUSE;
			break;
		}
		break;
	default:
		break;
	}

	//结束,不做任何处理
	return 1;
}

//版本标识/方法选择
STATE SocksMethodSelect(SOCKET s,char * buf,int buflen,int * cmd,int * method)
{
	BYTE nmethods;

	int recvcount=0;
	int recvall=0;

	BOOL tempbool;
	struct timeval timeout;
	timeout.tv_sec=0;
	timeout.tv_usec=100000;

	//接收消息
	for(;1;)
	{
		//退出?
		if(CONNECTIONDATA_CMD_QUIT==*cmd)
		{
			return -1;
		}
		if(1!=IsSocketReadReady(s,timeout,tempbool))
		{
			return -2;
		}
		if(tempbool)
		{
			recvcount=recv(s,buf+recvall,buflen-recvall,0);
		}
		else
		{
			continue;
		}
		if(SOCKET_ERROR==recvcount)
		{
			return -3;
		}
		else if(0==recvcount)
		{
			return -4;
		}
		recvall+=recvcount;
		if(recvall>=1)
		{
			if(0x05!=(BYTE)buf[0])
			{
				return -5;
			}
		}
		if(recvall>2)
		{
			nmethods=buf[1];
			if(recvall>=nmethods+2)
			{
				break;
			}
		}
	}

	//选择方法
	*method=SelectMethod((BYTE*)buf);
	buf[1]=(BYTE)(*method);

	//发送 方法选择 消息
	if(SOCKET_ERROR==send(s,buf,2,0))
	{
		return -6;
	}

	return 1;
}

//方法选择
BYTE SelectMethod(BYTE * msg)
{
	int i;

	for(i=msg[1];i;i--)
	{
		if(0x00==msg[i+1])
		{
			return msg[i+1];
		}
	}
	return 0xff;
}

//接收用户请求(方法0x00)
STATE SocksRecvRequest00(SOCKET s,char * buf,int buflen,int * cmd)
{
	BYTE atyp;
	BOOL isrecvend=FALSE;

	int recvcount=0;
	int recvall=0;

	BOOL tempbool;
	struct timeval timeout;
	timeout.tv_sec=0;
	timeout.tv_usec=100000;

	//接收消息
	for(;1;)
	{
		//退出?
		if(CONNECTIONDATA_CMD_QUIT==*cmd)
		{
			return -1;
		}
		if(1!=IsSocketReadReady(s,timeout,tempbool))
		{
			return -2;
		}
		if(tempbool)
		{
			recvcount=recv(s,buf+recvall,buflen-recvall,0);
		}
		else
		{
			continue;
		}
		if(SOCKET_ERROR==recvcount)
		{
			return -3;
		}
		else if(0==recvcount)
		{
			return -4;
		}
		recvall+=recvcount;
		if(recvall>=1)
		{
			if(0x05!=(BYTE)buf[0])
			{
				return -5;
			}
		}
		if(recvall>6)
		{
			atyp=buf[3];
			switch(atyp)
			{
			case 0x01://IP V4
				if(recvall>=10)
				{
					isrecvend=TRUE;
				}
				break;
			case 0x03://domain name
				if(recvall>=7+buf[4])
				{
					isrecvend=TRUE;
				}
				break;
			case 0x04://IP V6
				if(recvall>=22)
				{
					isrecvend=TRUE;
				}
				break;
			}
		}
		if(isrecvend)
		{
			break;
		}
	}

	return 1;
}

//*命令01(CONNECT)处理(方法00)
STATE SocksCmd01Method00(LPDWORD lpdwParam,SOCKADDR_IN * psa)
{
//--线程参数处理------------------------
	int cdindex;//连接数据索引
	struct ServiceData * servicedata;

	cdindex=((struct ThreadUserData *)lpdwParam)->index;
	servicedata=((struct ThreadUserData *)lpdwParam)->servicedata;
//--------------------------------------
	struct ConnectionData * cd;
	struct LogStruct * logs;

	cd=&servicedata->connectiondataarray.pconnectiondata[cdindex];
	if(-1!=cd->log)
	{
		logs=servicedata->memlogfile.logstruct+cd->log;
	}
	else
	{
		logs=NULL;
	}
//----------------------------------------
	char str[256];
	char str2[256];
	char * pstr;
	char resp[10];

	//构造应答
	resp[0]=5;//版本
	//resp[1]=//应答
	resp[2]=0;//保留
	resp[3]=1;//IPV4
	memcpy(resp+4,&psa->sin_addr.S_un.S_addr,4);
	memcpy(resp+8,&psa->sin_port,2);

	//建立SOCKET
	if(INVALID_SOCKET==(cd->sdr.s=socket(AF_INET,SOCK_STREAM,0)))
	{
		resp[1]='\x01';
		send(cd->sdc.s,resp,10,0);
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -1;
	}

	//退出?
	if(CONNECTIONDATA_CMD_QUIT==cd->cmd)
	{
		closesocket(cd->sdc.s);
		closesocket(cd->sdr.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -2;
	}
	
	//连接
	if(SOCKET_ERROR==connect(cd->sdr.s,(struct sockaddr *)psa,sizeof(*psa)))
	{
		resp[1]='\x04';
		send(cd->sdc.s,resp,10,0);
		closesocket(cd->sdc.s);
		closesocket(cd->sdr.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -3;
	}
	else
	{
		resp[1]='\x00';
		send(cd->sdc.s,resp,10,0);
		if(-1!=cd->log)
		{
			strcpy(logs->domainname,"SOCKS:CONNECT -> ");
			strcpy(str,"");
			switch((BYTE)cd->sdc.buf[3])
			{
			case 0x01://IP V4
				if(NULL!=(pstr=inet_ntoa(psa->sin_addr)))
				{
					strcpy(str,pstr);
				}
				else
				{
					strcpy(str,"???");
				}
				break;
			case 0x03://domain name
				memcpy(str,cd->sdc.buf+5,cd->sdc.buf[4]);
				str[cd->sdc.buf[4]]='\0';
				break;
			case 0x04://IP V6
				strcpy(str,"IP V6 - 未支持的");
				break;
			}
			mystrcat(logs->domainname,256,str,TRUE);
			strcpy(str," : ");
			itoa(ntohs(psa->sin_port),str2,10);
			mystrcat(str,256,str2,TRUE);
			mystrcat(logs->domainname,256,str,FALSE);
		}
	}

	//退出?
	if(CONNECTIONDATA_CMD_QUIT==cd->cmd)
	{
		closesocket(cd->sdc.s);
		closesocket(cd->sdr.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -4;
	}

	//接收数据并发给客户
	TransData(cd->sdr.s,cd->sdc.s,cd->sdr.buf,BUFFERSIZE,&cd->cmd,&cd->sdr.bufcount,servicedata,cd);
	//记录字节数
	if(-1!=cd->log)
	{
		logs->bytecount+=cd->sdr.bufcount;
	}

	//结束
	closesocket(cd->sdc.s);
	closesocket(cd->sdr.s);
	if(-1!=cd->log)
	{
		time(&logs->timeend);
		logs->state=LOGSTRUCT_STATE_USED;
	}
	cd->state=CONNECTION_NOUSE;

	return 1;
}

//命令03(UDP ASSOCIATE)处理(方法00)
STATE SocksCmd03Method00(LPDWORD lpdwParam,SOCKADDR_IN * psa)
{
//--线程参数处理------------------------
	int cdindex;//连接数据索引
	struct ServiceData * servicedata;

	cdindex=((struct ThreadUserData *)lpdwParam)->index;
	servicedata=((struct ThreadUserData *)lpdwParam)->servicedata;
//--------------------------------------
	struct ConnectionData * cd;
	struct LogStruct * logs;

	cd=&servicedata->connectiondataarray.pconnectiondata[cdindex];
	if(-1!=cd->log)
	{
		logs=servicedata->memlogfile.logstruct+cd->log;
	}
	else
	{
		logs=NULL;
	}
//----------------------------------------
	SOCKET udpsocket;//与远程服务器连接,sdr实际与客户连接
	int fromlen=sizeof(SOCKADDR_IN);
	SOCKADDR_IN udpsa;
	char host[256];
	char resp[10];
	BOOL tempbool;
	struct timeval timeout;
	timeout.tv_sec=0;
	timeout.tv_usec=100000;
	int i;

	//构造应答
	resp[0]=5;//版本
	//resp[1]=//应答
	resp[2]=0;//保留
	resp[3]=1;//IPV4

	//建立客户端 UDP SOCKET
	if(INVALID_SOCKET==(cd->sdr.s=socket(AF_INET,SOCK_DGRAM,0)))
	{
		resp[1]='\x01';
		send(cd->sdc.s,resp,10,0);
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -1;
	}
	//bind
	udpsa.sin_family=AF_INET;
	udpsa.sin_addr.S_un.S_addr=servicedata->serviceconfigfiledata.configarray[cd->serviceindex].sa.sin_addr.S_un.S_addr;
	udpsa.sin_port=0;
	if(SOCKET_ERROR==bind(cd->sdr.s,(sockaddr *)&udpsa,sizeof(SOCKADDR_IN)))
	{
		resp[1]='\x01';
		send(cd->sdc.s,resp,10,0);
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -1;
	}
	//connect
	udpsa.sin_family=AF_INET;
	if(0==psa->sin_addr.S_un.S_addr)
		udpsa.sin_addr.S_un.S_addr=((SOCKADDR_IN *)(&cd->saSC))->sin_addr.S_un.S_addr;
	else
		udpsa.sin_addr.S_un.S_addr=psa->sin_addr.S_un.S_addr;
	memcpy(&udpsa.sin_port,&psa->sin_port,2);
	if(SOCKET_ERROR==connect(cd->sdr.s,(sockaddr *)&udpsa,sizeof(SOCKADDR_IN)))
	{
		resp[1]='\x01';
		send(cd->sdc.s,resp,10,0);
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -1;
	}
	i=sizeof(SOCKADDR_IN);
	if(SOCKET_ERROR==getsockname(cd->sdr.s,(sockaddr *)&udpsa,&i))
	{
		resp[1]='\x01';
		send(cd->sdc.s,resp,10,0);
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -1;
	}
	memcpy(resp+4,&servicedata->serviceconfigfiledata.configarray[cd->serviceindex].sa.sin_addr.S_un.S_addr,4);//设置应答
	memcpy(resp+8,&udpsa.sin_port,2);

	//建立服务器端 UDP SOCKET
	if(INVALID_SOCKET==(udpsocket=socket(AF_INET,SOCK_DGRAM,0)))
	{
		resp[1]='\x01';
		send(cd->sdc.s,resp,10,0);
		closesocket(cd->sdc.s);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -1;
	}

	//发送应答
	resp[1]=0;
	if(SOCKET_ERROR==send(cd->sdc.s,resp,10,0))
	{
		closesocket(cd->sdc.s);
		closesocket(cd->sdr.s);
		closesocket(udpsocket);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -2;
	}

	//退出?
	if(CONNECTIONDATA_CMD_QUIT==cd->cmd)
	{
		closesocket(cd->sdc.s);
		closesocket(cd->sdr.s);
		closesocket(udpsocket);
		if(-1!=cd->log)
		{
			logs->state=LOGSTRUCT_STATE_NOUSE;
		}
		cd->state=CONNECTION_NOUSE;
		return -2;
	}

	int i_Perm;
	IN_ADDR     ipSC;
	bool bret;
	int userindex;
	int reason;

	//转发数据报
	i_Perm=0;
	for(;1;)
	{
		//根据IP检查用户许可
		i_Perm++;
		if(i_Perm>=300 && servicedata->userfiledata.IsCheckUser)
		{
			i_Perm=0;
			memcpy(&ipSC,cd->saSC.sa_data+2,4);
			if(1!=IsUserPermission(&servicedata->userfiledata,ipSC,&bret,&userindex,&reason))break;
			if(!bret)break;
		}

		//检查发起连接是否已经关闭
		if(1!=IsSocketReadReady(cd->sdc.s,timeout,tempbool))
		{
			break;
		}
		if(tempbool)
		{
			cd->sdc.bufcount=recv(cd->sdc.s,cd->sdc.buf,BUFFERSIZE,0);
			if(0==cd->sdc.bufcount || SOCKET_ERROR==cd->sdc.bufcount)
			{
				break;
			}
		}
		//检查来自客户的数据
		if(1!=IsSocketReadReady(cd->sdr.s,timeout,tempbool))
		{
			break;
		}
		if(tempbool)
		{
			cd->sdr.bufcount=recvfrom(cd->sdr.s,cd->sdr.buf,BUFFERSIZE,0,(sockaddr *)&udpsa,&fromlen);
			if(0==cd->sdr.bufcount || SOCKET_ERROR==cd->sdr.bufcount)
			{
				break;
			}
			//取得目标主机
			switch((BYTE)cd->sdr.buf[3])
			{
			case 0x01://IP V4
				memcpy(&(udpsa.sin_addr.S_un.S_addr),cd->sdr.buf+4,4);
				udpsa.sin_family=AF_INET;
				memcpy(&udpsa.sin_port,cd->sdr.buf+8,2);
				cd->sdr.bufcount-=10;
				memmove(cd->sdr.buf,cd->sdr.buf+10,cd->sdr.bufcount);
				//MessageBox(NULL,inet_ntoa(udpsa.sin_addr),"IP",MB_OK);//这一句显示目标地址
				break;
			case 0x03://domain name
				memcpy(host,cd->sdr.buf+5,cd->sdr.buf[4]);
				host[cd->sdr.buf[4]]='\0';
				if(1!=GetAddrByHost(udpsa.sin_addr.S_un.S_addr,host))
				{
					closesocket(cd->sdc.s);
					closesocket(cd->sdr.s);
					closesocket(udpsocket);
					if(-1!=cd->log)
					{
						time(&logs->timeend);
						logs->state=LOGSTRUCT_STATE_USED;
					}
					cd->state=CONNECTION_NOUSE;
					return (DWORD)-5;
				}
				udpsa.sin_family=AF_INET;
				memcpy(&udpsa.sin_port,cd->sdr.buf+4+1+cd->sdr.buf[4],2);
				cd->sdr.bufcount-=6+1+cd->sdr.buf[4];
				memmove(cd->sdr.buf,cd->sdr.buf+6+1+cd->sdr.buf[4],cd->sdr.bufcount);
				break;
			case 0x04://IP V6
				closesocket(cd->sdc.s);
				closesocket(cd->sdr.s);
				closesocket(udpsocket);
				if(-1!=cd->log)
				{
					time(&logs->timeend);
					logs->state=LOGSTRUCT_STATE_USED;
				}
				cd->state=CONNECTION_NOUSE;
				return (DWORD)-6;
				break;
			}
			//send
			if(SOCKET_ERROR==sendto(udpsocket,cd->sdr.buf,cd->sdr.bufcount,0,(sockaddr *)&udpsa,sizeof(SOCKADDR_IN)))
			{
				closesocket(cd->sdc.s);
				closesocket(cd->sdr.s);
				closesocket(udpsocket);
				if(-1!=cd->log)
				{
					time(&logs->timeend);
					logs->state=LOGSTRUCT_STATE_USED;
				}
				cd->state=CONNECTION_NOUSE;
				return -2;
			}
			if(-1!=cd->log)
			{
				logs->bytecount+=cd->sdr.bufcount;
			}
		}
		//检查来自远端的数据
		if(1!=IsSocketReadReady(udpsocket,timeout,tempbool))
		{
			break;
		}
		if(tempbool)
		{
			cd->sdr.bufcount=recvfrom(udpsocket,cd->sdr.buf,BUFFERSIZE,0,(sockaddr *)&udpsa,&fromlen);
			if(0==cd->sdr.bufcount || SOCKET_ERROR==cd->sdr.bufcount || cd->sdr.bufcount>BUFFERSIZE-10)
			{
				if(SOCKET_ERROR==cd->sdr.bufcount && 10054==WSAGetLastError())
				{
					continue;
				}
				break;
			}
			memmove(cd->sdr.buf+10,cd->sdr.buf,cd->sdr.bufcount);
			cd->sdr.bufcount+=10;
			cd->sdr.buf[0]=0;
			cd->sdr.buf[1]=0;
			cd->sdr.buf[2]=0;
			cd->sdr.buf[3]=1;
			memcpy(cd->sdr.buf+4,&udpsa.sin_addr.S_un.S_addr,4);
			memcpy(cd->sdr.buf+8,&udpsa.sin_port,2);
			//MessageBox(NULL,inet_ntoa(udpsa.sin_addr),"Source IP",MB_OK);//这一句显示源地址
			//send
			if(SOCKET_ERROR==send(cd->sdr.s,cd->sdr.buf,cd->sdr.bufcount,0))
			{
				closesocket(cd->sdc.s);
				closesocket(cd->sdr.s);
				closesocket(udpsocket);
				if(-1!=cd->log)
				{
					time(&logs->timeend);
					logs->state=LOGSTRUCT_STATE_USED;
				}
				cd->state=CONNECTION_NOUSE;
				return -2;
			}
			if(-1!=cd->log)
			{
				logs->bytecount+=cd->sdr.bufcount;
			}
		}
		//退出?
		if(CONNECTIONDATA_CMD_QUIT==cd->cmd)
		{
			closesocket(cd->sdc.s);
			closesocket(cd->sdr.s);
			closesocket(udpsocket);
			if(-1!=cd->log)
			{
				time(&logs->timeend);
				logs->state=LOGSTRUCT_STATE_USED;
			}
			cd->state=CONNECTION_NOUSE;
			return -2;
		}
	}

	closesocket(cd->sdc.s);
	closesocket(cd->sdr.s);
	closesocket(udpsocket);
	if(-1!=cd->log)
	{
		time(&logs->timeend);
		logs->state=LOGSTRUCT_STATE_USED;
	}
	cd->state=CONNECTION_NOUSE;
	return 1;
}

(这里是结束)

相关推荐
FeboReigns17 分钟前
C++简明教程(4)(Hello World)
c语言·c++
FeboReigns18 分钟前
C++简明教程(10)(初识类)
c语言·开发语言·c++
zh路西法27 分钟前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(二):从FSM开始的2D游戏角色操控底层源码编写
c++·游戏·unity·设计模式·状态模式
.Vcoistnt1 小时前
Codeforces Round 994 (Div. 2)(A-D)
数据结构·c++·算法·贪心算法·动态规划
小k_不小1 小时前
C++面试八股文:指针与引用的区别
c++·面试
沐泽Mu1 小时前
嵌入式学习-QT-Day07
c++·qt·学习·命令模式
ALISHENGYA1 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战训练三)
数据结构·c++·算法·图论
GOATLong2 小时前
c++智能指针
开发语言·c++
F-2H3 小时前
C语言:指针3(函数指针与指针函数)
linux·c语言·开发语言·c++