开发者

Sending a image file using a socket in C# (Large Data)

i want to send a large data (image) approx . 1MB file though a socket connection

Question 1

following code snippet of the socket client which i currently use to send a a text message .. how i can modify this to send a file ?

 NetworkStream serverStream = clientSocket.GetStream();
开发者_如何学运维    byte[] outStream = System.Text.Encoding.ASCII.GetBytes(richTextBox1.Text+"$");
    serverStream.Write(outStream, 0, outStream.Length);
    serverStream.Flush();

Question 2 : What modifications that required in both socket client and server to send and get large files ?


For large data portions you will probably need some kind of transmitting by portions. In your snippet you get all of the data in the array which couldn't be possible if file is large enough (or at least not suitable if it is not just one file to send).

Sending side will be something like that:

const int bufsize = 8192;

var buffer = new byte[bufsize];
NetworkStream ns = socket.GetStream();

using (var s = File.OpenRead("path"))
{
    int actuallyRead;
    while ((actuallyRead = s.Read(buffer, 0, bufsize)) > 0)
    {
        ns.Write(buffer, 0, actuallyRead);
    }
}
ns.Flush();

Receiving site is just symmetric.


A socket doesn't care if you send text or binary data. Or how much you send. If there's any trouble then it is at the receiving end, code you didn't post. A classic mistake is to forget that a NetworkStream is a stream and not a sequence of packets. The Read() call at the receiving end can return any number of bytes. It won't be the number of bytes you wrote in the Write() call, depending on how routers in between the two machines broke up the IP packets and how much data is buffered in the receiver. You are probably getting away with calling Read only once because the string is short. That is definitely not going to work when you send a lot of data.

You need a protocol to help the receiver figure out when it received all the data. A simple way to do this is by first sending the length of the data. The receiver can then first read that length, then know how long to keep calling Read() to get the rest of the data.

You can arbitrarily extend this protocol by, say, sending the name of the file. Etcetera. Although that by the time you're done, you'd be close to having re-invented FTP.


If all you want to do is to send an image and you don't need any metadata, you can use code like this:

Server:

var listener = new TcpListener(address, port);
listener.Start();

using (var incoming = listener.AcceptTcpClient())
using (var networkStream = incoming.GetStream())
using (var fileStream = File.OpenWrite(imagePath))
{
    networkStream.CopyTo(fileStream);
}

listener.Stop();

Client:

var client = new TcpClient();
client.Connect(address, port);

using (var networkStream = client.GetStream())
using (var fileStream = File.OpenRead(imagePath))
{
    fileStream.CopyTo(networkStream);
}

client.Close();

If you want to compress the file, you can use GZipStream.

This code uses CopyTo() method, which is available in .Net 4, but you can write it yourself in earlier versions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜