简体   繁体   English

使用C中的套接字将文件从客户端发送到服务器

[英]Sending files from client to server using sockets in C

The program is supposed to send the contents of a file from the client side to an output file on the server side.该程序应该将文件的内容从客户端发送到服务器端的输出文件。 However, my code is working for few files and not working for most of the files.但是,我的代码适用于少数文件,不适用于大多数文件。 For example if I try to copy content of a file called morefood.txt to an output file say picolo.txt , nothing is copied.例如,如果我尝试将名为morefood.txt的文件的内容复制到输出文件picolo.txt ,则不会复制任何内容。

Server code:服务器代码:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>

int main(int argc, char *argv[]){

  int fd =0, confd = 0;
  struct sockaddr_in serv_addr;

  char buff[1025];
  int num;

  fd = socket(AF_INET, SOCK_STREAM, 0);
  printf("Socket created\n");

  memset(&serv_addr, '0', sizeof(serv_addr));
  memset(buff, '0', sizeof(buff));

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port = htons(5000);

  bind(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
  listen(fd, 10);

  FILE* fp = fopen( "picolo.txt", "wb");

  if(fp == NULL){
      fprintf(stderr, "something went south");
      return 1;
  }

  while(1){

      confd = accept(fd, (struct sockaddr*)NULL, NULL);

      char recvbuff[10];

      int b = recv(confd, recvbuff, 10, 0);

      while(b>0)
     {
          fwrite(recvbuff, 1, b, fp);

          b = recv(confd, recvbuff, 10, 0);

     }
   close(confd);
  }

return 0;

}

Client code:客户端代码:

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


int main(int argc, char *argv[]){

    int sfd =0, n=0;
    char rbuff[1024];

    struct sockaddr_in serv_addr;

    memset(rbuff, '0', sizeof(rbuff));
    sfd = socket(AF_INET, SOCK_STREAM, 0);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000);
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    FILE *fp = fopen("morefood.txt", "rb");

    if(fp == NULL){
        fprintf(stderr, "oh no!");
        return 1;
    }

    char sendbuffer[100];

    int b = fread(sendbuffer, 1, sizeof(sendbuffer), fp);

    while(!feof(fp)){
        send(sfd, sendbuffer, b, 0);
        b = fread(sendbuffer, sizeof(sendbuffer), 1, fp);
    }

    return 0;

   }

The issue is that both transmission and reception loop are bugged!问题是传输和接收循环都被窃听了! I've modified them in a way that the codes run better, but I think there's a lot to modify to have a solid code!我已经以一种使代码运行得更好的方式修改了它们,但我认为有很多需要修改才能获得可靠的代码!

Client:客户:

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

int main(int argc, char *argv[]){

    int sfd =0, n=0, b;
    char rbuff[1024];
    char sendbuffer[100];

    struct sockaddr_in serv_addr;

    memset(rbuff, '0', sizeof(rbuff));
    sfd = socket(AF_INET, SOCK_STREAM, 0);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000);
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    b=connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if (b==-1) {
        perror("Connect");
        return 1;
    }

    FILE *fp = fopen("prova.jpg", "rb");
    if(fp == NULL){
        perror("File");
        return 2;
    }

    while( (b = fread(sendbuffer, 1, sizeof(sendbuffer), fp))>0 ){
        send(sfd, sendbuffer, b, 0);
    }

    fclose(fp);
    return 0;

}

Server:服务器:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>

int main(int argc, char *argv[]){

    int fd =0, confd = 0,b,tot;
    struct sockaddr_in serv_addr;

    char buff[1025];
    int num;

    fd = socket(AF_INET, SOCK_STREAM, 0);
    printf("Socket created\n");

    memset(&serv_addr, '0', sizeof(serv_addr));
    memset(buff, '0', sizeof(buff));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(5000);

    bind(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    listen(fd, 10);

    while(1){
        confd = accept(fd, (struct sockaddr*)NULL, NULL);
        if (confd==-1) {
            perror("Accept");
            continue;
        }
        FILE* fp = fopen( "provacopy.jpg", "wb");
        tot=0;
        if(fp != NULL){
            while( (b = recv(confd, buff, 1024,0))> 0 ) {
                tot+=b;
                fwrite(buff, 1, b, fp);
            }

            printf("Received byte: %d\n",tot);
            if (b<0)
               perror("Receiving");

            fclose(fp);
        } else {
            perror("File");
        }
        close(confd);
    }

    return 0;
}

this code, in the client:这段代码,在客户端:

char sendbuffer[100];

int b = fread(sendbuffer, 1, sizeof(sendbuffer), fp);

while(!feof(fp)){
    send(sfd, sendbuffer, b, 0);
    b = fread(sendbuffer, sizeof(sendbuffer), 1, fp);
}

is not a good way to send a 'nameless' file.不是发送“无名”文件的好方法。

I suggest我建议

while( 0< (byteCount = fread( sendbuffer, sizeof(sendbuffer), 1, fp) ) )
{
    send(sfd, sendbuffer, byteCount, 0);
}

however, for robustness然而,为了稳健

--client send a file name and total file size with recordNum 0
--server when receiving recordNum 0
  open the appropriate file name
  if successful open, send 'ack', maxRecordSize echo recordNum
  else send 'nak' echo recordNum
--client, on following records, 
  send byteCount, recordNum, data
--server respond with 'ack' for each received record
  when it is expected recordNum
  otherwise respond with 'nak' expected recordNum
--when client receives 'ack' send next record
--when client receives 'nak' resend prior record
--client, after all file sent, send file checksum with recordnum -1
--server, when receive recordNum -1 compares checksum, closes file
  responds with final 'ack' if checksum matches
  responds with final 'nak' if checksum does not match

This 'lockstep' communication, which is often used in the real world, will assure both ends of the communication know what is going on and will assure a successful file transfer,这种在现实世界中经常使用的“锁步”通信将确保通信的两端都知道发生了什么,并确保文件传输成功,

This works for only one file being sent at a time.这仅适用于一次发送一个文件。 for multiple files being sent at the same time, the records will need another field, that indicates which file 'this' record is part of.对于同时发送的多个文件,记录将需要另一个字段,指示“此”记录属于哪个文件。

of course, all send/recv/open/connect/bind/ etc system function calls need to have the returned value(s) checked for errors当然,所有的 send/recv/open/connect/bind/etc 系统函数调用都需要检查返回值是否有错误

Part to read from file in server从服务器中的文件读取的部分

    .
    .  // Your other code
    .
    read(client, rbuff, sizeof(rbuff); //Getting file name from client
    printf("File wanted by client%s\n", textToRec);
    int filedesc = open(textToRec, O_RDONLY); //Opening the file
    struct stat sb;  //To get the size of file

    if (lstat(ruff, &sb) == -1) {
        exit(EXIT_FAILURE);
    }
    long long fsize;
    fsize = sb.st_size;
    if ((0 == filedesc)) {
        fprintf(stderr,"error in reading file");
        exit(-1);
    }
    write(client, fsize, sizeof(fsize)); //Sending Filesize
    read(filedesc, sendbuffer, fsize);  //Putting file in buffer
    write(client, sendbuffer, sizeof(sendbuffer));  //Sending buffer to client
    
    close(socketid);
    .
    .
    .  // Your code

Part on the client side:客户端部分:

   /* your code above */
    printf("file name sent...Now wait!\n");
// I am assuming you put filename in buff
    read(sock, buff,sizeof(buff)); //Receiving file size
    long long fsize = strtol(buff,NULL,10);
    read(sock, buff,sizeof(buff)); 
    /*It's better to use sizeof instead of actual number as you can change the size of buffer anytime without needing to change values everywhere */
    int filedesc;
    filedesc =
        open(textToSend, O_WRONLY | O_APPEND | O_CREAT, 0644);
    if (!filedesc) {
        printf("failed to create file\n");
        exit;
    }
    write(filedesc, buff, fsize);
    close(filedesc);
    close(confd);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM