zoukankan      html  css  js  c++  java
  • C# socket编程第四篇

          在第三篇里已经实现了文件的传输,但是在第三篇里,传输的文件是用一个包传过去的,如果文件大点的话,就无法实现了,今天我们来讲如何将大文件分包来处理。既然一个大文件不能一次传,那就要多次传了,既然是多次,那就要分包了。先把demo贴出,程序中都有注释。

    服务端:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Net;
    using System.IO;
    namespace FileReceiveControl
    {
    public class FileOutPackets
    {
    public void GetFileOutPackets()
    {
    try
    {
    Console.WriteLine(
    "this is server");
    int Port = 8001;
    IPEndPoint ipep
    = new IPEndPoint(IPAddress.Any, Port);
    EndPoint ep
    = (EndPoint)ipep;
    Socket sc
    = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    sc.Bind(ep);

    IPEndPoint ipepClient
    = new IPEndPoint(IPAddress.Any, 0);
    EndPoint epClient
    = (EndPoint)ipepClient;

    int Rec;
    byte[] Bytes = new byte[1024];
    //=====获取文件名
    Rec = sc.ReceiveFrom(Bytes, ref epClient);
    string FileName = Encoding.ASCII.GetString(Bytes, 0, Rec);
    //=====向客服端 发送接收到的信号
    Bytes = Encoding.ASCII.GetBytes("1");
    sc.SendTo(Bytes, epClient);

    //======获取文件 bytes 大小
    Bytes = new byte[1024];
    Rec
    = sc.ReceiveFrom(Bytes, ref epClient);
    //=====向客服端 发送接收到的信号
    //Bytes = Encoding.ASCII.GetBytes("2");
    //sc.SendTo(Bytes, epClient);

    //=======获取fs bytes总的大小
    int FileByteLength = int.Parse(Encoding.ASCII.GetString(Bytes, 0, Rec));

    //=======获取总的包数量
    Bytes = new byte[1024];
    Rec
    = sc.ReceiveFrom(Bytes, ref epClient);
    //=======获取总的包数量
    int PacketNum = int.Parse(Encoding.ASCII.GetString(Bytes, 0, Rec));
    Console.WriteLine(
    "packetNum is " + PacketNum);
    //====获取最后一个包的大小
    Bytes = new byte[1024];
    Rec
    = sc.ReceiveFrom(Bytes, ref epClient);
    int FinalPacketSize = int.Parse(Encoding.ASCII.GetString(Bytes, 0, Rec));
    string TempPath = @"E:\" + FileName + ".temp";
    FileStream fs
    = new FileStream(TempPath, FileMode.OpenOrCreate, FileAccess.Write);
    //======循环 接收
    for (int i = 0; i < PacketNum; i++)
    {
    byte[] Data = new byte[8192];
    Rec
    = sc.ReceiveFrom(Data, ref epClient);
    fs.Write(Data,
    0, 8192);
    fs.Flush();
    Console.WriteLine(
    "this is " + (i + 1) + " packet");
    }
    if (FinalPacketSize != 0)
    {
    byte[] data = new byte[FinalPacketSize];
    Rec
    = sc.ReceiveFrom(data, ref epClient);
    fs.Write(data,
    0, FinalPacketSize);
    fs.Flush();
    }
    fs.Close();
    sc.Close();

    FileStream FsMove
    = new FileStream(TempPath, FileMode.Open, FileAccess.Read);

    string Path = TempPath.Remove(TempPath.Length - 5, 5);
    byte[] ByteFile = new byte[FsMove.Length];
    FsMove.Read(ByteFile,
    0, (int)FsMove.Length);
    File.WriteAllBytes(Path, ByteFile);
    FsMove.Close();
    File.Delete(TempPath);
    Console.WriteLine(
    "receive is over");
    //===========死循环 方便调试 避免直接退出
    while (true)
    {

    }
    }
    catch (Exception ex)
    {
    Console.WriteLine(ex.ToString());
    }
    }
    }
    }

    客户端:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    using System.IO;
    using System.Threading;
    namespace FileDistributeControl
    {
    public class FileOutPackets
    {
    public void GetFileOutPackets()
    {
    Console.WriteLine(
    "this is client");
    int Port=8001;
    string Ip="192.168.1.20";
    IPEndPoint ipep
    = new IPEndPoint(IPAddress.Parse(Ip), Port);
    EndPoint ep
    = (EndPoint)ipep;
    Socket sc
    = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);

    string path = @"F:\1.jpg";
    FileInfo fino
    = new FileInfo(path);

    IPEndPoint ipepClient
    = new IPEndPoint(IPAddress.Any,0);
    EndPoint epClient
    = (EndPoint)ipepClient;

    int Rec,Rtn;
    byte[] Bytes=new byte[1024];
    //=========发送 文件名
    sc.SendTo(Encoding.ASCII.GetBytes(fino.Name),ep);

    Rec
    = sc.ReceiveFrom(Bytes,ref epClient);
    Rtn
    =int.Parse(Encoding.ASCII.GetString(Bytes,0,Rec));
    if (Rtn == 1)
    {
    Console.WriteLine(
    "this file name send successful");

    FileStream fs
    = new FileStream(path,FileMode.Open,FileAccess.Read);
    //=======取得最后一个数据包前的数据包总数 (int)将一个浮点数 转整型,只会四舍,不会五入
    //=======1k==1024B==1024*8b 1k等于2的10次方字节,一个字节等于8位
    int PacketNum = (int)(fs.Length /(long)8192);
    int EndPacket = (int)(fs.Length - PacketNum * 8192);
    //=======最后一个包有可能是0
    int TotalPacket;
    if (EndPacket == 0)
    {
    TotalPacket
    = PacketNum;
    }
    else
    {
    TotalPacket
    = PacketNum + 1;
    }

    //=======发送总 的数据包 etc
    sc.SendTo(Encoding.ASCII.GetBytes(fs.Length.ToString()), ep);
    sc.SendTo(Encoding.ASCII.GetBytes(PacketNum.ToString()), ep);
    sc.SendTo(Encoding.ASCII.GetBytes(EndPacket.ToString()),ep);
    //=======循环发送
    Console.WriteLine("packetNum is "+PacketNum);
    for (int i = 0; i < PacketNum; i++)
    {
    byte[] data = new byte[8192];
    fs.Read(data,
    0, 8192);
    sc.SendTo(data,ep);
    Console.WriteLine(
    "this is "+(i+1)+" packet");
    Thread.Sleep(
    300);
    }

    Console.WriteLine(
    "this for is over");
    //=======发送最后一个包
    if (EndPacket != 0)
    {
    byte[] finallData=new byte[EndPacket];
    fs.Read(finallData,
    0,EndPacket);
    sc.SendTo(finallData,ep);
    Console.WriteLine(
    "this is final packet");
    }

    Console.WriteLine(
    "send over");

    }
    else
    {
    //=======返回值不等于1 重新发送
    sc.SendTo(Encoding.ASCII.GetBytes(fino.Name),ep);
    }

    while (true)
    { }

    }
    }
    }
    这样就可以把一个大文件分成很多个包来进行发送了。这里需要注意的是,循环发送的时候需要休眠段时间,如果没有sleep这条语句,那么在服务端无法完整的收完每一个包。至于为什么一次性发完无法收取完,我现在也解释不了,在研究中...希望下一遍的时候可以解决这些问题..

  • 相关阅读:
    紫书 例题8-18 UVa 1442 (扫描法)
    紫书 例题8-17 UVa 1609 (构造法)(详细注释)
    紫书 例题8-16 UVa 1608 (递归)
    紫书 例题8-15 UVa 12174 (滑动窗口)
    紫书 例题8-14 UVa 1607 (二分)
    紫书 例题8-13 UVa 11093 (反证法)
    紫书 例题8-12 UVa 12627 (找规律 + 递归)
    Codeforces Round #441 (Div. 2, by Moscow Team Olympiad)
    CodeForces
    CodeForces 444C 线段树
  • 原文地址:https://www.cnblogs.com/_fyz/p/2042194.html
Copyright © 2011-2022 走看看