C#通过Socket进行网络传输文件

转贴:

如果想要利用C#通过Socket进行网络传输文件,一般情况下,大家会首先考虑使用.NET自带的 Socket.SendFile Method (String)这个方法。不过这个方法没有相应的文件接受方法,而且据说会有8KB的限制。所以,我尝试了另外一种方法,发现效果不错。下面,我就来简 单介绍一下其原理。
  Socket.Send()和Socket.Receive()方法都是传递byte[]的,所以就要想办法把文件给变成 byte[]。一开始试过用StreamReader来读取string,然后用Encoding来进行编码得到byte[],接收以后再还原成 string写入文件。结果发现不可行,只有纯文本文件以这种方法传输是正常的。
  无奈之下,只好另想办法。后来在File类下找到了这两个方 法——File.ReadAllBytes()和File.WriteAllBytes()。试了一下用这两个方法来把文件变成byte[],再把 byte[]还原成文件,结果成功了!(试过了传输图片和rar压缩文件,都OK!)

C# code
/************************************************** 
* Class Name:  MyRenFramework.NetWork.SynchronousSocket
* Description: The socket does socket communication
*              in the Synchronous way.
*              It is better used as a server socket.
* Create By:  Steven Mo
* Version:    2008-01
**************************************************/
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace MyRenFramework.NetWork
{
    /// <summary>
    /// SynchronousSocket
    /// </summary>
    public class SynchronousSocket
    {
        private const int BUFFER_SIZE = 65536;
        private const int CONNECTED_WAITTIME = 50;

        private const string END_OF_STRING = "$EOS$";
        private const int LISTEN_BACKLOG = 100;
        private IPEndPoint _localEndPoint;
        private IPAddress _localIpAddress;
        private IPEndPoint _remoteEndPoint;
        public delegate void AcceptedFileSavedEventHandler(string fileName);

        public delegate void SocketConnectedEventHandler(Socket connectedSocket);

        public delegate void StringReceivedEventHandler(Socket connectedSocket, string receivedData);
        public delegate void StringSentEventHandler(Socket connectedSocket, int sentBytes);
        public event SocketConnectedEventHandler SocketConnected;
        public event StringReceivedEventHandler StringReceived;
        public event StringSentEventHandler StringSent;
        public event AcceptedFileSavedEventHandler AcceptedFileSaved;

        public SynchronousSocket()
        {
            _localIpAddress = IP.GetLocalIP();
        }
        public void StartListening(int localPort)
        {
            try
            {
                _localEndPoint = new IPEndPoint(_localIpAddress, localPort);

                // Create a TCP/IP listener.
                Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                listener.Bind(_localEndPoint);
                listener.Listen(LISTEN_BACKLOG);

                while (true)
                {
                    Socket connectedSocket = listener.Accept();

                    // Wait for the connection to be stabilized.
                    Thread.Sleep(CONNECTED_WAITTIME);

                    // Call the SocketConnected event.
                    SocketConnected(connectedSocket);
                }
            }
            catch
            {
                return;
            }
        }
        public void StartConnecting(string remoteHostNameOrAddress, int remotePort)
        {
            try
            {
                IPAddress ipAddress = IP.GetRemoteIpAddress(remoteHostNameOrAddress);
                _remoteEndPoint = new IPEndPoint(ipAddress, remotePort);

                // Create a TCP/IP client.
                Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // Connect to the remote endpoint.
                client.Connect(_remoteEndPoint);

                // Wait for the connection to be stabilized.
                Thread.Sleep(CONNECTED_WAITTIME);

                // Call the SocketConnected event.
                SocketConnected(client);
            }
            catch
            {
                return;
            }
        }

        private int SendBytes(Socket connectedSocket, byte[] bytes)
        {
            int bytesSent = 0;
            while (bytesSent < bytes.Length)
            {
                int size;
                if (bytes.Length - bytesSent >= BUFFER_SIZE)
                {
                    size = BUFFER_SIZE;
                }
                else
                {
                    size = bytes.Length - bytesSent;
                }
                bytesSent += connectedSocket.Send(bytes, bytesSent, size, SocketFlags.None);
                Thread.Sleep(10);
            }
            Thread.Sleep(1000);
            return bytesSent;
        }
        public void SendData(Socket connectedSocket, String data)
        {
            try
            {
                // Convert the string data to byte data using Unicode encoding.
                byte[] byteData = Encoding.Unicode.GetBytes(data + END_OF_STRING);

                // Begin sending the data to the remote device.
                int bytesSent = SendBytes(connectedSocket, byteData);

                // Call the StringSent event.
                StringSent(connectedSocket, bytesSent - END_OF_STRING.Length);
            }
            catch
            {
                return;
            }
        }
        public void TransmitFile(Socket connectedSocket, string fileName)
        {
            try
            {
                byte[] fileData = File.ReadAllBytes(fileName);
                int fileSize = fileData.Length;
                byte[] byteSize = Encoding.Unicode.GetBytes(fileSize + END_OF_STRING);

                // Send the size of the byte array.
                connectedSocket.Send(byteSize, 0, byteSize.Length, SocketFlags.None);

                // Send the data of the file.
                SendBytes(connectedSocket, fileData);
            }
            catch
            {
                return;
            }
        }
        public void AcceptFile(Socket connectedSocket, string fileName)
        {
            try
            {
                byte[] bytes = new Byte[BUFFER_SIZE];
                byte[] fileData;
                int fileSize;
                int receivedBytes = 0;

                // Receive the size of the byte array.
                while (true)
                {
                    String receivedData = string.Empty;
                    int bytesRec = connectedSocket.Receive(bytes);
                    receivedData += Encoding.Unicode.GetString(bytes, 0, bytesRec);
                    if (receivedData.IndexOf(END_OF_STRING) > -1)
                    {
                        receivedData = receivedData.Replace(END_OF_STRING, string.Empty);
                        fileSize = Convert.ToInt32(receivedData);
                        fileData = new byte[fileSize];
                        break;
                    }
                }

                // Receive the data of the file.
                while (receivedBytes < fileSize)
                {
                    int bytesRec = connectedSocket.Receive(bytes);
                    if (bytesRec < BUFFER_SIZE)
                    {
                        for (int i = receivedBytes, j = 0; i < fileSize && j < bytesRec; i++, j++)
                        {
                            fileData[i] = bytes[j];
                        }
                    }
                    else
                    {
                        bytes.CopyTo(fileData, receivedBytes);
                    }
                    receivedBytes += bytesRec;
                }

                // Save file.
                File.WriteAllBytes(fileName, fileData);

                // Call the AcceptedFileSaved event.
                AcceptedFileSaved(fileName);
            }
            catch
            {
                return;
            }
        }
        public void ReceiveData(Socket connectedSocket)
        {
            try
            {
                String receivedData = string.Empty;
                byte[] bytes = new Byte[BUFFER_SIZE];

                while (true)
                {
                    int bytesRec = connectedSocket.Receive(bytes);
                    receivedData += Encoding.Unicode.GetString(bytes, 0, bytesRec);
                    if (receivedData.IndexOf(END_OF_STRING) > -1)
                    {
                        // Call the StringReceived event.
                        receivedData = receivedData.Replace(END_OF_STRING, string.Empty);
                        StringReceived(connectedSocket, receivedData);
                        break;
                    }
                }
            }
            catch
            {
                return;
            }
        }

        #endregion
    }
}
posted @ 2012-06-13 10:57  base  阅读(4653)  评论(0编辑  收藏  举报