使用TCP通过套接字进行二进制文件传输 [英] Binary file transfer over Socket using TCP

查看:82
本文介绍了使用TCP通过套接字进行二进制文件传输的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个二进制文件传输程序,其中客户端必须将文件上传到服务器.对于这种情况,我需要先发送文件名,然后再发送文件内容.但这对我来说是不可行的.

I am working on a binary file transfer program in which the client has to upload a file to server. For this case, I need to send the file name first and file content second. But this is not feasible for me.

让我们看看代码:

// Client-side code to send file name
void sendFileName(
    int sd,         /*Socket Descriptor*/
    char *fname)    /*Array Containing the file name */
{       
    int n , byteswritten=0 , written ;
    char buffer[1024];
    strcpy(buffer , fname);
    n=strlen(buffer);
    while (byteswritten<n)
    {
        written=write(sd , buffer+byteswritten,(n-byteswritten));
        byteswritten+=written;
    }
    printf("File name : %s sent to server \n",buffer);
}

在这段代码中,我正在通过套接字&写入文件名.服务器将从套接字读取名称,如下所示:

In this code, I am writing the file name over socket & server will read the name from socket which is as follows:

// Server-side code to read file name from client
while ((n = read((int)connfd, (fname + pointer), 1024)) > 0)
{
    pointer=pointer+n;
}

好吧,问题是我必须在发送文件名后关闭客户端的写端,该文件名将是服务器端代码的FIN段以停止从服务器读取.

Well, the problem is I have to close the write end in the client-side after sending the filename which will be a FIN segment for server-side code to stop reading from the server.

如果我像这样关闭读取端:

If I close the read end like:

shutdown(sd,SHUT_WR);       //Closing write end at client side

我如何通过套接字将文件内容写入(即发送)到服务器,以便可以从套接字读取文件内容?

How can I write (i.e. send) the file content via socket to server so that it can read from socket?

注意:我所做的是在客户端添加文件名和文件内容,并在内容中添加一个特殊字符(目的是通知文件名的结尾),然后是文件内容.

Note: What I did was to append the file name with the file content from the client side, and adding a special character to the content (for the purpose of notifying end of file name) and then the file content.

在客户端,

void readWriteFile(
   int sd,                      /*Socket Descriptor */
   int fd,                      /*File Descriptot */
   char *fname)                 /*File Name  */
{
   char buffer[1050];
   int n;
   int len = 0;
   char *tmp = (char *)malloc(sizeof (char) * (strlen(fname) + 2));
   strcpy(tmp, fname);          //Copying the file name with tmp 
   strcat(tmp, "/");            //Appending '/' to tmp
   len = strlen(tmp);
   memset(buffer, '\0', sizeof (buffer));
   strcpy(buffer, tmp);         //Now copying the tmp value to buffer

   while ((n = read(fd, buffer + len, 1024)) > 0)
   {
      if (write(sd, buffer, n) != n)
      {
         printf("File write Error \n");
         exit(0);
      }
      len = 0;
   }
   printf("File sent successfully \n");
}

在服务器端,

   char fname[50], buffer[1024];
   int n, fd;
   int i;
   int start = 0;

   while ((n = read((int)connfd, buffer, 1024)) > 0) // Reading from socket
   {
      if (!start)
      {
          /* This 'if' loop will executed almost once i.e. until 
             getting the file name */
         for (i = 0; i < 1024; i++)
         {
            /* Since '/' is the termination character for file name */
            if (buffer[i] == '/')
            {
               start = 1;       // Got the file name
               break;
            }

            fname[i] = buffer[i]; //Storing the file name in fname
         }

         fname[i] = '\0';

         /* Creating the file in the server side */
         fd = open(fname, O_WRONLY | O_CREAT, S_IRWXU);

         if (fd < 0)
         {
            perror("File error");
            exit(0);
         }

         /* Here writing the buffer content to the file after 
            the (buffer+i+1), because after this address only, we 
            can get the original file content */

         write(fd, buffer + i + 1, n);
      }
      else
      {
         write(fd, buffer, n);
      }
   }
   printf("%s received successful \n", fname);

此代码适用于图片,可执行文件和文本文件.但是,如果我发送任何音频文件,则不会在服务器端播放.大小保持不变.但是我想知道为什么音频文件会发生这种情况.逻辑上有什么问题吗?我还没有尝试视频文件.

This code works fine for image, executable & text files. But if I send any audio file, it's not playing in the server side. The size remains the size. But I am wondering why this happens to audio files. Is there anything wrong in the logic? I didn't try out video files yet.

推荐答案

为什么说发送文件名后,我必须在客户端关闭写端"?您还没有完成数据发送,因此确定您还不想关闭套接字吗?

Why do you say "I have to close the write end in the client side after sending the filename"? You are not finished sending your data so surely you do not want to close the socket yet?

首先确定如何构造数据,以便接收方可以读取数据并重建原始文件名和文件内容.有关如何构造它的一些示例:

First decide how you want to structure your data so that the receiver can read it and reconstruct the original filename and file contents. Some examples of how you might want to structure it:

  • 发送文件名,以NUL字节结尾,然后发送内容.
  • 以网络字节顺序(大字节序)发送两个32位整数,分别包含文件名的长度和文件内容的长度.然后发送文件名,然后发送文件内容.
  • 将文件名和文件内容序列化为结构化的文档格式,例如JSON或XML.发送序列化的版本.(对于您的用例而言,可能会适得其反.)

在发送完整个结构后,无论您决定了什么,都请关闭套接字.

Close the socket after you've sent the entire structure, whatever you've decided it is.

采用这些配置中的任何一种,接收方都具有清楚地重建原始文件名和内容所需的所有信息.

With any one of these arrangements, the receiver has all the information it needs to unambiguously reconstruct the original file name and contents.

更新:您在问题中添加了更多内容,这几乎是一个不同的问题...

UPDATE: You added a lot more to your question, it's almost a different question...

您的服务器端代码(读取文件名和文件内容的代码)包含许多错误.

Your server side code (the one that reads the file name and file contents) contains many bugs.

  • 您假定文件名将在第一个缓冲数据中完全交付.如果耗尽该缓冲区而没有找到文件名终止符,则代码的处处都是(打开一个错误的文件,写一些垃圾,当读取下一个缓冲区时,它会从头开始再次寻找文件名.).
  • 即使没有可用的 n 个字节,也要从第一个缓冲数据中将 n 个字节写入输出文件.其实有 n 减去,但是文件名使用了很多.
  • 您不会对 read() write()进行任何错误检查,但是为了清楚起见,我将假设您忽略了这一点..
  • 您不会检查另一端提供的文件名是否超过了50个字节的缓冲区.
  • You assume that the filename will be completely delivered in the first bufferful of data. If you exhaust that buffer without finding the filename terminator, your code kind of goes all over the place (it opens an incorrect file, it writes some garbage, it goes back to looking for the filename again from the start when the next bufferful is read).
  • You write n bytes from the first bufferful of data to the output file, even though there are not n bytes available. Actually there are n minus however many were used by the filename.
  • You don't do any error checking on read() and write() but I'm going to assume you omitted that for clarity of the question...
  • You don't check whether the filename supplied by the other end exceeds your buffer of 50 bytes.

在其他大小的代码中,存在明显的缓冲区溢出,在该缓冲区中,您将1024个字节读入只有 1024-len 个字节的缓冲区.

In the code from the other size, there is a glaring buffer overflow where you read 1024 bytes into a buffer that only has 1024 - len bytes available.

您需要先修复所有这些问题,然后才能期待一切正常.

You need to fix all of this before you can expect anything to work.

这篇关于使用TCP通过套接字进行二进制文件传输的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆