落霞与孤鹜齐飞,秋水共长天一色.
姊妹篇: 代理服务器 poll version: https://blog.csdn.net/fdsafwagdagadg6576/article/details/42872279
代理服务器多线程版 1:https://blog.csdn.net/fdsafwagdagadg6576/article/details/42872279
多线程代理服务器version2:https://blog.csdn.net/fdsafwagdagadg6576/article/details/42872371
#include "stdio.h"
#include "stdlib.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "netinet/tcp.h"
#include "arpa/inet.h"
#include "string.h"
#include <errno.h>
#include "sys/time.h"
#include "sys/times.h"
#include <unistd.h>
#include "sys/types.h"
#include "sys/stropts.h"
#include <signal.h>
#include <time.h>
#include "sockopt.h"
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
#define msglen 1500
int serverfd,clientfd;
int bindlisten();
int clientconn();
void closemap(int sockfd);
int proxy[65535]={0},user[65535]={0};
int temp;
fd_set fdset;
main () {
struct sockaddr_in tcpaddr;
int retVal;
char line[msglen]={0};
int tcpaddr_len;
int lstnScktNum;
int count=0;
int k_milliSecPerSec = 1000;
int msecWaitTime = 10000;
int errno;
struct timeval timeout;
int max_fd;
int fd,fdmap;
int client;
char *str;
int ret;
signal (SIGPIPE,SIG_IGN);
serverfd=bindlisten();
if (serverfd==-1) {
printf("bind & listen fail\n");
return -1 ;
}
FD_ZERO(&fdset);
FD_SET(serverfd, &fdset);
max_fd = serverfd;
while (1) {
fd_set oset;
//select timeout all fd reset to 0,so we need recover the save value
oset = fdset;
// Set the actual value to wait
msecWaitTime = 10000;
// Set timeout for select call to wtime
timeout.tv_sec = msecWaitTime/k_milliSecPerSec;
timeout.tv_usec = (msecWaitTime%k_milliSecPerSec)*k_milliSecPerSec;
//select test two read fd,one is from user, one is from default proxy
count=select(max_fd+1,&oset,NULL,NULL,&timeout);
if(count > 0){
for(fd = 0; fd <= max_fd; fd++){
if(FD_ISSET(fd, &oset)){
if(fd == serverfd){//server listen fd
//This is a new connection.
tcpaddr_len = sizeof(tcpaddr);
//the accept tcpaddr is diffrent from bind.it get cient ip
client =accept(fd, (struct sockaddr *)(&tcpaddr),&tcpaddr_len);
str=inet_ntoa(tcpaddr.sin_addr);
if(client > 0){
printf("Accept a new client: %d\n", client);
FD_SET(client, &fdset);
if(client > max_fd)
max_fd = client;
//connect proxy server
clientfd=clientconn();
if (clientfd==-1) {
printf("clientfd fail\n");
return -1;
}
printf("create a new connect to default proxy: %d\n", clientfd);
FD_SET(clientfd, &fdset);
if(clientfd > max_fd)
max_fd = clientfd;
//map user and default proxy socket;eg:user fd is 1,proxy fd is 5
//proxy[5]=1,user[1]=5,这样将user connect的fd和proxy connect的fd绑定
proxy[client]=clientfd;
user[clientfd]=client;
}else{
//debug scoket error
perror("accept()");
}
}else{
memset(line,0x00,msglen);
//此处可以优化为循环读
retVal = read(fd, line, msglen);
//retVal = recv(fd, line, msglen,0);
if(retVal <= 0){
if (errno==EINTR) //中断
continue;
else
closemap(fd);
}else{//forword data
if (proxy[fd]!=0) {
fdmap=proxy[fd];
ret=write(fdmap,line,retVal);
//ret=send(fdmap,line,retVal,MSG_NOSIGNAL);
if (ret <=0) {
if (errno==EINTR)
continue;
else {
printf("write to proxy srever error:%d:%s\n",
errno,strerror(errno));
closemap(fdmap);
}
} else {
printf("write to default proxy\n");
}
break;
} else if (user[fd]!=0) {
fdmap=user[fd];
printf("from %d to %d\n",fd, fdmap);
ret=write(fdmap,line,retVal);
//ret=send(fdmap,line,retVal,MSG_NOSIGNAL);
if (ret <0) {
if (errno==EINTR)
continue;
else {
printf("write to user error:%d:%s\n",
errno,strerror(errno));
closemap(fdmap);
}
} else {
printf("write to user\n");
}
break;
}
}
}
}
}
} else if (count ==0) {
continue;
}else {
printf("error:fd=%d\n",fd);
break;
}
}
for (fd=0;fd<=max_fd;fd++) {
if(FD_ISSET(fd, &fdset)){
close (fd);
}
}
fclose(C_Logfile_fd);
}
int bindlisten() {
struct sockaddr_in tcpaddr;
struct in_addr intfIpAddr;
int tcpaddr_len;
int sockfd;
int client;
int port=7000;
int bReuseaddr=1;
int retVal;
int ret;
int buf,optlen;
int on,errno;
memset( &tcpaddr, 0, sizeof(tcpaddr) );
if ( (sockfd= socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
printf ("socket create fail\n");
return -1;
}
// intitalize to hold given restrictions
tcpaddr.sin_family = AF_INET;
tcpaddr.sin_addr.s_addr = htonl(INADDR_ANY);
tcpaddr.sin_port = htons(port);
tcpaddr_len = sizeof(tcpaddr);
on=1;
errno=0;
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(char *)(&on),sizeof(on))<0)
{
printf("so_resueadd failed,error %d:%s\n",errno,strerror(errno));
return -2;
}
// make bind call
if ((retVal = bind(sockfd, (struct sockaddr *)(&tcpaddr), sizeof(tcpaddr)))< 0 )
{
fprintf(C_Logfile_fd,"bind() call failed. Error: %d, %s,port: %d\n ", errno, ( strerror(errno) ), port);
}
//listen have 5 queue
if (listen(sockfd, 5) < 0 )
{
printf("Error: Listen socket returned %d %s\n", errno, strerror(errno) );
return -1;
}
return sockfd;
}
int clientconn() {
struct sockaddr_in tcpaddr;
char ipHost[10]={0};
int ipPort=8000;
int ret;
int sockfd;
int bReuseaddr=1;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("socket create fail\n");
return -1;
}
/* Connect to the socket */
memset(&tcpaddr, 0, sizeof(tcpaddr));
//135.245.1.1 is default default proxy proxy ip
strcpy(ipHost, "135.245.1.1");
/* local host, processes must be running on the same machine ... */
/* intitalize to given address */
tcpaddr.sin_family = AF_INET;
tcpaddr.sin_addr.s_addr = inet_addr((const char *)ipHost);
tcpaddr.sin_port = htons(ipPort);
//basic connect is block, after timeout it return fail
if ((ret = connect(sockfd,(struct sockaddr *)(&tcpaddr),sizeof(tcpaddr))) < 0 ) {
printf("connect fail,retVal=%d,%s\n",errno,strerror(errno));
return 1;
}
return sockfd;
}
//close proxy and user socket fd together
void closemap (int fd) {
//The socket is wrong or closed.
close(fd);
FD_CLR(fd, &fdset);
printf("close %d\n",fd);
//remove the socketfd;one sockfd close ,peer sockfd close
if (proxy[fd]!=0) {
temp=proxy[fd];
close (proxy[fd]);
printf("client close %d\n",proxy[fd]);
FD_CLR(proxy[fd], &fdset);
proxy[fd]=0;
user[temp]=0;
} else if (user[fd]!=0) {
temp=user[fd];
close(user[fd]);
printf("server close %d\n",user[fd]);
FD_CLR(user[fd], &fdset);
user[fd]=0;
proxy[temp]=0;
}
}
网友评论