gpt4 book ai didi

c - C语言套接字编程

转载 作者:太空宇宙 更新时间:2023-11-04 03:57:28 25 4
gpt4 key购买 nike

我正在尝试编写一个 Web 服务器,但使用我的代码时出现“打开失败”。应该在浏览器中打开的 html 文档 (ht.html)。

我的代码是:

#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define SERVER_PORT 12345
#define BUF_SIZE 4096
#define QUEUE_SIZE 10


int main(int argc, char *argv[])
{
int s, b, l, fd, sa, bytes, on = 1;
char buf[BUF_SIZE]; //buffer for outgoing file
struct hostent *h; //info about server
struct sockaddr_in channel; //holds IP address

//Build address structure to bind to socket
memset(&channel, 0, sizeof(channel)); //zero channel
channel.sin_family = AF_INET;
channel.sin_addr.s_addr = htonl(INADDR_ANY);
channel.sin_port = htons(SERVER_PORT);


//Passive open. Wait for connection
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /* create socket */
if (s < 0) fatal("socket failed");
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));


b = bind(s, (struct sockaddr *) &channel, sizeof(channel));
if (b < 0) fatal("bind failed");

l = listen(s, QUEUE_SIZE); /* specify queue size */
if (l < 0) fatal("listen failed");


/* Socket is now set up and bound. Wait for connection and process it. */
while(1) {
sa = accept(s, 0, 0); /* block for connection request */
if (sa < 0) fatal("accept failed");

read(sa, buf, BUF_SIZE); /* read file name from socket */

/* Get and return the file. */

fd = open(buf, O_RDONLY); /* open the file to be sent back */
if (fd < 0) fatal("open failed");

while(1){
bytes = read(fd, buf, BUF_SIZE); /* read from file */
if (bytes <= 0) break; /* check for end of file */
write(sa, buf, bytes); /*write bytes to socket*/
}

close(fd); //close file
close(sa); //close connection

}
}

fatal(char*string)
{
printf("%s", string);
exit(1);
}

我的错误在哪里?或者必须添加什么?

最佳答案

也许你可以从输出从套接字接收到的数据开始,或者至少在调试器中运行,否则一切都将在黑暗中运行,而你不知道发生了什么。在下面的代码中,我添加了 printf 来打印我们从网络浏览器获得的内容。

也像其他人指出的那样,很高兴知道 errno 试图告诉我们什么。使用perror + exit有点尴尬/烦人,所以在Linux和BSD中你可以使用err(3)warn(3) . err 将打印 errno 消息然后退出,而 warn 将只打印 errno 消息而不退出,我用这些替换了你的 fatal 函数。

Web 浏览器很可能会发送 GET/ht.html HTTP/1.1\r\n,这就是您尝试打开的内容。为了打开文件,我们需要提取 ht.html 部分。我已经在下面更新了您的代码,现在 strchr(3)strstr(3)用于提取ht.html

我们还需要发送 HTTP 响应代码并告诉 Web 浏览器我们要发送 HTML,这就是发送 HTTP/1.1 200 OK 的原因。请记住,所有 HTTP header 都需要用 \r\n(回车符 - 换行符)分隔。您将在 RFC 2616 中找到有关 HTTP 协议(protocol)的更多信息。 .

#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>

#define SERVER_PORT 12345
#define BUF_SIZE 4096
#define QUEUE_SIZE 10

int main(int argc, char *argv[])
{
int s, b, l, fd, sa, bytes, on = 1;
char buf[BUF_SIZE]; /* buffer for outgoing file */
char *p, *endp, *cp;

struct sockaddr_in channel; /* holds IP address */

/* Build address structure to bind to socket */
memset(&channel, 0, sizeof(channel)); /* zero channel */
channel.sin_family = AF_INET; /* ipv4 */
channel.sin_addr.s_addr = htonl(INADDR_ANY); /* 0.0.0.0 */
channel.sin_port = htons(SERVER_PORT);


/* Passive open. Wait for connection */
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /* create socket */
if (s < 0) err(1, "socket failed");
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

b = bind(s, (struct sockaddr *) &channel, sizeof(channel));
if (b < 0) err(1, "bind failed");

l = listen(s, QUEUE_SIZE); /* specify queue size */
if (l < 0) err(1, "listen failed");


/* Socket is now set up and bound. Wait for connection and process it. */
while(1) {
sa = accept(s, NULL, NULL); /* block for connection request */
if(sa < 0) {
warn("accept failed");
continue;
}

bytes = 0;
endp = buf + sizeof(buf); /* pointer to end of buf */
cp = NULL;
buf[0] = '\0';
/* read first line from socket */
/* should be "GET /[file] HTTP/1.1" */
for(p = buf; (bytes = read(sa, p, endp - p)) > 0; p += bytes) {
p[bytes] = '\0'; /* read(2) doesn't NUL terminate buf */
if((cp = strchr(p, '\r')) != NULL) /* break at first carriage return */
break;
}
printf("incoming request %lu bytes:\n%s\n", strlen(buf), buf);
/* no carrige return or no "GET /" was found */
if(cp == NULL || strstr(buf, "GET /") != buf) {
warnx("incomplete request");
close(sa);
continue;
}
*cp = '\0'; /* replace '\r' with '\0' */
p = buf + sizeof("GET /") - 1; /* point to after "GET /" */
cp = strchr(p, ' '); /* find " HTTP/1.1" */
if(cp == NULL) {
warnx("HTTP version was not found");
close(sa);
continue;
}
*cp = '\0'; /* replace ' ' with '\0' */


/* Get and return the file. */
fd = open(p, O_RDONLY); /* open the file to be sent back */
if(fd < 0) {
warn("open failed: %s", p);
close(fd);
close(sa);
continue;
}

/* Send HTTP header */
/* Should probably also send Content-Length: <sizeof file>, */
/* this can be checked using fstat(2) */
write(sa, "HTTP/1.1 200 OK\r\n" \
"Content-Type: text/html;charset=UTF-8\r\n\r\n", 58);
while(1) {
bytes = read(fd, buf, sizeof(buf)); /* read from file */
if (bytes <= 0) break; /* check for end of file */
write(sa, buf, bytes); /*write bytes to socket*/
}

close(fd); /* close file */
close(sa); /* close connection */
}
return 0;
}

要从 Web 浏览器连接到 HTTP 服务器,请转到:http://127.0.0.1:12345/ht.html

关于c - C语言套接字编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15044068/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com