我试图将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;
}
}
}
}
答案 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()
,将其记录下来,然后再调用任何其他系统呼叫。