简单代理服务器C代码实现(SOLARIS)

本文介绍了一种基于C语言的网络套接字编程实现方案,包括侦听套接字和连接套接字的生成、数据转发等功能。通过具体代码展示了如何进行套接字创建、绑定、监听及数据收发等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导读:
  ** 返回值 : 侦听套接字,为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 <  {
  //出错
  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

本文转自
http://www.20cn.net/ns/wz/comp/data/20040502233237.htm
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值