通过TCP socket发送二进制文件

本文关键字:二进制文件 socket TCP 通过 | 更新日期: 2023-09-27 18:10:48

我做了一个客户端&通过套接字建立TCP连接的服务器,我试图通过套接字发送二进制数据,但我只能发送txt或pdf文件,我没有运气与exe文件,我使用read和fseek读取文件并将其拆分为缓冲区。当我读取整个exe文件时,它会成功发送,但当我分割它时,它会被损坏!

我读了一些关于socket的书,但我仍然不太了解,我有一些问题。

是可以发送整个文件在一个send()??还是我应该继续把它分成小块发送?

另外,为什么exe文件损坏时,我发送它们块?

谢谢!

客户端代码(c中):

int bufSize = 10000;
int sentBytes = 0;

  FILE * pFile;
  long remainingBytes;
  char * buffer;
  size_t result;
  pFile = fopen ( "D:''file.exe" , "rb" );
  fseek (pFile , 0 , SEEK_END);
  remainingBytes = ftell (pFile);
  rewind (pFile);
int bufferSize = remainingBytes > bufSize ? bufSize : remainingBytes;
buffer = (char*) malloc (sizeof(char)*bufferSize);
send(Socket, (char*)&remainingBytes, 4, 0);
while(remainingBytes > 0)
{
    fseek (pFile , sentBytes , SEEK_SET);
    result = fread(buffer,1,bufferSize,pFile);
    if(bufferSize < remainingBytes)
    {
        send(Socket, buffer, bufferSize, 0);
    }
    else
    {
        send(Socket, buffer, remainingBytes, 0);
        bufferSize = remainingBytes;
    }
    remainingBytes -= bufferSize;
    sentBytes += bufferSize;
}

服务端代码(c#)

        try
        {
            int bufferSize = 200;
            int len = 0;
            int receivedBytes = 0;
            int remainingBytes = len;
            byte[] length = new byte[4];
            //byte[] imgBuf = new byte[bufferSize];
            int current = 0;
            List<byte[]> coming = new List<byte[]>();
            sockets[number].Receive(length,4,0);
            len = BitConverter.ToInt32(length, 0);
            remainingBytes = len;
            bufferSize = len < bufferSize ? len : bufferSize;
            while(receivedBytes < len)
            {
                if (remainingBytes > bufferSize)
                {
                    coming.Add(new byte[bufferSize]);
                    //imgBuf = new byte[bufferSize];
                    sockets[number].Receive(coming[current], bufferSize, 0);
                }
                else
                {
                    coming.Add(new byte[remainingBytes]);
                    //imgBuf = new byte[remainingBytes];
                    sockets[number].Receive(coming[current], remainingBytes, 0);
                    bufferSize = remainingBytes;
                }
                remainingBytes -= bufferSize;
                receivedBytes += bufferSize;
                current++;
                //Array.Clear(imgBuf, 0, imgBuf.Length);
            }
            using (var stream = new FileStream(@"C:'receivedFile.exe",FileMode.Create))
            {
                using (var binaryWriter = new BinaryWriter(stream))
                {
                    foreach (byte[] buffer in coming)
                    {
                        binaryWriter.Write(buffer);
                    }
                }
            }
        }
        catch (Exception ex)
        { this.setText(ex.Message, textBox2); }

编辑:谢谢你的帮助,我把它工作了:)

        try
        {
            int bufferSize = 1024 * 100;
            int len = 0;
            int receivedBytes = 0;
            int remainingBytes = len;
            int reached = 0;
            byte[] length = new byte[4];
            byte[] imgBuf = new byte[bufferSize];
            int current = 0;
            sockets[number].Receive(length,4,0);
            len = BitConverter.ToInt32(length, 0);
            remainingBytes = len;
            bufferSize = len < bufferSize ? len : bufferSize;
            imgBuf = new byte[len];
            while (reached < len)
            {
                reached += sockets[number].Receive(imgBuf, receivedBytes, remainingBytes, 0);
                remainingBytes = len - reached;
                receivedBytes = reached;
                current++;
                //Array.Clear(imgBuf, 0, imgBuf.Length);
            }
            using (var stream = new FileStream(@"C:'putty.exe",FileMode.Create))
            {
                using (var binaryWriter = new BinaryWriter(stream))
                {
                        binaryWriter.Write(imgBuf);
                }
            }
            Array.Clear(imgBuf, 0, imgBuf.Length);
        }
        catch (Exception ex)
        { this.setText(ex.Message, textBox2); }

通过TCP socket发送二进制文件

您不检查在sockets[number].Receive(coming[current], bufferSize, 0);中实际接收了多少字节。它不必等于您声明的缓冲区大小。此外,正如在注释中所说,将整个文件保存在内存中并不是一个好主意。

除了检查接收的字节数,您还需要检查每个发送调用发送的字节数——如果您的TCP传输窗口填满,发送调用可能发送的数据少于您请求的数据,在这种情况下,您将需要重新发送未发送的数据。

一般来说,您总是需要检查系统调用的返回值,以检查可能发生的各种奇怪的极端情况。请阅读send(2)和recv(2)的手册页,以获取可能发生的所有事情的完整列表。