2016-03-03 70 views
0

我试图代理HTTP请求到另一台HTTP服务器。上游HTTP服务器的主机名和端口号分别为server_proxy_hostname和server_proxy_port。在C:代理HTTP请求到另一台服务器

第一步将执行server_proxy_hostname的DNS查找。

其次,我创建一个网络套接字并将其连接到我从DNS获得的IP地址。

最后一步:等待两个插座上的新数据。当数据到达时,我立即将其读取到缓冲区,然后将其写入另一个 套接字。这保持HTTP客户端和上游HTTP服务器之间的双向通信。

如果任何插座关闭,我关闭另一个。


现在的问题是它不工作。 (它超时)

我相信我得到我的IP地址的方式是正确的,所以问题必须在我的while循环(它永远不会终止?)或我称为connect()的部分? 。我试着为read()和select()添加错误终止,但那也不起作用。

void handle_proxy_request(int fd) { 

    char * targetHostName = server_proxy_hostname; 
    int targetPort = server_proxy_port; 
    struct hostent *info; 
    info = gethostbyname(targetHostName); 
    struct in_addr ** ipAddresslist; 
    ipAddresslist = (struct in_addr **) (info -> h_addr_list); 
    struct in_addr * ipAddress = ipAddresslist[0]; 
    printf("ip address is %s\n", inet_ntoa(*ipAddress)); 

    /*ip for in_addr struct*/ 
    unsigned long ip = inet_addr(inet_ntoa(*ipAddress)); 
    struct in_addr addressIp = {ip}; 
    struct sockaddr_in address = {PF_INET, htons(targetPort), addressIp}; 

    int socket_num = socket(PF_INET, SOCK_STREAM, 0); 
    connect(socket_num, (struct sockaddr *)&address, sizeof(address)); 

    /*portion for select()*/ 
    char buf[10000]; 
    int nfds = (fd > socket_num)?fd:socket_num; 
    fd_set readSet; 
    fd_set writeSet; 

    while (1) { 

    FD_ZERO(&readSet); 
    FD_ZERO(&writeSet); 
    FD_SET(fd, &readSet); 
    FD_SET(socket_num, &readSet); 
    FD_SET(fd, &writeSet); 
    FD_SET(socket_num, &writeSet); 
    int selectReturn = select(nfds, &readSet, &writeSet, NULL, NULL); 
    if (selectReturn == -1){ 
     break; 
    } 
    if(FD_ISSET(fd, &readSet)){ 
     int readStat = read(fd, buf, sizeof(buf)); 
     int status = write(socket_num, buf, sizeof(buf)); 
     if (status == -1 || readStat == -1){ 
     close(socket_num); 
     close(fd); 
     break; 
     } 
     /*memset(buf, 0, sizeof(buf));*/ 
    } 
    if(FD_ISSET(socket_num, &readSet)){ 
     int readStat2 = read(socket_num, buf, sizeof(buf)); 
     int status2 = write(fd, buf, sizeof(buf)); 
     if (status2 == -1 || readStat2 == -1){ 
     close(socket_num); 
     close(fd); 
     break; 
     } 
    } 

    } 

} 
+0

如果你不知道具体哪个部分被挂起,我会建议添加更多的调试日志(或上面的代码样式中的'printf'),并尝试用调试器进行调试。为什么你认为IP地址代码是正确的?你确定'connect'实际上有连接吗?你有没有尝试telnet到地址和端口,以确保它响应连接? –

回答

1
int socket_num = socket(PF_INET, SOCK_STREAM, 0); 

未选中。检查这个错误。

connect(socket_num, (struct sockaddr *)&address, sizeof(address)); 

同上。

FD_SET(fd, &writeSet); 
FD_SET(socket_num, &writeSet); 

删除。这是不好的做法。套接字是几乎总是准备好写的,所以你不应该使用writeSet,除非你以前遇到过的情况下一个套接字还没有准备好写,即write()errno == EAGAIN/EWOULDBLOCK.

int readStat = read(fd, buf, sizeof(buf)); 
int status = write(socket_num, buf, sizeof(buf)); 

应该返回-1

int status = write(socket_num, buf, readStat); 

在这两种情况下,插座。

并且它应该是之前通过试验readStat == 0,表示流的末尾,和readStat == -1,指示错误,你应该跟踪。

在此代码不能得到超时,因为你没有设置任何。

有皱纹。如果读取一个套接字的流结束,则应关闭另一个套接字进行输出。如果您已经关闭了输出的套接字上的流结束,请关闭它们两者。这会在正确的时间在两个方向上正确传播FIN。

当您从任何系统呼叫时,您必须立即电话perror()与结果strerror()记录它调用任何其他系统调用之前得到任何错误。

+0

“这里有一个问题,如果你在读取一个套接字的流结束,你应该关闭另一个套接字输出,如果你的套接字已经关闭了,输出结束,关闭它们。两个方向在正确的时间。“你能详细解释一下吗?我现在确实正在通过对等方重置[Errno 104]连接。 –

+0

另外,你是什么意思“关闭”一个“输出套接字”?你的意思是“接近”吗? –

+0

谢谢。你说的一切都有帮助,而且是真的。当我改变第一个输入select(),nfds到FD_SETSIZE时,它现在可以工作。 –

相关问题