在TCP/IP套接字(Web服务器)上发送文件

14 浏览
0 Comments

在TCP/IP套接字(Web服务器)上发送文件

我在写一个Web服务器的框架,但是我弄不清楚为什么我的文件没有通过套接字发送,我已经连接到它了,但是它没有调用send()发送我的文件...我漏掉了什么吗?

//代码 (server.c)

#include<netinet/in.h>    
#include    
#include    
#include<sys/socket.h>    
#include<sys/stat.h>    
#include<sys/types.h>    
#include    
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, "

Hello world

 

",46); */
        if((send(new_socket, msg, fsize+1, 0)) > 0){
            printf("success");
        }     
        else{
            printf("failed");
        }
      close(new_socket);    
   }    
   close(create_socket);    
   return 0;    
}

//文件 (index.html) *同一个目录

Hello World

 


admin 更改状态以发布 2023年5月24日
0
0 Comments

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(),或者在错误消息中使用errnostrerror()。"失败"传达不了有用的信息,而调试成为了一个单纯的猜谜游戏。不要编写这样的代码。对于上面所有其他未检查的返回值,你应该使用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。

0
0 Comments

这段代码有很多不同的原因导致完全崩溃。建议改成以下代码:

#include     
#include     
#include     
#include     
#include     
#include     
#include     
bool writeDataToClient(int sckt, const void *data, int datalen)
{
    const char *pdata = (const char*) data;
    while (datalen > 0){
        int numSent = send(sckt, pdata, datalen, 0);
        if (numSent <= 0){
            if (numSent == 0){
                printf("The client was not written to: disconnected\n");
            } else {
                perror("The client was not written to");
            }
            return false;
        }
        pdata += numSent;
        datalen -= numSent;
    }
    return true;
}
bool writeStrToClient(int sckt, const char *str)
{
    return writeDataToClient(sckt, str, strlen(str));
}
int main(void){
    int create_socket, new_socket;    
    char *buffer;
    int bufsize = 1024;    
    struct sockaddr_in address;    
    socklen_t addrlen;    
    buffer = (char*) malloc(bufsize);    
    if (!buffer){
        printf("The receive buffer was not allocated\n");
        exit(1);    
    }
    create_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (create_socket == -1){    
        perror("The socket was not created");    
        exit(1);    
    }
    printf("The socket was created\n");
    memset(&address, 0, sizeof(address));    
    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)) == -1){    
        perror("The socket was not bound");    
        exit(1);    
    }
    printf("The socket is bound\n");    
    long fsize;
    FILE *fp = fopen("index.html", "rb");
    if (!fp){
        perror("The file was not opened");    
        exit(1);    
    }
    printf("The file was opened\n");
    if (fseek(fp, 0, SEEK_END) == -1){
        perror("The file was not seeked");
        exit(1);
    }
    fsize = ftell(fp);
    if (fsize == -1) {
        perror("The file size was not retrieved");
        exit(1);
    }
    rewind(fp);
    char *msg = (char*) malloc(fsize);
    if (!msg){
        perror("The file buffer was not allocated\n");
        exit(1);
    }
    if (fread(msg, fsize, 1, fp) != 1){
        perror("The file was not read\n");
        exit(1);
    }
    fclose(fp);
    printf("The file size is %ld\n", fsize);
    if (listen(create_socket, 10) == -1){
        perror("The socket was not opened for listening");    
        exit(1);    
    }    
    printf("The socket is listening\n");
    while (1) {    
        addrlen = sizeof(address);
        new_socket = accept(create_socket, (struct sockaddr *) &address, &addrlen);
        if (new_socket == -1) {    
            perror("A client was not accepted");    
            exit(1);    
        }    
        printf("A client is connected from %s:%hu...\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));    
        // I will leave it as an exercise for you to implement
        // a proper HTTP request parser here...
        int numRead = recv(new_socket, buffer, bufsize, 0);
        if (numRead < 1){
            if (numRead == 0){
                printf("The client was not read from: disconnected\n");
            } else {
                perror("The client was not read from");
            }
            close(new_socket);
            continue;
        }
        printf("%.*s\n", numRead, buffer);    
        if (!writeStrToClient(new_socket, "HTTP/1.1 200 OK\r\n")){
            close(new_socket);
            continue;
        }
        char clen[40];
        sprintf(clen, "Content-length: %ld\r\n", fsize);
        if (!writeStrToClient(new_socket, clen)){
            close(new_socket);
            continue;
        }
        if (!writeStrToClient(new_socket, "Content-Type: text/html\r\n")){
            close(new_socket);
            continue;
        }
        if (!writeStrToClient(new_socket, "Connection: close\r\n\r\n") == -1){
            close(new_socket);
            continue;
        }
        //if (!writeStrToClient(new_socket, "

Hello world

")){ if (!writeDataToClient(new_socket, msg, fsize)){ close(new_socket); continue; } printf("The file was sent successfully\n"); close(new_socket); } close(create_socket); return 0; }

0