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

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

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

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

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

如果任何一个sockets关闭 ,我关闭另一个sockets


现在的问题是它无法正常工作。 (它超时)

我相信我获取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); 

去掉。 这是不好的做法。 套接字几乎总是可以写入,所以你不应该使用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()然后再调用任何其他系统调用。