我正在写一个网络服务器的准系统,但我无法弄清楚为什么我的文件不能通过我的套接字发送,我连接到它和它的一切只是没有send()
我的档案......我错过了什么?
//代码(server.c)
#include<netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
int main(void) {
int create_socket, new_socket;
socklen_t addrlen;
int bufsize = 1024;
char *buffer = malloc(bufsize);
struct sockaddr_in address;
if ((create_socket = socket(AF_INET, SOCK_STREAM, 0)) > 0){
printf("The socket was created\n");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(80);
if (bind(create_socket, (struct sockaddr *) &address, sizeof(address)) == 0){
printf("Binding Socket\n");
}
long fsize;
FILE *fp = fopen("index.html", "r");
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
rewind(fp);
char *msg = malloc(fsize + 1);
fread(msg, sizeof(msg), 1, fp);
while (1) {
if (listen(create_socket, 10) < 0) {
perror("server: listen");
exit(1);
}
if ((new_socket = accept(create_socket, (struct sockaddr *) &address, &addrlen)) < 0) {
perror("server: accept");
exit(1);
}
if (new_socket > 0){
printf("The Client is connected...\n");
}
recv(new_socket, buffer, bufsize, 0);
printf("%s\n", buffer);
write(new_socket, "HTTP/1.1 200 OK\n", 16);
write(new_socket, "Content-length: 46\n", 19);
write(new_socket, "Content-Type: text/html\n\n", 25);
/* write(new_socket, "<html><body><H1>Hello world</H1></body></html>",46); */
if((send(new_socket, msg, fsize+1, 0)) > 0){
printf("success");
}
else{
printf("failed");
}
close(new_socket);
}
close(create_socket);
return 0;
}
// FILE (index.html)*同一目录
<html>
<body>
<h1>Hello World</h1>
</body>
</html>
答案 0 :(得分:6)
由于十几种不同的原因,代码完全已损坏。尝试更像这样的东西:
remote: Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
remote: Fetching gem metadata from https://rubygems.org/...........
remote: Fetching version metadata from https://rubygems.org/...
remote: Fetching dependency metadata from https://rubygems.org/..
remote: Could not find net-ssh-2.10.0 in any of the sources
remote: Bundler Output: Fetching gem metadata from https://rubygems.org/...........
remote: Fetching version metadata from https://rubygems.org/...
remote: Fetching dependency metadata from https://rubygems.org/..
remote: Could not find net-ssh-2.10.0 in any of the sources
remote: !
remote: ! Failed to install gems via Bundler.
答案 1 :(得分:1)
fsize = ftell(fp);
rewind(fp);
char *filebuff = malloc(fsize + 1);
为什么fsize+1
?您不需要+1
。
fread(filebuff, sizeof(filebuff), 1, fp);
未选中的返回值。第二个参数应为fsize
。目前你只传递sizeof
指针。
//create/bind socket
if ((create_socket = socket(AF_INET, SOCK_STREAM, 0)) > 0)
{
printf("The socket was created\n");
}
如果套接字创建失败,您必须(a)打印正确的错误消息,如下所述和(b) 不 继续执行,就好像错误没有'发生了。
if (bind(create_socket, (struct sockaddr *) &address, sizeof(address)) == 0)
{
printf("Binding Socket\n");
}
同上。
//listen, create new_sock, write headers, send file
while (1){
if (listen(create_socket, 10) < 0) {
perror("server: listen");
exit(1);
}
listen()
调用应该在循环之前,而不是在循环内部。这是您第一次真正处理失败案例。
new_sock = accept(sock, (struct sockaddr *) &address, &addrlen);
recv(new_socket, buffer, bufsize, 0);
printf("%s\n", buffer);
无效。未选中的返回代码。缓冲区仅在recv()
返回正整数时才有效,并且只有那么多字节有效。它应该是:
int count = recv(new_socket, buffer, bufsize, 0);
printf("%.*s\n", count, buffer);
然后我们从HTTP开始:
write(new_sock, "HTTP/1.1 200 OK\n", 16);
write(new_sock, "Content-length: 46\n", 19);
write(new_sock, "Content-Type: text/html\n\n", 25);
HTTP中的行终止符是从Telnet继承的,它被指定为\r\n
,而不是\n
。
if(send(new_sock, filebuff, fsize+1, 0) > 0){
printf("success");
}
else{
printf("failed");
}
不足。如果您在任何系统调用中收到错误消息,则必须在错误消息中调用perror()
或使用errno
或strerror()
。 “失败”没有传达有用的信息,调试变成了猜测游戏。不要写这样的代码。您应该使用perror()
或您决定的所有其他未经检查的返回值。
但是有一个更大的问题。你假设文件适合内存。没有必要这样的假设。只需使用8k缓冲区复制文件,如下所示:
int count;
while ((count = read(in, buffer, sizeof buffer)) > 0)
{
send(out, buffer, count, 0);
}
if (count < 0)
{
perror("send failed");
}
我会为此避免stdio
,它有太多问题,例如设计不佳的fread()
和fwrite()
函数API。
答案 2 :(得分:0)
除了在各个地方使用的错误大小(如数学家1975所述),你的“真实”问题是你试图与需要HTTP服务器的浏览器进行通信。
H yper T 分机 T 转发 P rotocol,嗯,a protocol。它比简单连接和内容转储更复杂。
您必须根据它解析请求,并以某种方式发送标题和内容。
答案 3 :(得分:0)
检查addrlen
是否失败并报告是否失败。你绑定到端口80;在类Unix操作系统下,只有root可以绑定到保留端口(小于1024)。
更新1:
在致电sizeof(address)
之前,您必须先将accept()
初始化为{{1}}。来自http://linux.die.net/man/2/accept:
addrlen参数是一个value-result参数:调用者必须 初始化它以包含指向的结构的大小(以字节为单位) 通过addr;返回时它将包含对等体的实际大小 地址。