简单代理服务器C代码实现(SOLARIS)
/ns/wz/comp/data/20040502233237.htm
					/*
**	编写:无可非议
**	来源:WWW.20CN.NET
**	注意:请注明转贴来源
*/
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <signal.h>
#include <arpa/inet.h> 
#include <netdb.h> 
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/stat.h>
int  m_MainId = 0;			//主进程ID
int  m_ListenSocket = 0;		//侦听套接字
char m_ConnectAddr[256] = {0};		//目标地址
char m_ConnectPort[256] = {0};		//目标端口
/*	
**	函数名称:	GetListenSocket
**	函数功能:	生成侦听套接字	
**	传入参数:	Port : 侦听端口
**	传出参数:	无
**	引用函数:	无
**	返回值	:	侦听套接字,为0时表示生成套接字失败,其他为套接字句柄
**	备注	:	无
*/
int GetListenSocket(int Port)
{
	struct sockaddr_in	m_LisAddr = {0}; 
	int 			m_Socket = 0;
	int			m_AddrLen = sizeof(struct sockaddr_in);
	
	//配置端口信息
	m_LisAddr.sin_family = AF_INET; 
	m_LisAddr.sin_port = htons(Port); 
	m_LisAddr.sin_addr.s_addr = INADDR_ANY; 
	
	//创建套接字
	if ((m_Socket = socket(AF_INET,SOCK_STREAM,0)) < 0 ) 
	{ 
		//创建套接字失败
		return 0; 
	} 
	
	//绑定套接字
	if(bind(m_Socket, (sockaddr*)&m_LisAddr , m_AddrLen) < 0 ) 
	{ 
		//绑定套接字失败
		close(m_Socket);
		return 0;
	} 
	
	//侦听套接字
	if(listen(m_Socket,5)) 
	{ 
		//侦听套接字失败
		close(m_Socket);
		return 0;
	} 
	
	//侦听套接字生成成功
	return m_Socket;
}
/*	
**	函数名称:	GetConnectSocket
**	函数功能:	生成连接套接字	
**	传入参数:	pServerAddr : 连接地址 pServerPort : 连接端口
**	传出参数:	无
**	引用函数:	无
**	返回值	:	连接套接字,为0时表示生成套接字失败,其他为套接字句柄
**	备注	:	无
*/
int GetConnectSocket(char* pServerAddr,char* pServerPort)
{
	struct sockaddr_in	m_ServerAddr = {0}; 
	int			m_AddrLen = sizeof(struct sockaddr_in);
	int			m_Socket = 0;
	//初始化连接信息
	m_ServerAddr.sin_addr.S_un.S_addr = inet_addr(pServerAddr);
	m_ServerAddr.sin_port = htons(atoi(pServerPort)); 
	m_ServerAddr.sin_family = AF_INET; 
	//创建发送套接字
	m_Socket = socket(AF_INET,SOCK_STREAM,0);
	if(m_Socket <= 0)
	{
		//失败
		return NULL;
	}
	
	//连接客户计算机
	if(connect(m_Socket,(sockaddr*)&m_ServerAddr,m_AddrLen) < 0 ) 
	{ 
		close(m_Socket); 
		return NULL;
	}
	//连接成功
	return m_Socket;
}
/*	
**	函数名称:	TransSocket
**	函数功能:	完成套接字数据转发	
**	传入参数:	m_SendSocket : 发送套接字 m_RecvSocket : 接收套接字
**	传出参数:	无
**	引用函数:	无
**	返回值	:	无
**	备注	:	逆反完成全双工
*/
void TransSocket(int m_SendSocket,int m_RecvSocket) 
{ 
	char m_Buf[512 * 1024] = {0};
	int ret = 0;
	fd_set readset;
	struct timeval tm = {0};
	tm.tv_sec = 3600 * 24;
	FD_ZERO(&readset);
	FD_SET(m_RecvSocket,&readset);
	while(1)
	{
		if((select(m_RecvSocket + 1,&readset,NULL,NULL,&tm) 
			<= 0))
		{
			//出错
			break;
		}
		if(!FD_ISSET(m_RecvSocket,&readset)) continue;
		ret = recv(m_RecvSocket,m_Buf,512 * 1024 - 1,0);
		if(ret < 0)
		{
			//出错
			break;
		}
		send(m_SendSocket,m_Buf,ret,0);
	}
	close(m_SendSocket);
	close(m_RecvSocket);
} 
/*	
**	函数名称:	SocketTrans
**	函数功能:	工作主函数,完成数据转发,新进程启动	
**	传入参数:	m_SendSocket : 发送套接字 m_RecvSocket : 接收套接字
**	传出参数:	无
**	引用函数:	无
**	返回值	:	无
**	备注	:	逆反完成全双工
*/
void SocketTrans()
{
	struct sockaddr_in	m_WorkAddr = {0}; 
	int	    		m_191Socket = 0;
	int			m_147socket = 0;
	int			m_WorkAddrLen = 0;
	//开始任务执行
	while(1) 
	{ 
		//接受147的连接
		m_WorkAddrLen = sizeof(struct sockaddr_in); 
		m_147socket = accept(m_ListenSocket, 
			(sockaddr*)&m_WorkAddr , &m_WorkAddrLen); 
			
		//检查套接字合法性
		if(m_147socket < 0) continue;
		
		//连接191
		m_191Socket = GetConnectSocket(m_ConnectAddr,m_ConnectPort);
		if(m_191Socket == NULL)
		{
			close(m_147socket);
			continue;
		}
		int ret = fork();
		if(ret < 0)
		{
			//建立新进程失败
			printf("致命错误,无法建立新进程!\n");
			fflush(stdout);
			close(m_191Socket);
			close(m_147socket);
			break;
		}
		else if(ret == 0)
		{
			//关闭原来端口
			close(m_ListenSocket);
			//建立二次子进程,防止僵尸进程
			ret = fork();
			if(ret < 0)
			{
				close(m_191Socket);
				close(m_147socket);
				_exit(0);
			}
			else if(ret == 0)
			{
				//接收进程
				TransSocket(m_191Socket,m_147socket); 
				_exit(0);
			}
			ret = fork();
			if(ret < 0)
			{
				close(m_191Socket);
				close(m_147socket);
				_exit(0);
			}
			else if(ret == 0)
			{
				//发送进程
				TransSocket(m_147socket,m_191Socket);
				_exit(0);
			}
			close(m_191Socket);
			close(m_147socket);
			_exit(0);
		}
	
		//等待子线程结束
		close(m_191Socket);
		close(m_147socket);
		waitpid(ret,NULL,0);
	} 
}
/*	
**	函数名称:	sig_usr
**	函数功能:	进程信号处理函数	
**	传入参数:	无
**	传出参数:	无
**	引用函数:	无
**	返回值	:	无
**	备注	:	处理进程终止事件
*/
static void sig_usr(int signo)
{
	close(m_ListenSocket);
	if(m_MainId == getpid())
		kill(0,SIGKILL);
	exit(0);
}
static void sig_ign(int signo)
{
	fprintf(stderr,"signal %d catched ,ignoring\n",signo);
}
int daemon_init()
{
    pid_t pid;
    if((pid=fork())<0){
        return -1;
    }else if(pid!=0){
        exit(0);
    }
    setsid();
    umask(0);
    return 0;
}
/*	
**	函数名称:	main
**	函数功能:	进程主函数	
**	传入参数:	无
**	传出参数:	无
**	引用函数:	MakeFilePath,GetMyInitInfo,SocketTrans
**	返回值	:	无
**	备注	:	为客户接收进程主函数
*/
int main(int argc,char* argv[]) 
{ 
	//检查参数合法性
	if(argc != 4)
	{
		printf("格式:本地端口 目的地址 目的端口\n");
		fflush(stdout);
		return 0;
	}
	daemon_init();
	//登记信号事件
	signal(SIGTERM,sig_usr);
	signal(SIGINT,sig_usr);
	signal(SIGQUIT,sig_usr);
	signal(SIGPIPE,sig_ign);
	signal(SIGALRM,sig_ign);
	signal(SIGQUIT,sig_ign);
	signal(SIGFPE,sig_ign);
	signal(SIGILL,sig_ign);
	signal(SIGPIPE,sig_ign);
	signal(SIGSEGV,sig_ign);
	signal(SIGTRAP,sig_ign);
	signal(SIGTSTP,sig_ign);
	
	//取参数
	strcpy(m_ConnectAddr,argv[2]);
	strcpy(m_ConnectPort,argv[3]);
	
	//获取侦听套接字
	m_ListenSocket = GetListenSocket(atoi(argv[1]));
	if(m_ListenSocket == 0)
	{
		printf("侦听端口[%s]失败!\n",argv[1]); 
		fflush(stdout);
		return 0;
	}
	m_MainId = getpid();
	//启动文件接收侦听线程
	SocketTrans();
	close(m_ListenSocket);
	return 0;
} 
===============================================
本文版权属20CN网络安全小组及其作者所有,如有转载,请保持文章完整性并注明出处
文章类型:原创 提交:无可非议 核查:NetDemon