Germain67
Germain67

Reputation: 718

Transmitting file between C++ Client / C# Server over TCP

I'm currently trying to send a stream of jpeg pictures between a c++ client and a C# server over TCP. I'm using the transmitFile function on C++ side but I don't know if I'm handling it properly on C#-side. I don't get runtime errors but the picture is not displayed, so I guess I'm missing something.

EDIT : Updated code, the fileSize I'm receiving is doing a stackOverflow...

C++ code (Client : sending picture)

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# code (Server : receiving the picture and displaying it)

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

Upvotes: 1

Views: 871

Answers (1)

mrogal.ski
mrogal.ski

Reputation: 5940

Change :

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

To this :

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

You're disposing your Image object right after creating it.
When instantiating MemoryStream with data buffer ( from what i remember ) will set it's position to the end of that stream so you have to set MemoryStream.Position back to the beginning.

Upvotes: 2

Related Questions