c - 创建自己的 Web 服务器时无法连接到 localhost
问题描述
我已经创建了 Web 服务器,并且我想对其进行测试。我在浏览器(Chrome,我也使用 macbook pro)中输入了https://localhost:8080/test.html 。浏览器显示 ERR_CONNECTION_REFUSED。
如果有人可以帮助我解释和解决这种情况,那将非常有帮助。我试过在 linux 和 macOS 环境下运行这个程序,它们都不起作用。我已经在网上搜索了很多类似的解决方案,但是没有一个可以解决我的问题。感谢你们。
我的代码在这里:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> // just added
#include <netdb.h>//Network address and service translation
#include <arpa/inet.h> //For message type convertion
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <signal.h>
#include <errno.h>
#define BUFFSIZE 2048
// port number
int port_num = 8080;
void handle(int fd) {
printf("handle function.\n");
char buff[BUFFSIZE + 1];
int bytes_read = read(fd, buff, BUFFSIZE);
printf("bytes_read: %d\n", bytes_read);
if (bytes_read <= 0) {
fprintf(stderr, "connection failed, or read failed.\n");
}
printf("Msg: %s\n", buff);
exit(1);
}
int main(int argc, char* argv[]){
// make sure get the port num
/*
if (argc != 2) {
fprintf(stderr, "Error: Improper number of arguments used\n");
exit(1);
}else {
port_num = atoi(argv[1]);
}
*/
// setup socket
struct sockaddr_in server_address, client_address;
socklen_t client_address_length = sizeof(client_address);
// socket file descriptor
int fd_server, fd_client;
char buf[BUFFSIZE];
int on = 1;
fd_server = socket(AF_INET, SOCK_STREAM, 0);
if (fd_server < 0) {
fprintf(stderr, "Error: socket set up failed.\n");
exit(1);
}
// I don't know what is this
setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port_num);
server_address.sin_addr.s_addr = INADDR_ANY;
// binding
if (bind(fd_server, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {
fprintf(stderr, "Error: binding failed.\n");
exit(1);
}
// listen
if (listen(fd_server, 10) == -1) {
fprintf(stderr, "Error: socket listen failed.\n");
exit(1);
}
while (1) {
// accept
fd_client = accept(fd_server, (struct sockaddr *)&client_address, &client_address_length);
if (fd_client == -1) {
fprintf(stderr, "Error: accept failed.\n");
continue;
}
printf("connected...\n");
int pid = fork();
if (!fork()) {
// child process
close(fd_server);
memset(buf, 0, 2048);
read(fd_client, buf, 2047);
printf("%s\n", buf);
close(fd_client);
printf("closing...\n");
exit(0);
}
close(fd_client);
}
return 0;
}
在我点击 url ( https://localhost:8080/test.html ) 后,它会打印
解决方案
两件事情:
- 首先,您
fork()
在主循环中调用了两次,因此您为每个连接创建了两个子进程,同时您必须检查给定的值并存储在pid
变量中。 - 其次,您不知道为什么要调用
setsockopts
以重用套接字提供的地址……您是对的。在这里没用……我已经评论过了。
通过进行以下更改,我进行了第一次尝试:
// I don't know what is this
- setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));
+ // setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)); // indeed, you had better not to use it.
和
printf("connected...\n");
int pid = fork();
- if (!fork()) {
+ if (!pid) { // check for the value of pid, not call fork() again.
// child process
close(fd_server);
在此之后,我得到这个输出:
[s000]lcu@Luiss-MacBook-Pro:~/so/59935716$ pru
connected...
connected...
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: es,en;q=0.9
Cookie: tocTree_ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1Text-hi=tocTree:ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1:ref-jdbcconnectionpoolnew1_link; tocTree-hi=tocTree:ref-topic-group:ref-group-configuration:ref-group-connectionservice; JSESSIONID=2d890f14dcdd285f478653a16a62; treeForm_tree-hi=treeForm:tree:resources:JDBC:connectionPoolResources
closing...
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: es,en;q=0.9
Cookie: tocTree_ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1Text-hi=tocTree:ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1:ref-jdbcconnectionpoolnew1_link; tocTree-hi=tocTree:ref-topic-group:ref-group-configuration:ref-group-connectionservice; JSESSIONID=2d890f14dcdd285f478653a16a62; treeForm_tree-hi=treeForm:tree:resources:JDBC:connectionPoolResources
closing...
connected...
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: es,en;q=0.9
Cookie: tocTree_ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1Text-hi=tocTree:ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1:ref-jdbcconnectionpoolnew1_link; tocTree-hi=tocTree:ref-topic-group:ref-group-configuration:ref-group-connectionservice; JSESSIONID=2d890f14dcdd285f478653a16a62; treeForm_tree-hi=treeForm:tree:resources:JDBC:connectionPoolResources
closing...
(如您所见,谷歌浏览器尝试对服务器进行三次连接尝试)
经过一些修改后,我对您的代码进行了以下更改,导致了这一点:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> // just added
#include <netdb.h>//Network address and service translation
#include <arpa/inet.h> //For message type convertion
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <signal.h>
#include <errno.h>
#define BUFFSIZE 2048
// port number
int port_num = 8080;
void handle(int fd) {
printf("handle function.\n");
char buff[BUFFSIZE + 1];
int bytes_read = read(fd, buff, BUFFSIZE);
printf("bytes_read: %d\n", bytes_read);
if (bytes_read <= 0) {
fprintf(stderr, "connection failed, or read failed.\n");
}
printf("Msg: %s\n", buff);
exit(1);
}
int main(int argc, char* argv[]){
// make sure get the port num
/*
if (argc != 2) {
fprintf(stderr, "Error: Improper number of arguments used\n");
exit(1);
}else {
port_num = atoi(argv[1]);
}
*/
// setup socket
struct sockaddr_in server_address, client_address;
socklen_t client_address_length = sizeof(client_address);
// socket file descriptor
int fd_server, fd_client;
char buf[BUFFSIZE];
int on = 1;
fd_server = socket(AF_INET, SOCK_STREAM, 0);
if (fd_server < 0) {
fprintf(stderr, "Error: socket set up failed.\n");
exit(1);
}
// I don't know what is this
// setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)); // indeed, you had better not to use it.
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port_num);
server_address.sin_addr.s_addr = INADDR_ANY;
// binding
if (bind(fd_server, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {
fprintf(stderr, "Error: binding failed.\n");
exit(1);
}
// listen
if (listen(fd_server, 10) == -1) {
fprintf(stderr, "Error: socket listen failed.\n");
exit(1);
}
// accept
while ((fd_client = accept(fd_server, (struct sockaddr *)&client_address, &client_address_length)) >= 0) {
printf("connected...\n"); // do this only in the child process. Or flush stdout before forking...
fflush(stdout); // so you get only one message (you flush the buffer before forking)
int pid = fork();
if (pid == 0) { // check for the value of pid, not call fork() again.
// child process
close(fd_server); // good.
memset(buf, 0, 2048);
ssize_t n = read(fd_client, buf, sizeof buf);
if (n > 0) {
write(1, buf, n); // better not consider it a null terminated string.
}
close(fd_client);
printf("closing...\n");
exit(EXIT_SUCCESS);
}
close(fd_client); // good.
}
fprintf(stderr, "Error: accept failed.\n");
exit(EXIT_FAILURE);
}
我没有检查这个handle()
函数,因为它没有在主代码中使用。
您将从此处获得此代码的不同版本。
推荐阅读
- flutter - 初始化initstate时如何聚焦文本字段
- python - 无法为使用 PEP 517 且无法直接安装的密码学构建轮子
- git - 如何在我签出到上一个提交后推送,然后我做了一些提交,现在当我推送时,没有发送更改
- git - Visual Studio 版本控制 UI 中的图标覆盖(彩色圆圈)是什么意思?
- python - 在Django中提交多页表单后清除会话数据
- reactjs - 如果字段不为空,Graphql Hasura 更新
- intellij-idea - IntelliJ 不显示生成选项
- angular - 从 ionic 4 中的服务调用页面的功能
- php - 如何在 Laravel 中获取字符串中的所有列值
- python-3.x - 为什么变量(第 6 行)有一个白色的空格?(Nivel: 初级工作流程符石)