zoukankan      html  css  js  c++  java
  • 基于SOCK4网络协议的代理服务器端代码示例

    //**********************************************************************
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <windows.h>
    #include <winsock.h>
    #define BufferSize 1024*8 // 8k Buffer
    #define SOCKS4_GRANT 90
    #define SOCKS4_REJECT 91
    
    #pragma comment(lib,"ws2_32.lib")
    #pragma comment(lib,"wsock32.lib")
    
    // Some Structures To Define
    typedef struct
    {
    	SOCKET ClientSocket;
    }TSocks4Info;
    
    typedef struct
    {
    	BYTE VN; // Version Number
    	BYTE CD; // Code Of Command
    	WORD wPort; // Remote Port
    	DWORD dwIP; // Remote IP
    }Socks4Info;
    // End Of Structure
    
    static CRITICAL_SECTION cs;
    
    // Function ProtoType Declaration
    //------------------------------------------------------------------------------------------------------
    DWORD GetRemoteAddressAndPort(char *HTTPBuffer, WORD *wPort);
    BOOL SendSock4ID(SOCKET sSocket, BYTE Socks4RequestID);
    DWORD WINAPI Socks4Thread(TSocks4Info *Sock4Info);
    BOOL StartSocks4Proxy(unsigned int Sock4Port);
    BOOL Init();
    BOOL IsDigits(const char *String);
    //------------------------------------------------------------------------------------------------------
    // End Of Fucntion ProtoType Declaration
    
    // Main Function
    int main(int argc,char *argv[])
    {
    	unsigned int Sock4Port; // Define Sock4 Listening Port
    	if (argc != 2) // Require Two Arguments
    	{
    		printf("Usage: %s Port
    ",argv[0]); // Display Usage
    		return -1; // Quit The Program
    	}
    	
    	if (!IsDigits(argv[1])) // Invalid Port Number
    	{
    		printf("Invalid Port
    "); // Display Error Message
    		return -1; // Quit The Program
    	}
    	
    	Sock4Port = atoi(argv[1]); // Convert String Into Unsigned Int Format,And Store Into Sock4Port
    	if (Sock4Port <= 0 || Sock4Port > 65535) // The Port Out Of Bound
    	{
    		printf("The Port Out Of Bound
    "); // Display Error Message
    		return -1; // Quit The Program
    	}
    	
    	if (!Init()) // Socket StartUP Fails
    	{
    		printf("Fail To StartUp
    "); // Display Error Message
    		return -1; // Quit The Program
    	}
    	
    	StartSocks4Proxy(Sock4Port); // Start The Proxy
    	WSACleanup(); // Clean UP
    	DeleteCriticalSection(&cs); // Delete Critical Section
    	return 0; // Quit The Program
    }// End Of Main Method
    
    //------------------------------------------------------------------------------------
    // Purpose: To Get The Remote IP And Port From The Buffer
    // Return Type: DWORD
    // Parameters:
    // In: char *HTTPBuffer --> The HTTP Buffer Containing Remote IP And Port
    // Out: DWORD *wPort --> Store The Remote Port And Returen To The Caller
    //------------------------------------------------------------------------------------
    DWORD GetRemoteAddressAndPort(char *HTTPBuffer, WORD *wPort)
    {
    	// All Variable Stuff
    	DWORD dwIP, Socks4InfoSize = sizeof(Socks4Info);
    	struct hostent* pHostEnt;
    	DWORD dwIndex = 0;
    	char ServerAddress[BufferSize] = {0};
    	Socks4Info Socks4Request;
    	
    	memcpy(&Socks4Request, HTTPBuffer, Socks4InfoSize); // Get The Sock4 Structure
    	if ((Socks4Request.VN != 4) || (Socks4Request.CD != 1)) // Invalid Sock4 Request
    	{
    		EnterCriticalSection(&cs); // Enter Critical Section
    		printf("Invalid Socks 4 Request
    "); // Display Error Message
    		LeaveCriticalSection(&cs); // Leave Critical Section
    		return INADDR_NONE; // Return NULL Address
    	}
    	
    	*wPort = ntohs(Socks4Request.wPort); // Get The Remote Port
    	if ((Socks4Request.dwIP >> 8) == 0) // Some Shift Operation
    	{
    		strcpy(ServerAddress, &HTTPBuffer[Socks4InfoSize + strlen(&HTTPBuffer[Socks4InfoSize]) + 1]); // Get The Remote Address
    		dwIP = inet_addr(ServerAddress); // Is In Dot Form
    		if (dwIP == INADDR_NONE) // The Remote Address Is Not In Dot Form
    		{
    			pHostEnt = gethostbyname(ServerAddress); // Get The Dot Form
    			if (pHostEnt == NULL) // Fail To Get The IP
    			{
    				EnterCriticalSection(&cs); // Enter Critical Section
    				printf("Fail To Get Host By Name
    "); // Display Errory Message
    				LeaveCriticalSection(&cs); // Leave Critical Section
    				return INADDR_NONE; // Return NULL Address
    			}
    			dwIP = *((unsigned long *)pHostEnt->h_addr); // Get The Remote IP
    		}
    		return dwIP; // Return The Remote IP
    	}
    	return Socks4Request.dwIP; // We Already Get The Remote IP In The Sock4 Structure,Return It Then
    }// End Of GetRemoteAddressAndPort() Method
    
    //------------------------------------------------------------------------------------
    // Purpose: To Send The Sock4 Request
    // Return Type: Boolean
    // Parameters:
    // 1.SOCKET sSocket --> The Socket That That ID Will Send To
    // 2.BYTE SocketsRequestID --> Either Grand Or Reject
    //------------------------------------------------------------------------------------
    BOOL SendSock4ID(SOCKET sSocket, BYTE Socks4RequestID)
    {
    	Socks4Info Socks4Request; // Define Variable
    	memset(&Socks4Request, 0, sizeof(Socks4Info)); // Reset Variable
    	Socks4Request.CD = Socks4RequestID;
    	return (send(sSocket, (char *)&Socks4Request, sizeof(Socks4Info), 0) != SOCKET_ERROR); // Return Send Success Or Failure
    }// End Of SendSock4ID() Method
    
    //------------------------------------------------------------------------------------
    // Purpose: To Handle All Sock4 Traffic
    // Return Type: DWORD
    // Parameters:
    // 1.TSocks4Info *Sock4Info --> Sock4 Info
    //------------------------------------------------------------------------------------
    DWORD WINAPI Socks4Thread(TSocks4Info *Sock4Info)
    {
    	// Variables Define And Reset
    	int iRet;
    	struct sockaddr_in SockAddrIn;
    	SOCKET MySocket, ClientSocket = Sock4Info->ClientSocket;
    	BOOL ClientFlag = FALSE, ServerFlag = FALSE;
    	int iClientLen = 0, iServerLen = 0;
    	BYTE byClientBuf[BufferSize], byServerBuf[BufferSize];
    	fd_set readfds;
    	DWORD dwRemoteIP;
    	WORD wRemotePort;
    	memset(byClientBuf, 0, BufferSize);
    	
    	iRet = recv(Sock4Info->ClientSocket, (char *)byClientBuf, BufferSize, 0); // Receive Data
    	if ((iRet == SOCKET_ERROR) || (iRet == 0)) // Fail To Receive Data
    	{
    		closesocket(Sock4Info->ClientSocket); // Close Socket
    		free(Sock4Info); // Free The Allocated Ram
    		return 1; // Return To The Caller
    	}
    	
    	byClientBuf[iRet] = 0;
    	if ((dwRemoteIP = GetRemoteAddressAndPort((char *)byClientBuf, &wRemotePort)) == INADDR_NONE) // Fail To Get Remote IP And Port
    	{
    		SendSock4ID(ClientSocket, SOCKS4_REJECT); // Send The Reject ID
    		closesocket(Sock4Info->ClientSocket); // Close Socket
    		free(Sock4Info); // Free The Allocated Ram
    		return 1; // Return To The Caller
    	}
    	
    	MySocket = socket(AF_INET, SOCK_STREAM, 0); // Create A New Socket
    	if (MySocket == INVALID_SOCKET) // Fail To Create A New Socket
    	{
    		EnterCriticalSection(&cs); // Enter Critical Section
    		printf("Fail To Create Socket
    "); // Display Error Message
    		LeaveCriticalSection(&cs); // Leave Critical Section
    		SendSock4ID(ClientSocket, SOCKS4_REJECT); // Send The Reject ID
    		closesocket(Sock4Info->ClientSocket); // Close Socket
    		free(Sock4Info); // Free The Allowed Ram
    		return 1; // Return To The Caller
    	}
    	
    	BOOL Val = 1;
    	if (setsockopt(MySocket, SOL_SOCKET, SO_KEEPALIVE, (char *)(&Val), sizeof(BOOL)) != 0) // Set Socket Option(KeepAlive) Fail
    	{
    		EnterCriticalSection(&cs); // Enter Critical Section
    		printf("Fail To Set Socket Option
    "); // Display Error Message
    		LeaveCriticalSection(&cs); // Leave Critical Section
    		SendSock4ID(ClientSocket, SOCKS4_REJECT); // Send Reject ID
    		closesocket(Sock4Info->ClientSocket); // Close Socket
    		closesocket(MySocket); // Close Socket
    		free(Sock4Info); // Free Allocated Ram
    		return 1; // Return To The Caller
    	}
    	
    	// All Socket Stuff
    	SockAddrIn.sin_family = AF_INET;
    	SockAddrIn.sin_port = htons(wRemotePort);
    	SockAddrIn.sin_addr.s_addr = dwRemoteIP;
    	
    	iRet = connect(MySocket, (struct sockaddr *) &SockAddrIn, sizeof(SockAddrIn)); // Connect To The Remote IP
    	if (iRet == SOCKET_ERROR) // Fail To Connect
    	{
    		EnterCriticalSection(&cs); // Enter Critical Section
    		printf("Fail To Connect To %s
    ",inet_ntoa(SockAddrIn.sin_addr)); // Display Error Message
    		LeaveCriticalSection(&cs); // Leave Critical Section
    		SendSock4ID(ClientSocket, SOCKS4_REJECT); // Send Reject ID
    		closesocket(ClientSocket); // Close Socket
    		closesocket(MySocket); // Close Socket
    		free(Sock4Info); // Free Allocated Ram
    		return 1; // Return To The Caller
    	}
    	
    	if (!SendSock4ID(ClientSocket, SOCKS4_GRANT)) // We Fail To Send The Grant ID
    	{
    		EnterCriticalSection(&cs); // Enter Critical Section
    		printf("Fail To Send Grant ID
    "); // Display Error Message
    		LeaveCriticalSection(&cs); // Leave Critical Section
    		closesocket(Sock4Info->ClientSocket); // Close Socket
    		closesocket(MySocket); // Close Socket
    		free(Sock4Info); // Free Allocated Ram
    		return 1; // Return To The Caller
    	}
    	
    	EnterCriticalSection(&cs); // Enter Critical Section
    	printf("Connected to: %s:%d ThreadID:%X
    ",inet_ntoa(SockAddrIn.sin_addr), wRemotePort, GetCurrentThreadId()); // Display Successful Message
    	LeaveCriticalSection(&cs); // Leave Critical Section
    	
    	while(TRUE) // Sock4 Traffic Starts
    	{
    		FD_ZERO(&readfds); // Reset The Readable Socket Flag
    		FD_SET(MySocket, &readfds); // Set MySocket As Readable
    		FD_SET(ClientSocket, &readfds); //Send ClientSocket As Readable
    		iRet = select(0, &readfds, NULL, NULL, NULL); // Select Any Readable Socket
    		if (iRet == SOCKET_ERROR) // We Fail To Get Any Readable Socket
    		{
    			break; // Leave The Loop
    		}
    		// Below Are All About Send And Receive Stuff,Pretty Tedious To Explain.Read It YouSelf
    		if (iClientLen < BufferSize)
    		{
    			if ((FD_ISSET(ClientSocket, &readfds)) && (!ClientFlag))
    			{
    				iRet = recv(ClientSocket, (char *)&byClientBuf[iClientLen], BufferSize-iClientLen, 0);
    				if (iRet == 0 || iRet == SOCKET_ERROR)
    				{
    					break;
    				}
    				ClientFlag = TRUE;
    				iClientLen += iRet;
    			}
    		}
    		if (ClientFlag)
    		{
    			iRet = send(MySocket, (char *)byClientBuf, iClientLen, 0);
    			if (iRet == SOCKET_ERROR)
    			{
    				break;
    			}
    			ClientFlag = FALSE;
    			iClientLen = 0;
    		}
    		if (iServerLen < BufferSize)
    		{
    			if ((FD_ISSET(MySocket, &readfds)) && (!ServerFlag))
    			{
    				iRet = recv(MySocket, (char *)&byServerBuf[iServerLen], BufferSize-iServerLen, 0);
    				if (iRet == 0 || iRet == SOCKET_ERROR)
    				{
    					break;
    				}
    				ServerFlag = TRUE;
    				iServerLen += iRet;
    			}
    		}
    		if (ServerFlag)
    		{
    			iRet = send(ClientSocket, (char *)byServerBuf, iServerLen, 0);
    			if (iRet == SOCKET_ERROR)
    			{
    				break;
    			}
    			ServerFlag = FALSE;
    			iServerLen = 0;
    		}
    	}
    	closesocket(MySocket); // Close Socket
    	closesocket(ClientSocket); // Close Socket
    	free(Sock4Info); // Free Allocated Ram
    	return 0; // Return To The Caller
    }// End Of Socks4Thread() Method
    
    //------------------------------------------------------------------------------------
    // Purpose: To Start The Socks4 Proxy
    // Return Type: Boolean
    // Parameters:
    // 1.unsigned int Sock4Port --> The Port Listening On
    //------------------------------------------------------------------------------------
    BOOL StartSocks4Proxy(unsigned int Sock4Port)
    {
    	// All Variables Define
    	SOCKADDR_IN saServer;
    	int iRet;
    	SOCKET ListenSocket; // socket to listen
    	SOCKET ClientSocket; // Client socket
    	DWORD dwThreadID;
    	TSocks4Info *Sock4Info;
    	
    	saServer.sin_family = AF_INET; // Address Family(Internet)
    	saServer.sin_addr.s_addr = INADDR_ANY; // Let WinSock Assign Address
    	saServer.sin_port = htons(Sock4Port); // Port Number
    	
    	ListenSocket = socket( AF_INET, SOCK_STREAM,IPPROTO_TCP); // Create A New Socket
    	if (ListenSocket == INVALID_SOCKET) // Fail To Create A New Socket
    	{
    		printf("Fail To Create Listening Socket
    "); // Display Error Message
    		return FALSE; // Return False
    	}
    	
    	iRet = bind(ListenSocket, (LPSOCKADDR)&saServer, sizeof(struct sockaddr)); // Bind The Socket
    	if (iRet == SOCKET_ERROR) // Fail To Bind
    	{
    		printf("Fail To Bind Socket
    "); // Display Error Message
    		closesocket(ListenSocket); // Close Socket
    		return FALSE; // Return False
    	}
    	
    	iRet = listen(ListenSocket, SOMAXCONN); // Listen On The Socket
    	if (iRet == SOCKET_ERROR) // Fail To Listen
    	{
    		printf("Fail To Listen On The Socket
    "); // Display ErrorMessage
    		closesocket(ListenSocket); // Close Socket
    		return FALSE; // Return False
    	}
    	
    	printf("Socks 4 Server Started On Port %d
    ",Sock4Port); // The Sock4 Proxy Is Started Successfully
    	
    	while(TRUE)
    	{
    		ClientSocket = accept(ListenSocket, NULL, NULL); // Accept Incoming Connection
    		if (ClientSocket == SOCKET_ERROR) // Fail To Accept Connection
    		{
    			break; // Leave The Loop
    		}
    		
    		BOOL Val = 1;
    		if (setsockopt(ClientSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)(&Val), sizeof(BOOL)) != 0) // Set The Socket As Keepalive Fail
    		{
    			closesocket(ClientSocket); // Close The Socket
    			continue; // Begin A New Loop
    		}
    		
    		if ((Sock4Info = (TSocks4Info *)malloc(sizeof(TSocks4Info))) == NULL) // Allocate Ram Fail
    		{
    			closesocket(ClientSocket); // Close Socket
    			closesocket(ListenSocket); // Close Socket
    			return FALSE; // Return False
    		}
    		
    		Sock4Info->ClientSocket = ClientSocket; // Get The Socket
    		if (CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Socks4Thread, (LPVOID)Sock4Info, 0, &dwThreadID) == NULL) // Fail To Create A New Thread
    		{
    			closesocket(ClientSocket); // Close Socket
    			continue; // Begin A New Loop
    		}
    	}
    	
    	closesocket(ListenSocket); // Close Socket
    	return TRUE; // Return To The Caller
    }// End Of StartSocks4Proxy() Method
    
    //-------------------------------------------------------------------------
    // Purpose: To Initize Socket
    // Return Type: Boolean
    // Parameters: NULL
    // This Is Too Simple,I Won't Comment It
    //-------------------------------------------------------------------------
    BOOL Init()
    {
    	WSADATA data;
    	WORD ver;
    	
    	ver = MAKEWORD(2,2);
    	if (WSAStartup( ver, &data ) != 0 )
    	{
    		return FALSE;
    	}
    	InitializeCriticalSection(&cs);
    	return TRUE;
    }// End Of Init() Method
    
    //-------------------------------------------------------------------------
    // Purpose: To Check Whether A String Is All Digits
    // Return Type: Boolean
    // Parameters: cosnt char *String --> The String To Be Checked
    //-------------------------------------------------------------------------
    BOOL IsDigits(const char *String)
    {
    	unsigned int i = 0;
    	unsigned int StringLength = strlen(String); // Get The Length Of The String
    	
    	//One By One To Check Every Character
    	for (i = 0;i < StringLength;i++)
    	{
    		if (String[i] < 48 || String[i] > 57) // The Character Is Not One Of 0 To 9
    		{
    			return FALSE; // Return False
    		}
    	}
    	return TRUE; // Return True
    }// End Of IsDigits() Method
    // End Of File 
    
     
    
  • 相关阅读:
    StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(二)小车端
    StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(一)准备工作
    公司名称后缀 Inc. Co.,Ltd.
    Linux C定时器使用指南
    配置QQ企业邮箱小结
    常用PHP文件操作函数
    Git基本命令 -- 基本工作流程 + 文件相关操作
    Git基本命令 -- 创建Git项目
    Entity Framework Core 2.0 入门
    用VSCode开发一个asp.net core2.0+angular5项目(5): Angular5+asp.net core 2.0 web api文件上传
  • 原文地址:https://www.cnblogs.com/microzone/p/3204019.html
Copyright © 2011-2022 走看看