【问题标题】:Transmitting file between C++ Client / C# Server over TCP通过 TCP 在 C++ 客户端/C# 服务器之间传输文件
【发布时间】:2017-08-29 13:16:46
【问题描述】:

我目前正在尝试通过 TCP 在 c++ 客户端和 C# 服务器之间发送 jpeg 图片流。 我在 C++ 端使用了 transmitFile 函数,但我不知道我是否在 C# 端正确处理它。 我没有收到运行时错误,但没有显示图片,所以我想我遗漏了一些东西。

编辑:更新代码,我收到的 fileSize 正在执行 stackOverflow...

C++代码(客户端:发送图片)

void TCPclient::sendPicture(LPCWSTR filename, std::string filename_str)
{
    HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
    //Send file size
    send(sock, (const char*)GetSize(filename_str), sizeof(int), 0);
    LogManager::log(std::to_string(GetSize(filename_str)));
    //Send file
    TransmitFile(sock, hFile, GetFileSize(hFile, NULL), 1024, NULL, NULL, TF_USE_KERNEL_APC | TF_WRITE_BEHIND);
    CloseHandle(hFile);
}

int TCPclient::GetSize(std::string filename)
{
    struct stat stat_buf;
    int rc = stat(filename.c_str(), &stat_buf);
    return rc == 0 ? stat_buf.st_size : -1;
}

C#代码(服务器:接收图片并显示)

 while (true)
        {
            try
            {
                using (MemoryStream stream = new MemoryStream(ReceiveVarData(clientSock)))
                {
                    stream.Position = 0;
                    Image image = Image.FromStream(stream);
                    if (image != null)
                        pictureBox1.Image = image;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

    public static byte[] ReceiveVarData(Socket s)
    {
        Console.WriteLine("Receiving data ...");
        int offset = 0;
        int recv;
        Console.WriteLine("Receiving data size ...");
        byte[] datasize = new byte[4];
        s.Receive(datasize);
        int size = BitConverter.ToInt32(datasize, 0);
        Console.WriteLine("Data size " + size);
        byte[] data = new byte[size];
        while (offset < size)
        {
            Console.WriteLine("Downloading " + (offset/size)*100.0 + "%");
            recv = s.Receive(data, offset, 1024, SocketFlags.None);
            if (recv == 0)
            {
                data = null;
                break;
            }
            offset += recv;
        }
        return data;
    }

【问题讨论】:

  • 您读取了文件大小,但我没有看到您将文件大小发送到哪里?

标签: c# c++ sockets tcp winsock2


【解决方案1】:

改变:

using (Image image = Image.FromStream(new MemoryStream(ReceiveVarData(clientSock))))
{
    if (image != null)
        pictureBox1.Image = image;
}

到这里:

using ( MemoryStream stream = new MemoryStream(ReceiveVarData(clientSock)) )
{
    stream.Position = 0;
    Image image = Image.FromStream(stream);
    if ( image != null )
        pictureBox1.Image = image;
}

您将在创建 Image 对象后立即处理它。
当使用数据缓冲区(据我记得)实例化 MemoryStream 时,会将其位置设置为该流的末尾,因此您必须将 MemoryStream.Position 设置回开头。

【讨论】:

  • 释放 MemoryStream 是一个非常讨厌的错误。不幸的是,它不会经常导致异常。
  • 我已经更新了代码,尝试在 c# 端读取文件大小时遇到​​ stackoverflow 错误......
  • @Germain67 在不发送文件大小的情况下尝试相同的操作。据我记得TransmitFile 首先发送文件大小,然后发送文件内容。这可能是错误的,但值得一试。
猜你喜欢
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多