我正在尝试将HTTP请求代理到另一个HTTP服务器。上游HTTP服务器的主机名和端口号分别是server_proxy_hostname和server_proxy_port。

第一步是对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;
      }
    }

  }

}

最佳答案

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);


去掉。这是不好的做法。套接字几乎总是可以编写的,因此,除非您以前遇到套接字尚未准备好写的情况,即writeSetwrite()返回-1的情况,否则不应该使用errno == EAGAIN/EWOULDBLOCK.

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


那应该是

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


在两种插座情况下。

并且应该先进行readStat == 0(表示流结束)和readStat == -1(表示错误)的测试,然后进行跟踪。

您尚未设置此代码,因此无法在此代码中获得超时。

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

当您从任何系统调用中遇到任何错误时,必须立即调用perror()或将其记录为结果strerror(),然后再调用其他系统调用。

关于c - 在C中:代理HTTP请求到另一台服务器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35762852/

10-12 14:56
查看更多