天天看点

TCP文件传输

using System;  

using System.Net;  

using System.Net.Sockets;  

using System.IO;  

namespace Win  

{  

    /// <summary>  

    /// Net : 提供静态方法,对常用的网络操作进行封装  

    /// </summary>  

    public sealed class Net  

    {  

        private Net()  

        {  

        }  

        /// <summary>  

        /// 连接使用 tcp 协议的服务端  

        /// </summary>  

        /// <param name="ip">服务端的ip地址</param>  

        /// <param name="port">服务端的端口号</param>  

        /// <returns></returns>  

        public static Socket ConnectServer(string ip, int port)  

            Socket s = null;  

            try 

            {  

                IPAddress ipAddress = IPAddress.Parse(ip);  

                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);  

                s = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);  

                s.Connect(ipEndPoint);  

                if (s.Connected == false)  

                {  

                    s = null;  

                }  

            }  

            catch (Exception e)  

                Log.WriteLog(e);  

            return s;  

        /// 用主机名称连接使用Tcp协议的服务端  

        /// <param name="hostName">在hosts 文件中存在的主机名称</param>  

        public static Socket ConnectServByHostName(string hostName, int port)  

            IPHostEntry iphe = null;  

                iphe = Dns.Resolve(hostName);  

                foreach (IPAddress ipad in iphe.AddressList)  

                    IPEndPoint ipe = new IPEndPoint(ipad, port);  

                    Socket tmps = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);  

                    tmps.Connect(ipe);  

                    if (tmps.Connected)  

                    {  

                        s = tmps;  

                        break;  

                    }  

                    else 

                        continue;  

        /// 向远程主机发送数据  

        /// <param name="socket">要发送数据且已经连接到远程主机的 Socket</param>  

        /// <param name="buffer">待发送的数据</param>  

        /// <param name="outTime">发送数据的超时时间,以秒为单位,可以精确到微秒</param>  

        /// <returns>0:发送数据成功;-1:超时;-2:发送数据出现错误;-3:发送数据时出现异常</returns>  

        /// <remarks >  

        /// 当 outTime 指定为-1时,将一直等待直到有数据需要发送  

        /// </remarks>  

        public static int SendData(Socket socket, byte[] buffer, int outTime)  

            if (socket == null || socket.Connected == false)  

                throw new ArgumentException("参数socket 为null,或者未连接到远程计算机");  

            if (buffer == null || buffer.Length == 0)  

                throw new ArgumentException("参数buffer 为null ,或者长度为 0");  

            int flag = 0;  

                int left = buffer.Length;  

                int sndLen = 0;  

                while (true)  

                    if ((socket.Poll(outTime * 1000000, SelectMode.SelectWrite) == true))  

                    {        // 收集了足够多的传出数据后开始发送  

                        sndLen = socket.Send(buffer, sndLen, left, SocketFlags.None);  

                        left -= sndLen;  

                        if (left == 0)  

                        {                                        // 数据已经全部发送  

                            flag = 0;  

                            break;  

                        }  

                        else 

                        {  

                            if (sndLen > 0)  

                            {                                    // 数据部分已经被发送  

                                continue;  

                            }  

                            else 

                            {                                                // 发送数据发生错误  

                                flag = -2;  

                                break;  

                    {                                                        // 超时退出  

                        flag = -1;  

            catch (SocketException e)  

                flag = -3;  

            return flag;  

        /// <param name="buffer">待发送的字符串</param>  

        public static int SendData(Socket socket, string buffer, int outTime)  

                throw new ArgumentException("待发送的字符串长度不能为零.");  

            return (SendData(socket, System.Text.Encoding.Default.GetBytes(buffer), outTime));  

        /// 接收远程主机发送的数据  

        /// <param name="socket">要接收数据且已经连接到远程主机的 socket</param>  

        /// <param name="buffer">接收数据的缓冲区</param>  

        /// <param name="outTime">接收数据的超时时间,以秒为单位,可以精确到微秒</param>  

        /// <returns>0:接收数据成功;-1:超时;-2:接收数据出现错误;-3:接收数据时出现异常</returns>  

        /// 1、当 outTime 指定为-1时,将一直等待直到有数据需要接收;  

        /// 2、需要接收的数据的长度,由 buffer 的长度决定。  

        public static int RecvData(Socket socket, byte[] buffer, int outTime)  

            buffer.Initialize();  

            int left = buffer.Length;  

            int curRcv = 0;  

                    if (socket.Poll(outTime * 1000000, SelectMode.SelectRead))  

                    {        // 已经有数据等待接收  

                        curRcv = socket.Receive(buffer, curRcv, left, SocketFlags.None);  

                        left -= curRcv;  

                        {                                    // 数据已经全部接收   

                            if (curRcv > 0)  

                            {                                // 数据已经部分接收  

                            {                                            // 出现错误  

                    {                                                    // 超时退出  

        /// <param name="buffer">存储接收到的数据的字符串</param>  

        /// <param name="bufferLen">待接收的数据的长度</param>  

        /// 当 outTime 指定为-1时,将一直等待直到有数据需要接收;  

        public static int RecvData(Socket socket, string buffer, int bufferLen, int outTime)  

            if (bufferLen <= 0)  

                throw new ArgumentException("存储待接收数据的缓冲区长度必须大于0");  

            byte[] tmp = new byte[bufferLen];  

            if ((flag = RecvData(socket, tmp, outTime)) == 0)  

                buffer = System.Text.Encoding.Default.GetString(tmp);  

        /// 向远程主机发送文件  

        /// <param name="socket" >要发送数据且已经连接到远程主机的 socket</param>  

        /// <param name="fileName">待发送的文件名称</param>  

        /// <param name="maxBufferLength">文件发送时的缓冲区大小</param>  

        /// <param name="outTime">发送缓冲区中的数据的超时时间</param>  

        /// <returns>0:发送文件成功;-1:超时;-2:发送文件出现错误;-3:发送文件出现异常;-4:读取待发送文件发生错误</returns>  

        public static int SendFile(Socket socket, string fileName, int maxBufferLength, int outTime)  

            if (fileName == null || maxBufferLength <= 0)  

                throw new ArgumentException("待发送的文件名称为空或发送缓冲区的大小设置不正确.");  

                FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);  

                long fileLen = fs.Length;                        // 文件长度  

                long leftLen = fileLen;                            // 未读取部分  

                int readLen = 0;                                // 已读取部分  

                byte[] buffer = null;  

                if (fileLen <= maxBufferLength)  

                {            /* 文件可以一次读取*/ 

                    buffer = new byte[fileLen];  

                    readLen = fs.Read(buffer, 0, (int)fileLen);  

                    flag = SendData(socket, buffer, outTime);  

                else 

                {                                    /* 循环读取文件,并发送 */ 

                    buffer = new byte[maxBufferLength];  

                    while (leftLen != 0)  

                        readLen = fs.Read(buffer, 0, maxBufferLength);  

                        if ((flag = SendData(socket, buffer, outTime)) < 0)  

                        leftLen -= readLen;  

                fs.Close();  

            catch (IOException e)  

                flag = -4;  

        public static int SendFile(Socket socket, string fileName)  

            return SendFile(socket, fileName, 2048, 1);  

        /// 接收远程主机发送的文件  

        /// <param name="socket">待接收数据且已经连接到远程主机的 socket</param>  

        /// <param name="fileName">保存接收到的数据的文件名</param>  

        /// <param name="fileLength" >待接收的文件的长度</param>  

        /// <param name="maxBufferLength">接收文件时最大的缓冲区大小</param>  

        /// <param name="outTime">接受缓冲区数据的超时时间</param>  

        /// <returns>0:接收文件成功;-1:超时;-2:接收文件出现错误;-3:接收文件出现异常;-4:写入接收文件发生错误</returns>  

        /// 当 outTime 指定为-1时,将一直等待直到有数据需要接收  

        public static int RecvFile(Socket socket, string fileName, long fileLength, int maxBufferLength, int outTime)  

                throw new ArgumentException("保存接收数据的文件名称为空或发送缓冲区的大小设置不正确.");  

                FileStream fs = new FileStream(fileName, FileMode.Create);  

                if (fileLength <= maxBufferLength)  

                {                /* 一次读取所传送的文件 */ 

                    buffer = new byte[fileLength];  

                    if ((flag = RecvData(socket, buffer, outTime)) == 0)  

                        fs.Write(buffer, 0, (int)fileLength);  

                {                                        /* 循环读取网络数据,并写入文件 */ 

                    int rcvLen = maxBufferLength;  

                    long leftLen = fileLength;                        //剩下未写入的数据  

                    buffer = new byte[rcvLen];  

                        if ((flag = RecvData(socket, buffer, outTime)) < 0)  

                        fs.Write(buffer, 0, rcvLen);  

                        leftLen -= rcvLen;  

                        rcvLen = (maxBufferLength < leftLen) ? maxBufferLength : ((int)leftLen);  

        public static int RecvFile(Socket socket, string fileName, long fileLength)  

            return RecvFile(socket, fileName, fileLength, 2048, 1);  

    }  

}