网络编程-在C语言中使用套接字从客户端发送文件到服务器



程序应该将文件的内容从客户端发送到服务器端的输出文件。但是,我的代码只适用于少数文件,而不适用于大多数文件。例如,如果我试图将一个名为morefood.txt的文件的内容复制到一个名为picolo.txt的输出文件,则不会复制任何内容。

服务器代码:

#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 createdn");
  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;
}
客户机代码:

#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;
   }

问题是传输和接收回路都有漏洞!我已经以一种代码运行得更好的方式修改了它们,但我认为要有一个可靠的代码还有很多需要修改的地方!

客户:

#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;
}
服务器:

#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 createdn");
    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: %dn",tot);
            if (b<0)
               perror("Receiving");
            fclose(fp);
        } else {
            perror("File");
        }
        close(confd);
    }
    return 0;
}

此代码,在客户端:

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);
}

不是发送"无名"文件的好方法。

我建议

while( 0< (byteCount = fread( sendbuffer, sizeof(sendbuffer), 1, fp) ) )
{
    send(sfd, sendbuffer, byteCount, 0);
}
然而,对于鲁棒性,

--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'记录是。

当然,所有send/recv/open/connect/bind/etc系统函数调用都需要检查返回值是否有错误

从服务器文件中读取的部分

    .
    .  // Your other code
    .
    read(client, rbuff, sizeof(rbuff); //Getting file name from client
    printf("File wanted by client%sn", 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

客户端部分:

   /* 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 filen");
        exit;
    }
    write(filedesc, buff, fsize);
    close(filedesc);
    close(confd);

相关内容

最新更新