我正在尝试将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);
去掉。这是不好的做法。套接字几乎总是可以编写的,因此,除非您以前遇到套接字尚未准备好写的情况,即
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()
,然后再调用其他系统调用。关于c - 在C中:代理HTTP请求到另一台服务器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35762852/