我正在尝试了解HTTP代理服务器程序。我写了一个简单的基于C的套接字,它发送一个响应收到消息。请在下面找到该计划。
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/types.h>
int main(){
int recvSocketFd = 0;
struct sockaddr_in serv_input_addr;
char inputBuff[1024];
memset(&serv_input_addr,'0',sizeof(serv_input_addr));
memset(&inputBuff, '0', sizeof(inputBuff));
recvSocketFd = socket(AF_INET,SOCK_STREAM,0);
if(recvSocketFd <= 0){
printf("\nError occurred while creating a socket\n");
return -1;
}
serv_input_addr.sin_family = AF_INET;
serv_input_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_input_addr.sin_port = htons(8080);
bind(recvSocketFd, (struct sockaddr*)&serv_input_addr, sizeof(serv_input_addr));
listen(recvSocketFd,5);
int connFd = 0;
int n = 0;
int client_length = sizeof(serv_input_addr);
while(1){
connFd = accept(recvSocketFd, (struct sockaddr*)&serv_input_addr, &client_length);
if(connFd <0){
printf("\nError in accepting messages from socket\n");
return -1;
}
n = read(connFd,inputBuff,1023);
if(n>0){
printf("\nMessage : %s\n",inputBuff);
}
write(connFd,"Message received",15);
close(connFd);
}
}
此正在运行的程序正在针对以下请求http://<localhost>:8080/test
正确响应。
我尝试将其设置为代理。所以我尝试在Firefox中将其设置为手动代理http://<localhost>
,并将端口设置为8080。
但请求没有达到此套接字。
如果有人可以帮助我理解这一点,那将会非常有帮助。
注意:这不是家庭作业,我不是学生。我只是想学习东西。本声明适用于我们光荣的可耻受访者。
答案 0 :(得分:2)
重新编辑:
请注意在 bind()上检查成功的重要性。有各种各样的情况;其中一个可能是套接字处于TIME_WAIT状态。如果一个人实际上没有验证 bind()并且在失败时中止,程序可能看起来正在运行OK。 listen()可以无错误地传递。虽然在客户端,Firefox很可能会报告拒绝连接但它不是给定的。
在您的问题中,您声明已使用http://<localhost>
进行代理设置。如果这是文字,它将失败:您不要在代理设置中包含方案名称。
请注意,Firefox不会验证主机名。例如。 a4a6®←@ł´ªĸµª5d4a"#¤&%=)(=/)=
飞过,没有任何警告。
如果其中包含http://
方案,则Firefox将无法连接,并且会找到 服务器 。
原始答案: - )
我会把它留在这里,即使对删除的部分发表评论,因为其他人可能会觉得它很有用。 (而且我用了一些时间来写它。)
这里有一些问题。我会一个接一个地拿它们。
首先修复此问题,然后根据需要进行报告。
read(),write()和close()在&lt; unistd.h&gt; 中定义,但您不包含此文件。它可能与之相关,但最好添加。
client_length
未签署int。您可以使用unsigned int,但最好使用手册中定义的 socklen_t 。
read()返回 ssize_t ,而非int。也改变这个。
没有错误检查它应该在哪里。规则#1:始终检查错误!遇到麻烦而没有验证请求是......一个很大的不行。
bind(),listen()和close()返回int。 0表示成功,-1表示错误。出错 errno 已设置。
本手册非常清晰易读。为您使用的每个功能阅读它。
包括&lt; errno.h&gt; 并使用perror()。
以最简单的方式。我们得到了堕胎而没有企图拯救:
int res;
...
res = bind(recvSocketFd, (struct sockaddr*)&serv_input_addr, sizeof(serv_input_addr));
if (res != 0) {
perror("bind");
return errno;
}
res = listen(recvSocketFd, 5);
if (res != 0) {
perror("listen");
return errno;
}
...
res = close(connFd);
if (res != 0) {
perror("close");
return errno;
}
write()返回 ssize_t ,成功时写入了多少字节,其他-1和 errno 设置得恰当。
res_wr = write(connFd, ...);
if (res == -1) {
perror("write");
return errno;
}
/* Else check if entire buffer was written, if not, act accordingly. */
Bad 写语句:
write(connFd, "Message received", 15);
首先:“收到消息”是17个字节,包括终止空值。如果要将此写入连接,请使用以下内容:
const char msg_received[] = "Message received";
...
write(connFd, msg_received, sizeof(msg_received));
第二:这是你传递给客户端的东西,在你的情况下是Firefox。换句话说,Firefox会获得字符:
{ 'M', 'e', 's', 's', 'a', 'g', 'e', ' ', 'r', 'e', 'c', 'e', 'i', 'v', 'e' }
第三:在第一次读/写后立即执行 close()。 Firefox很可能会回复 连接已重置 。通常你会写你的 inputBuff ,而不是像这样的一些状态信息。
stderr
作为一方不是:虽然在此示例中写入stdout
足够公平,但将错误和调试数据写入stderr
是一个好习惯。保持习惯。例如:
sz_buf = read(connFd, inputBuff, BUF_SIZE - 1)
inputBuff[sz_buf] = 0x00;
fprintf(stderr,
"\n====================== Message (%4d) ================\n"
"%s\n"
"--------------------------------------------------------\n"
,
sz_buf, inputBuff
);