在C:代理HTTP请求到另一台服务器

时间:2016-03-03 03:50:37

标签: c sockets http networking

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

第一步是对server_proxy_hostname进行DNS查找。

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

上一步:等待两个套接字上的新数据。当数据到达时,我立即将其读入缓冲区,然后将其写入另一个缓冲区 插座。这维持了HTTP客户端和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;
      }
    }

  }

}

1 个答案:

答案 0 :(得分: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()返回-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()将其记录下来,然后再调用任何其他系统呼叫。