簡單Proxy 伺服器C代碼實現(SOLARIS)

來源:互聯網
上載者:User
/*
** 編寫:無可非議
** 來源: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;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.