我正在c中构建一个http代理。 代理应该过滤URL和html内容中的一些关键字。 我遇到的第一个问题是send()函数。当我第一次加载页面时,一切都很好,花花公子。如果我让页面加载,下一个请求也没关系。但是,如果我打开www.google.com并开始输入“即时功能”,则在最后一个请求完成之前发出新请求,我会收到以下错误:
Program received signal SIGPIPE, Broken pipe.
0x00007ffff7b2efc2 in send () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) up
#1 0x0000000000401f1a in main () at net-ninny2.c:232
232 bytes_sent += send(i, buffer+bytes_sent, buffer_size-bytes_sent, 0);
生成错误的代码块如下所示:
while(bytes_sent < buffer_size) {
bytes_sent += send(i, buffer+bytes_sent, buffer_size-bytes_sent, 0);
printf("* Bytes sent to Client: %d/%d\n", bytes_sent, buffer_size);
}
如果您认为相关,我会很乐意提供更多代码。
我的第二个问题与Http标头有关。由于我想在html内容中过滤关键字,我不希望对内容进行编码。 Google似乎并不同意这一点,无论我在Accept-Encoding -header中放置什么,我总是将内容重新编码为gzip。任何想法如何摆脱它?
编辑:
我也在尝试使用fork()为新连接创建子进程,但这只会引发一个令人讨厌的错误:
select: Interrupted system call
我把它放在从传入连接创建新文件描述符的地方:
if (i == listener) {
// New connection
remote_addr_len = sizeof remote_addr;
newfd = accept(listener, (struct sockaddr *)&remote_addr, &remote_addr_len);
if (newfd == -1) {
perror("accept");
}
else {
FD_SET(newfd, &master); // Add new connection to master set
if (newfd > fdmax) {
fdmax = newfd;
}
printf("* New connection from %s on "
"socket %d\n",
inet_ntop(remote_addr.ss_family,
get_in_addr((struct sockaddr*)&remote_addr),
remoteIP, INET6_ADDRSTRLEN), newfd);
if(!fork()) {
fprintf(stderr, "!fork()\n");
close(newfd);
exit(5);
}
}
}
但我猜我做错了。
干杯!
答案 0 :(得分:1)
对于第一个问题,您需要忽略SIGPIPE
信号:
signal(SIGPIPE, SIG_IGN);
有关详细信息,请参阅How to prevent SIGPIPEs (or handle them properly)。如果忽略该信号并重置套接字连接,您还需要适当地处理来自-1
的{{1}}错误返回值。
对于您的第二个问题,您可能无法强制Google发送未压缩的数据,因为Google可能会假设所有浏览器都可以处理压缩数据。您可能需要在代理中嵌入一个gzip解压缩程序。仅仅因为你想要过滤一些关键词而增加两个的带宽需求当然是不公平的。