使用C#进行点对点通讯和文件传输


最近一个项目要用到点对点文件传输,俺就到处找资料写程序,最后终于完成了,为了让别人少走些弯路,俺决定将俺程序中最重要的部分贡献出来,希望对大家有所帮助。
俺的程序分三部分,包括发送部分、接受部分和一个两者共享的通讯基类,这个基类才是俺心血的结晶:)
一、通讯基类

using System;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Windows.Forms;
using System.Text;
namespace BaseClass
{
    /// <summary>
    /// 传送信息的格式为 给定长度的命令部分+给定长度的命令注释部分+可变长度的长度信息+可变长度的信息部分
    /// </summary>
    public class CommunClass
    {
        public CommunClass()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
        }

        /// <summary>
        /// 命令部分的长度
        /// </summary>
        private static readonly int CMDLEN = 50;
        /// <summary>
        /// 命令注释部分的长度
        /// </summary>
        private static readonly int DESCLEN = 100;
        /// <summary>
        /// 可变长度的长度信息部分所占的字节数
        /// </summary>
        private static readonly int DYNAMICLENGTHLEN = 10;
        /// <summary>
        /// 每次处理可变信息部分的长度
        /// </summary>
        private static readonly int DEALLEN = 1024;
        /// <summary>
        /// /应答的最大长度
        /// </summary>
        private static readonly int RESPONLEN = 20;
        /// <summary>
        /// 用于填充命令或注释不足长度部分的字符
        /// </summary> 
        private static readonly char FILLCHAR = '^';
        /// <summary>
        /// 成功发送一部分数据后的回调方法(也可以认为是触发的事件,但严格来说还不是)
        /// </summary>
        public delegate void OnSend(int iTotal, int iSending);
        /// <summary>
        /// 根据给定的服务器和端口号建立连接
        /// </summary>
        /// <param name="strHost">服务器名</param>
        /// <param name="iPort">端口号</param>
        /// <returns></returns>
        public static Socket ConnectToServer(string strHost, int iPort)
        {
            try
            {
                IPAddress ipAddress = Dns.Resolve(strHost).AddressList[0];
                IPEndPoint ipPoint = new IPEndPoint(ipAddress, iPort);
                Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                s.Connect(ipPoint);
                return s;
            }
            catch (Exception e)
            {
                throw (new Exception("建立到服务器的连接出错" + e.Message));
            }
        }
        /// <summary>
        /// 将文本写到Socket中
        /// </summary>
        /// <param name="s">要发送信息的Socket</param>
        /// <param name="strInfo">要发送的信息</param>
        /// <returns>是否成功</returns>
        public static bool WriteTextToSocket(Socket s, string strInfo)
        {
            byte[] buf = Encoding.UTF8.GetBytes(strInfo);
            try
            {
                s.Send(buf, 0, buf.Length, SocketFlags.None);
                return true;
            }
            catch (Exception err)
            {
                MessageBox.Show("发送文本失败!" + err.Message);
                return false;
            }
        }
        /// <summary>
        /// 将命令文本写到Socket中
        /// </summary>
        /// <param name="s">要发送命令文本的Socket</param>
        /// <param name="strInfo">要发送的命令文本</param>
        /// <returns>是否成功</returns>
        public static bool WriteCommandToSocket(Socket s, string strCmd)
        {
            if (strCmd == "")
                strCmd = "NOP";
            strCmd = strCmd.PadRight(CMDLEN, FILLCHAR);
            return WriteTextToSocket(s, strCmd);
        }
        /// <summary>
        /// 将命令注释写到Socket中
        /// </summary>
        /// <param name="s">要发送命令注释的Socket</param>
        /// <param name="strInfo">要发送的命令注释</param>
        /// <returns>是否成功</returns>
        public static bool WriteCommandDescToSocket(Socket s, string strDesc)
        {
            if (strDesc == "")
                strDesc = "0";
            strDesc = strDesc.PadRight(DESCLEN, FILLCHAR);
            return WriteTextToSocket(s, strDesc);
        }
        /// <summary>
        /// 发送可变信息的字节数
        /// </summary>
        /// <param name="s">要发送字节数的Socket</param>
        /// <param name="iLen">字节数</param>
        /// <returns>是否成功</returns>
        public static bool WriteDynamicLenToSocket(Socket s, int iLen)
        {
            string strLen = iLen.ToString().PadRight(DYNAMICLENGTHLEN, FILLCHAR);
            return WriteTextToSocket(s, strLen);
        }
        /// <summary>
        /// 将缓存的指定部分发送到Socket
        /// </summary>
        /// <param name="s">要发送缓存的Socket</param>
        /// <param name="buf">要发送的缓存</param>
        /// <param name="iStart">要发送缓存的起始位置</param>
        /// <param name="iCount">要发送缓存的字节数</param>
        /// <param name="iBlock">每次发送的字节说</param>
        /// <param name="SendSuccess">每次发送成功后的回调函数</param>
        /// <returns>是否发送成功</returns>
        public static bool WriteBufToSocket(Socket s, byte[] buf, int iStart, int iCount, int iBlock, OnSend SendSuccess)
        {
            int iSended = 0;
            int iSending = 0;
            while (iSended < iCount)
            {
                if (iSended + iBlock <= iCount)
                    iSending = iBlock;
                else
                    iSending = iCount - iSended;
                s.Send(buf, iStart + iSended, iSending, SocketFlags.None);
                iSended += iSending;
                if (ReadResponsionFromSocket(s) == "OK")
                    if (SendSuccess != null)
                        SendSuccess(iCount, iSended);
                    else
                        return false;
            }
            return true;
        }
        /// <summary>
        /// 将长度不固定文本发送到socket
        /// </summary>
        /// <param name="s">要发送文本的Socket</param>
        /// <param name="strText">要发送的文本</param>
        /// <param name="OnSendText">成功发送一部分文本后的回调函数</param>
        /// <param name="settextlen">得到文本长度的回调函数</param>
        /// <returns></returns>
        public static bool WriteDynamicTextToSocket(Socket s, string strText,
        OnSend OnSendText)
        {
            byte[] buf = Encoding.UTF8.GetBytes(strText);
            int iLen = buf.Length;
            try
            {
                WriteDynamicLenToSocket(s, iLen);
                return WriteBufToSocket(s, buf, 0, iLen, DEALLEN, OnSendText);
            }
            catch (Exception err)
            {
                MessageBox.Show("发送文本失败!" + err.Message);
                return false;
            }
        }
        /// <summary>
        /// 将文件写到Socket
        /// </summary>
        /// <param name="s">要发送文件的Socket</param>
        /// <param name="strFile">要发送的文件</param>
        /// <returns>是否成功</returns>
        public static bool WriteFileToSocket(Socket s, string strFile,
        OnSend OnSendFile)
        {
            FileStream fs = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read);
            int iLen = (int)fs.Length;
            WriteDynamicLenToSocket(s, iLen);
            byte[] buf = new byte[iLen];
            try
            {
                fs.Read(buf, 0, iLen);
                return WriteBufToSocket(s, buf, 0, iLen, DEALLEN, OnSendFile);
            }
            catch (Exception err)
            {
                MessageBox.Show("发送文件失败!" + err.Message);
                return false;
            }
            finally
            {
                fs.Close();
            }
        }
        /// <summary>
        /// 对方对自己消息的简单回应
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ReadResponsionFromSocket(Socket s)
        {
            byte[] bufCmd = new byte[RESPONLEN];
            int iCount = s.Receive(bufCmd);
            string strRespon = Encoding.UTF8.GetString(bufCmd, 0, iCount);
            return strRespon;
        }
        /// <summary>
        /// 从Socket读取命令
        /// </summary>
        /// <param name="s">要读取命令的Socket</param>
        /// <returns>读取的命令</returns>
        public static string ReadCommandFromSocket(Socket s)
        {
            byte[] bufCmd = new byte[CMDLEN];
            int iCount = s.Receive(bufCmd, 0, CMDLEN, SocketFlags.Partial);
            string strCommand = Encoding.UTF8.GetString(bufCmd, 0, CMDLEN);
            return strCommand = strCommand.TrimEnd(FILLCHAR);
        }
        /// <summary>
        /// 读取命令注释
        /// </summary>
        /// <param name="s">要读取命令注释的Socket</param>
        /// <returns>读取的命令注释</returns>
        public static string ReadCommandDescFromSocket(Socket s)
        {
            byte[] bufCmd = new byte[DESCLEN];
            int iCount = s.Receive(bufCmd, 0, DESCLEN, SocketFlags.Partial);
            string strCommand = Encoding.UTF8.GetString(bufCmd, 0, DESCLEN);
            return strCommand = strCommand.TrimEnd(FILLCHAR);
        }
        /// <summary>
        /// 读取可变部分的长度
        /// </summary>
        /// <param name="s">要读取可变部分长度的Socket</param>
        /// <returns>读取的可变部分的长度</returns>
        public static int ReadDynamicLenFromSocket(Socket s)
        {
            byte[] bufCmd = new byte[DYNAMICLENGTHLEN];
            int iCount = s.Receive(bufCmd, 0, DYNAMICLENGTHLEN, SocketFlags.Partial);
            string strCommand = Encoding.UTF8.GetString(bufCmd, 0, DYNAMICLENGTHLEN);
            return int.Parse(strCommand.TrimEnd(FILLCHAR));
        }
        /// <summary>
        /// 读取文本形式的可变信息
        /// </summary>
        /// <param name="s">要读取可变信息的Socket</param>
        /// <returns>读取的可变信息</returns>
        public static string ReadDynamicTextFromSocket(Socket s)
        {
            int iLen = ReadDynamicLenFromSocket(s);
            byte[] buf = new byte[iLen];
            string strInfo = "";
            int iReceiveded = 0;
            int iReceiveing = 0;
            while (iReceiveded < iLen)
            {
                if (iReceiveded + DEALLEN <= iLen)
                    iReceiveing = DEALLEN;
                else
                    iReceiveing = iLen - iReceiveded;
                s.Receive(buf, iReceiveded, iReceiveing, SocketFlags.None);
                CommunClass.WriteTextToSocket(s, "OK");
                iReceiveded += iReceiveing;
            }
            strInfo = Encoding.UTF8.GetString(buf, 0, iLen);
            return strInfo;
        }
        /// <summary>
        /// 读取文件形式的可变信息
        /// </summary>
        /// <param name="s">要读取可变信息的Socket</param>
        /// <param name="strFile">读出后的文件保存位置</param>
        /// <returns>是否读取成功</returns>
        public static bool ReadDynamicFileFromSocket(Socket s, string strFile)
        {
            int iLen = ReadDynamicLenFromSocket(s);
            byte[] buf = new byte[iLen];
            FileStream fs = new FileStream(strFile, FileMode.Create, FileAccess.Write);
            try
            {
                int iReceiveded = 0;
                int iReceiveing = 0;
                while (iReceiveded < iLen)
                {
                    if (iReceiveded + DEALLEN <= iLen)
                        iReceiveing = DEALLEN;
                    else
                        iReceiveing = iLen - iReceiveded;
                    s.Receive(buf, iReceiveded, iReceiveing, SocketFlags.None);
                    CommunClass.WriteTextToSocket(s, "OK");
                    iReceiveded += iReceiveing;
                }
                fs.Write(buf, 0, iLen);
                return true;
            }
            catch (Exception err)
            {
                MessageBox.Show("接收文件失败" + err.Message);
                return false;
            }
            finally
            {
                fs.Close();
            }
        }
    }//end class
}//end namespace



上面是俺的通讯基础类,有了这个类,再进行发送接受还不是小菜一碟吗?

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值