我想用C程序映射兩個端口(任何事物都轉到端口x轉到端口y,反之亦然),我寫了這個程序,但它不起作用。 這是我的代碼:如何在Linux中使用C程序映射兩個端口
int recv_all_nonblock(int sockfd,char* buff,int buffersize)
{
int numbytes;
if ((numbytes = recv(sockfd, buff, buffersize-1, MSG_NOSIGNAL|MSG_DONTWAIT)) <= 0)
{
perror("recv");
}
else if(numbytes>0)
{
buff[numbytes] = '\0';
}
return numbytes;
}
int sendall(int sockfd, char *buf, int *len)
{
int total = 0; // how many bytes we've sent
int bytesleft = *len; // how many we have left to send
int n=0;
while(total < *len)
{
n = send(sockfd, buf+total, bytesleft, MSG_NOSIGNAL|MSG_DONTWAIT);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // return number actually sent here
return n==-1?-1:0; // return -1 on failure, 0 on success
}
int Connect_To_Remote(char *Addr,char* PORT)
{
int sockfd;
struct addrinfo hints, *servinfo=NULL, *p=NULL;
int rv;
char s[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
while (p==NULL)
{
sleep(5);
while((rv = getaddrinfo(Addr, PORT, &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
sleep(5);
}
for(p = servinfo; p != NULL; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1)
{
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if (p == NULL)
{
fprintf(stderr, "client: failed to connect\n");
}
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
return sockfd;
}
int recv_all(int sockfd,char* buff,int buffersize)
{
int numbytes;
fd_set readfd_set;
struct timeval recvwait;
recvwait.tv_sec=10;
recvwait.tv_usec=0;
FD_ZERO(&readfd_set);
FD_SET(sockfd, &readfd_set);
if(select(sockfd+1, &readfd_set, NULL, NULL, &recvwait) <= 0)
{
perror("wait for recieve error:");
}
else
{
if ((numbytes = recv(sockfd, buff, buffersize-1, MSG_NOSIGNAL|MSG_DONTWAIT)) == -1)
{
perror("recv");
}
else if(numbytes>0)
{
buff[numbytes] = '\0';
}
return numbytes;
}
return 0;
}
void *Port_Mapper()
{
int sockfd,newfd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *tmpaddrinfo;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
int rv;
int yes=1;
int ret=0;
memset(&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
while (1)
{
if ((rv = getaddrinfo(NULL, MapPort, &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
sleep(2);
}
else
{
break;
}
}
while (1)
{
for(tmpaddrinfo = servinfo; tmpaddrinfo != NULL; tmpaddrinfo = tmpaddrinfo->ai_next)
{
if ((sockfd = socket(tmpaddrinfo->ai_family,tmpaddrinfo->ai_socktype,tmpaddrinfo->ai_protocol)) == -1)
{
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,sizeof(int)) == -1)
{
perror("setsockopt");
exit(1);
}
if (bind(sockfd, tmpaddrinfo->ai_addr, tmpaddrinfo->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
if (tmpaddrinfo == NULL)
{
fprintf(stderr, "server: failed to bind\n");
sleep(1);
}
else
{
break;
}
}
freeaddrinfo(servinfo); // all done with this structure
if (listen(sockfd, MAXLISTENQ) == -1)
{
perror("listen");
exit(1);
}
int bufpoint=0;
printf("server: waiting for connections...\n");
while(1)
{ // main accept() loop
char buff[MAX_SOCK_BUFFER];
char buff2[MAX_SOCK_BUFFER];
ret=0;
int sockfdweb=0;
sin_size = sizeof (their_addr);
printf("mapping server: going to accept connections...\n");
newfd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
printf("\n\nmapping server: connections accepted:%d\n",newfd);
sockfdweb=Connect_To_Remote("192.168.1.10","80");
if (sockfdweb<0)
{
printf("can not connect to %s\n","192.168.1.10");
break;
}
while(1)
{
memset(buff,0,sizeof(buff));
ret=recv_all_nonblock(newfd,buff,MAX_SOCK_BUFFER);
printf("recved from client1,%d\n",ret);
if (ret<=0)
{
perror("recieve error from browser:");
close(newfd);
sin_size = sizeof (their_addr);
printf("mapping server: going to accept connections...\n");
newfd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
ret=recv_all_nonblock(newfd,buff,MAX_SOCK_BUFFER);
printf("recved from client10,%d\n",ret);
if (ret<=0)
{
perror("recieve error from browser:");
close(newfd);
sin_size = sizeof (their_addr);
printf("mapping server: going to accept connections...\n");
newfd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
}
else if(ret>0)
{
printf("recved from client0\n");
printf("%s\n",buff);
if (sendall(sockfdweb,buff,&bufpoint)<0)
{
printf("can not send data to %s\n","192.168.1.10");
}
printf("send to 80,0\n");
}
}
else if(ret>0)
{
printf("recved from client\n");
printf("%s\n",buff);
if (sendall(sockfdweb,buff,&bufpoint)<0)
{
printf("can not send data to %s\n","192.168.1.10");
}
printf("send to 80\n");
}
memset(buff2,0,sizeof(buff2));
ret=recv_all_nonblock(sockfdweb,buff2,MAX_SOCK_BUFFER);
printf("recv from 80...%d\n",ret);
if (ret<=0)
{
close(sockfdweb);
sockfdweb=Connect_To_Remote("192.168.1.10","80");
if (sockfdweb<0)
{
printf("can not connect to %s\n","192.168.1.10");
break;
}
ret=recv_all_nonblock(sockfdweb,buff2,MAX_SOCK_BUFFER);
printf("recv from 80.9..%d\n",ret);
if (ret<=0)
{
close(sockfdweb);
sockfdweb=Connect_To_Remote("192.168.1.10","80");
if (sockfdweb<0)
{
printf("can not connect to %s\n","192.168.1.10");
break;
}
}
else if (ret>0)
{
printf("recved from 809\n");
if (sendall(newfd,buff2,&ret)<0)
{
printf("can not send data to %s\n","192.168.1.10");
}
printf("send to client9\n");
}
}
else if (ret>0)
{
printf("recved from 80\n");
if (sendall(newfd,buff2,&ret)<0)
{
printf("can not send data to %s\n","192.168.1.10");
}
printf("send to client\n");
}
}
}
return 0;
}
int main()
{
.
.
.
.
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&portmapper_threadid,&attr,Port_Mapper,NULL);
pthread_attr_destroy (&attr);
.
.
.
.
}
我的推杆在Port_Mapper功能有一定的「printf」,並做了一些改動,以跟蹤,當我在我的瀏覽器請求的web這樣會發生什麼:
,並把瀏覽器的清爽兩個三次節目出來是這樣的:
映射服務器:連接接受:5
客戶端:連接到192.168.1.10
從client1,360
recved從客戶recved
GET/1/HTTP/1.1
主機:127.0.0.1:8090
用戶代理:Mozilla/5.0(X11; Linux i686; rv:6.0.2)Gecko/20100101 Firefox/6.0.2
Accept:text/html,application/xhtml + xml,application/xml; q = 0.9,/; q = 0.8
Accept-Language:en -us,連接; q = 0.5
接受編碼:gzip,放氣
接收字符集:ISO-8859-1,utf-8; q = 0.7,*; q = 0.7
連接:保活
緩存控制:最大年齡= 0發送到80
的recv:資源暫時不可
的recv從80 ...- 1
客戶端:連接到192.168.1.10
的recv:資源暫時不可
從80.9 ..- 1個
客戶端的recv:連接到192.168.1.10
的recv:資源暫時不可
從recved客戶端1,-1
從瀏覽器收到錯誤::資源暫時不可用
映射服務器:要接受連接...
從client10,360
從client0
recved recvedGET/1/HTTP/1.1
Host:127.0.0.1:8090
User-Agent:Mozilla/5.0(X11; Linux i686; rv:6.0.2)Gecko/20100101 Firefox/6.0.2
Accept:text/html,application/xhtml + xml,application/xml; q = 0.9,/; q = 0.8
Accept-Language:en -us,en; q = 0.5
Accept-Encoding:gzip,deflate
Accept-Charset:ISO-8859-1,utf-8; q = 0.7,*; q = 0。7
連接:保持活躍
緩存控制:最大年齡= 0發送到80,0
的recv:資源暫時不可用80
的recv ... 0
客戶端:連接到192.168.1.10
的recv:資源暫時不可從80.9 ..- 1
客戶
的recv:連接到192.168.1.10
的recv:資源暫時不可用
從客戶端1 recved,-1
從瀏覽器收到錯誤::資源暫時不可用
映射服務器:要接受連接...
的recv:從資源暫時不可用
從client10 recved,-1
收到錯誤瀏覽器::資源暫時不可用
映射服務器:要接受連接...
的recv:資源暫時不可用80
的recv ... 0
客戶端:連接到192.168.1.10
的recv:從80.9 ..- 1
客戶資源暫時不可
的recv:連接到192.168.1.10
從client1,332
recved從客戶recved
GET/HTTP/1.1
主機:127.0.0.1 :8090
User-Agent:Mozilla/5.0(X11; Linux i686; RV:6.0.2)壁虎/ 20100101火狐/ 6.0.2
接受:text/html的,應用/ XHTML + xml的,應用/ XML; Q = 0.9,/; Q = 0.8
接受語言:EN -us,連接; q = 0.5
接受編碼:gzip,放氣
接收字符集:ISO-8859-1,utf-8; q = 0.7,*; q = 0.7
連接:保活發送到80
的recv:資源暫時不可
的recv從80 ...- 1
客戶端:連接爲192.168.1.10
的recv:資源暫時不可
從80.9 ..- 1個
客戶端的recv:連接到192.168.1.10
的recv:資源暫時不可
從客戶端1 recved,-1
從瀏覽器收到錯誤::資源暫時不可用
映射服務器:正在接受連接...
,你可以看到程序從瀏覽器正確地接收數據,但是當它發送到web服務器的數據,並希望接收來自Web服務器的數據總是得到錯誤,並且沒有收到來自Web服務器的任何數據:
發送到80
的recv:資源暫時不可用
的recv從80 ...- 1
我不得不說,網絡服務器工作正常 沒問題。
任何機構可以告訴我什麼是我的問題?
你能縮短你的代碼嗎?這是通過瀏覽很多方法。見http://sscce.org/ – 2012-04-04 11:17:40