|
|
简单代理服务器C代码实现(SOLARIS) |
|
|
作者:未知 来源:月光软件站 加入时间:2005-5-13 月光软件站 |
/* ** 编写:无可非议 ** 来源: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; }

|
|
相关文章:相关软件: |
|