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

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

    1. using System;  
    2. using System.Net.Sockets;  
    3. using System.Net;  
    4. using System.IO;  
    5. using System.Windows.Forms;  
    6. using System.Text;  
    7. namespace BaseClass  
    8. {  
    9.     /// <summary>  
    10.     /// 传送信息的格式为 给定长度的命令部分+给定长度的命令注释部分+可变长度的长度信息+可变长度的信息部分  
    11.     /// </summary>  
    12.     public class CommunClass  
    13.     {  
    14.         public CommunClass()  
    15.         {  
    16.             //  
    17.             // TODO: 在此处添加构造函数逻辑  
    18.             //  
    19.         }  
    20.   
    21.         /// <summary>  
    22.         /// 命令部分的长度  
    23.         /// </summary>  
    24.         private static readonly int CMDLEN = 50;  
    25.         /// <summary>  
    26.         /// 命令注释部分的长度  
    27.         /// </summary>  
    28.         private static readonly int DESCLEN = 100;  
    29.         /// <summary>  
    30.         /// 可变长度的长度信息部分所占的字节数  
    31.         /// </summary>  
    32.         private static readonly int DYNAMICLENGTHLEN = 10;  
    33.         /// <summary>  
    34.         /// 每次处理可变信息部分的长度  
    35.         /// </summary>  
    36.         private static readonly int DEALLEN = 1024;  
    37.         /// <summary>  
    38.         /// /应答的最大长度  
    39.         /// </summary>  
    40.         private static readonly int RESPONLEN = 20;  
    41.         /// <summary>  
    42.         /// 用于填充命令或注释不足长度部分的字符  
    43.         /// </summary>   
    44.         private static readonly char FILLCHAR = '^';  
    45.         /// <summary>  
    46.         /// 成功发送一部分数据后的回调方法(也可以认为是触发的事件,但严格来说还不是)  
    47.         /// </summary>  
    48.         public delegate void OnSend(int iTotal, int iSending);  
    49.         /// <summary>  
    50.         /// 根据给定的服务器和端口号建立连接  
    51.         /// </summary>  
    52.         /// <param name="strHost">服务器名</param>  
    53.         /// <param name="iPort">端口号</param>  
    54.         /// <returns></returns>  
    55.         public static Socket ConnectToServer(string strHost, int iPort)  
    56.         {  
    57.             try  
    58.             {  
    59.                 IPAddress ipAddress = Dns.Resolve(strHost).AddressList[0];  
    60.                 IPEndPoint ipPoint = new IPEndPoint(ipAddress, iPort);  
    61.                 Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
    62.                 s.Connect(ipPoint);  
    63.                 return s;  
    64.             }  
    65.             catch (Exception e)  
    66.             {  
    67.                 throw (new Exception("建立到服务器的连接出错" + e.Message));  
    68.             }  
    69.         }  
    70.         /// <summary>  
    71.         /// 将文本写到Socket中  
    72.         /// </summary>  
    73.         /// <param name="s">要发送信息的Socket</param>  
    74.         /// <param name="strInfo">要发送的信息</param>  
    75.         /// <returns>是否成功</returns>  
    76.         public static bool WriteTextToSocket(Socket s, string strInfo)  
    77.         {  
    78.             byte[] buf = Encoding.UTF8.GetBytes(strInfo);  
    79.             try  
    80.             {  
    81.                 s.Send(buf, 0, buf.Length, SocketFlags.None);  
    82.                 return true;  
    83.             }  
    84.             catch (Exception err)  
    85.             {  
    86.                 MessageBox.Show("发送文本失败!" + err.Message);  
    87.                 return false;  
    88.             }  
    89.         }  
    90.         /// <summary>  
    91.         /// 将命令文本写到Socket中  
    92.         /// </summary>  
    93.         /// <param name="s">要发送命令文本的Socket</param>  
    94.         /// <param name="strInfo">要发送的命令文本</param>  
    95.         /// <returns>是否成功</returns>  
    96.         public static bool WriteCommandToSocket(Socket s, string strCmd)  
    97.         {  
    98.             if (strCmd == "")  
    99.                 strCmd = "NOP";  
    100.             strCmd = strCmd.PadRight(CMDLEN, FILLCHAR);  
    101.             return WriteTextToSocket(s, strCmd);  
    102.         }  
    103.         /// <summary>  
    104.         /// 将命令注释写到Socket中  
    105.         /// </summary>  
    106.         /// <param name="s">要发送命令注释的Socket</param>  
    107.         /// <param name="strInfo">要发送的命令注释</param>  
    108.         /// <returns>是否成功</returns>  
    109.         public static bool WriteCommandDescToSocket(Socket s, string strDesc)  
    110.         {  
    111.             if (strDesc == "")  
    112.                 strDesc = "0";  
    113.             strDesc = strDesc.PadRight(DESCLEN, FILLCHAR);  
    114.             return WriteTextToSocket(s, strDesc);  
    115.         }  
    116.         /// <summary>  
    117.         /// 发送可变信息的字节数  
    118.         /// </summary>  
    119.         /// <param name="s">要发送字节数的Socket</param>  
    120.         /// <param name="iLen">字节数</param>  
    121.         /// <returns>是否成功</returns>  
    122.         public static bool WriteDynamicLenToSocket(Socket s, int iLen)  
    123.         {  
    124.             string strLen = iLen.ToString().PadRight(DYNAMICLENGTHLEN, FILLCHAR);  
    125.             return WriteTextToSocket(s, strLen);  
    126.         }  
    127.         /// <summary>  
    128.         /// 将缓存的指定部分发送到Socket  
    129.         /// </summary>  
    130.         /// <param name="s">要发送缓存的Socket</param>  
    131.         /// <param name="buf">要发送的缓存</param>  
    132.         /// <param name="iStart">要发送缓存的起始位置</param>  
    133.         /// <param name="iCount">要发送缓存的字节数</param>  
    134.         /// <param name="iBlock">每次发送的字节说</param>  
    135.         /// <param name="SendSuccess">每次发送成功后的回调函数</param>  
    136.         /// <returns>是否发送成功</returns>  
    137.         public static bool WriteBufToSocket(Socket s, byte[] buf, int iStart, int iCount, int iBlock, OnSend SendSuccess)  
    138.         {  
    139.             int iSended = 0;  
    140.             int iSending = 0;  
    141.             while (iSended < iCount)  
    142.             {  
    143.                 if (iSended + iBlock <= iCount)  
    144.                     iSending = iBlock;  
    145.                 else  
    146.                     iSending = iCount - iSended;  
    147.                 s.Send(buf, iStart + iSended, iSending, SocketFlags.None);  
    148.                 iSended += iSending;  
    149.                 if (ReadResponsionFromSocket(s) == "OK")  
    150.                     if (SendSuccess != null)  
    151.                         SendSuccess(iCount, iSended);  
    152.                     else  
    153.                         return false;  
    154.             }  
    155.             return true;  
    156.         }  
    157.         /// <summary>  
    158.         /// 将长度不固定文本发送到socket  
    159.         /// </summary>  
    160.         /// <param name="s">要发送文本的Socket</param>  
    161.         /// <param name="strText">要发送的文本</param>  
    162.         /// <param name="OnSendText">成功发送一部分文本后的回调函数</param>  
    163.         /// <param name="settextlen">得到文本长度的回调函数</param>  
    164.         /// <returns></returns>  
    165.         public static bool WriteDynamicTextToSocket(Socket s, string strText,  
    166.         OnSend OnSendText)  
    167.         {  
    168.             byte[] buf = Encoding.UTF8.GetBytes(strText);  
    169.             int iLen = buf.Length;  
    170.             try  
    171.             {  
    172.                 WriteDynamicLenToSocket(s, iLen);  
    173.                 return WriteBufToSocket(s, buf, 0, iLen, DEALLEN, OnSendText);  
    174.             }  
    175.             catch (Exception err)  
    176.             {  
    177.                 MessageBox.Show("发送文本失败!" + err.Message);  
    178.                 return false;  
    179.             }  
    180.         }  
    181.         /// <summary>  
    182.         /// 将文件写到Socket  
    183.         /// </summary>  
    184.         /// <param name="s">要发送文件的Socket</param>  
    185.         /// <param name="strFile">要发送的文件</param>  
    186.         /// <returns>是否成功</returns>  
    187.         public static bool WriteFileToSocket(Socket s, string strFile,  
    188.         OnSend OnSendFile)  
    189.         {  
    190.             FileStream fs = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read);  
    191.             int iLen = (int)fs.Length;  
    192.             WriteDynamicLenToSocket(s, iLen);  
    193.             byte[] buf = new byte[iLen];  
    194.             try  
    195.             {  
    196.                 fs.Read(buf, 0, iLen);  
    197.                 return WriteBufToSocket(s, buf, 0, iLen, DEALLEN, OnSendFile);  
    198.             }  
    199.             catch (Exception err)  
    200.             {  
    201.                 MessageBox.Show("发送文件失败!" + err.Message);  
    202.                 return false;  
    203.             }  
    204.             finally  
    205.             {  
    206.                 fs.Close();  
    207.             }  
    208.         }  
    209.         /// <summary>  
    210.         /// 对方对自己消息的简单回应  
    211.         /// </summary>  
    212.         /// <param name="s"></param>  
    213.         /// <returns></returns>  
    214.         public static string ReadResponsionFromSocket(Socket s)  
    215.         {  
    216.             byte[] bufCmd = new byte[RESPONLEN];  
    217.             int iCount = s.Receive(bufCmd);  
    218.             string strRespon = Encoding.UTF8.GetString(bufCmd, 0, iCount);  
    219.             return strRespon;  
    220.         }  
    221.         /// <summary>  
    222.         /// 从Socket读取命令  
    223.         /// </summary>  
    224.         /// <param name="s">要读取命令的Socket</param>  
    225.         /// <returns>读取的命令</returns>  
    226.         public static string ReadCommandFromSocket(Socket s)  
    227.         {  
    228.             byte[] bufCmd = new byte[CMDLEN];  
    229.             int iCount = s.Receive(bufCmd, 0, CMDLEN, SocketFlags.Partial);  
    230.             string strCommand = Encoding.UTF8.GetString(bufCmd, 0, CMDLEN);  
    231.             return strCommand = strCommand.TrimEnd(FILLCHAR);  
    232.         }  
    233.         /// <summary>  
    234.         /// 读取命令注释  
    235.         /// </summary>  
    236.         /// <param name="s">要读取命令注释的Socket</param>  
    237.         /// <returns>读取的命令注释</returns>  
    238.         public static string ReadCommandDescFromSocket(Socket s)  
    239.         {  
    240.             byte[] bufCmd = new byte[DESCLEN];  
    241.             int iCount = s.Receive(bufCmd, 0, DESCLEN, SocketFlags.Partial);  
    242.             string strCommand = Encoding.UTF8.GetString(bufCmd, 0, DESCLEN);  
    243.             return strCommand = strCommand.TrimEnd(FILLCHAR);  
    244.         }  
    245.         /// <summary>  
    246.         /// 读取可变部分的长度  
    247.         /// </summary>  
    248.         /// <param name="s">要读取可变部分长度的Socket</param>  
    249.         /// <returns>读取的可变部分的长度</returns>  
    250.         public static int ReadDynamicLenFromSocket(Socket s)  
    251.         {  
    252.             byte[] bufCmd = new byte[DYNAMICLENGTHLEN];  
    253.             int iCount = s.Receive(bufCmd, 0, DYNAMICLENGTHLEN, SocketFlags.Partial);  
    254.             string strCommand = Encoding.UTF8.GetString(bufCmd, 0, DYNAMICLENGTHLEN);  
    255.             return int.Parse(strCommand.TrimEnd(FILLCHAR));  
    256.         }  
    257.         /// <summary>  
    258.         /// 读取文本形式的可变信息  
    259.         /// </summary>  
    260.         /// <param name="s">要读取可变信息的Socket</param>  
    261.         /// <returns>读取的可变信息</returns>  
    262.         public static string ReadDynamicTextFromSocket(Socket s)  
    263.         {  
    264.             int iLen = ReadDynamicLenFromSocket(s);  
    265.             byte[] buf = new byte[iLen];  
    266.             string strInfo = "";  
    267.             int iReceiveded = 0;  
    268.             int iReceiveing = 0;  
    269.             while (iReceiveded < iLen)  
    270.             {  
    271.                 if (iReceiveded + DEALLEN <= iLen)  
    272.                     iReceiveing = DEALLEN;  
    273.                 else  
    274.                     iReceiveing = iLen - iReceiveded;  
    275.                 s.Receive(buf, iReceiveded, iReceiveing, SocketFlags.None);  
    276.                 CommunClass.WriteTextToSocket(s, "OK");  
    277.                 iReceiveded += iReceiveing;  
    278.             }  
    279.             strInfo = Encoding.UTF8.GetString(buf, 0, iLen);  
    280.             return strInfo;  
    281.         }  
    282.         /// <summary>  
    283.         /// 读取文件形式的可变信息  
    284.         /// </summary>  
    285.         /// <param name="s">要读取可变信息的Socket</param>  
    286.         /// <param name="strFile">读出后的文件保存位置</param>  
    287.         /// <returns>是否读取成功</returns>  
    288.         public static bool ReadDynamicFileFromSocket(Socket s, string strFile)  
    289.         {  
    290.             int iLen = ReadDynamicLenFromSocket(s);  
    291.             byte[] buf = new byte[iLen];  
    292.             FileStream fs = new FileStream(strFile, FileMode.Create, FileAccess.Write);  
    293.             try  
    294.             {  
    295.                 int iReceiveded = 0;  
    296.                 int iReceiveing = 0;  
    297.                 while (iReceiveded < iLen)  
    298.                 {  
    299.                     if (iReceiveded + DEALLEN <= iLen)  
    300.                         iReceiveing = DEALLEN;  
    301.                     else  
    302.                         iReceiveing = iLen - iReceiveded;  
    303.                     s.Receive(buf, iReceiveded, iReceiveing, SocketFlags.None);  
    304.                     CommunClass.WriteTextToSocket(s, "OK");  
    305.                     iReceiveded += iReceiveing;  
    306.                 }  
    307.                 fs.Write(buf, 0, iLen);  
    308.                 return true;  
    309.             }  
    310.             catch (Exception err)  
    311.             {  
    312.                 MessageBox.Show("接收文件失败" + err.Message);  
    313.                 return false;  
    314.             }  
    315.             finally  
    316.             {  
    317.                 fs.Close();  
    318.             }  
    319.         }  
    320.     }//end class  
    321. }//end namespace  

posted on 2012-10-29 23:47  ken0752  阅读(673)  评论(0)    收藏  举报

导航