通过套接字在 C# 中传输一半文件?

Half file transferring in c# via socket?

我正在通过中级贪婪路由开发文件传输应用程序,其中文件发送到贪婪,贪婪再次将文件发送到路由器 但他的问题是有时客户端会收到完整的文件,有时会收到文件的一部分

这是我的代码 服务器端

IPAddress[] ipAddress = Dns.GetHostAddresses("127.0.0.1");
            IPEndPoint ipEnd = new IPEndPoint(ipAddress[0], 5655);
            Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);


            string filePath = "";


            fileDes = fileDes.Replace("\", "/");
            while (fileDes.IndexOf("/") > -1)
            {
                filePath += fileDes.Substring(0, fileDes.IndexOf("/") + 1);
                fileDes = fileDes.Substring(fileDes.IndexOf("/") + 1);
            }


            byte[] fileNameByte = Encoding.ASCII.GetBytes(fileDes);

            lblError.Text = "";
            lblError.Text = "Buffering ...";
            byte[] fileData = File.ReadAllBytes(filePath + fileDes);
            byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
            byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);

            fileNameLen.CopyTo(clientData, 0);
            fileNameByte.CopyTo(clientData, 4);
            fileData.CopyTo(clientData, 4 + fileNameByte.Length);

            lblError.Text = "";
            lblError.Text = "Connection to server ...";
            clientSock.Connect(ipEnd);

            lblError.Text = "";
            lblError.Text = "File sending...";
         //   System.Threading.Thread.Sleep(1000);
            clientSock.Send(clientData);
            label3.Text = clientData.Length.ToString();

            lblError.Text = "";
            lblError.Text = "Disconnecting...";
            clientSock.Close();

            lblError.Text = "";
            lblError.Text = "File transferred.";

在客户端

class DestCode
{
    IPEndPoint ipEnd;
    Socket sock;
    public DestCode()
    {
       ipEnd = new IPEndPoint(IPAddress.Any, 5656);
       sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
       sock.Bind(ipEnd);
    }
    public static string receivedPath;
    public static string curMsg = "Stopped";
    public static int res;
    public  void StartServer()
    {
        try
        {
            curMsg = "Starting...";
            sock.Listen(100);

            curMsg = "Running and waiting to receive file.";
            Socket clientSock = sock.Accept();

            byte[] clientData = new byte[1024 * 5000];

            int receivedBytesLen = clientSock.Receive(clientData);

            curMsg = "Receiving data...";

            int fileNameLen = BitConverter.ToInt32(clientData, 0);
            string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);

            BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath +"/"+ fileName, FileMode.Append)); ;
            bWrite.Write(clientData,4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
            res = receivedBytesLen;
            if (receivedPath == "")
            {
                MessageBox.Show("No Path was selected to Save the File");
            }
            curMsg = "Saving file...";

            bWrite.Close();
            clientSock.Close();
            curMsg = "File Received ...";

            StartServer();

        }
        catch (Exception ex)
        {
            curMsg = "File Receving error.";
        }
    }
}

贪心

class ReceiverCode
{
    IPEndPoint ipEnd;
    Socket sock;
    public ReceiverCode()
    {
        ipEnd = new IPEndPoint(IPAddress.Any, 5655);
        sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
        sock.Bind(ipEnd);
    }
    public static string receivedPath;
    public static string curMsg = "Stopped";
    public static string Rout = "";
    public static int rlength = 0;
    public static string MsgStatus = "";
    public static byte[] send;
    public void StartServer()
    {
        try
        {
            curMsg = "Starting...";
            sock.Listen(100);

            curMsg = "Running and waiting to receive file.";
            Socket clientSock = sock.Accept();

            byte[] clientData = new byte[1024 * 5000];

            int receivedBytesLen = clientSock.Receive(clientData);
           System.Threading.Thread.Sleep(5000);
            rlength = receivedBytesLen;
            curMsg = "Receiving data...";

            int receive = clientSock.Receive(clientData);


            send = new byte[receivedBytesLen];
            Array.Copy(clientData, send, receivedBytesLen);
            Rout = "Start";
            clientSock.Close();
            curMsg = "Reeived & Saved file; Server Stopped.";
            StartServer();

        }
        catch (Exception ex)
        {
            curMsg = "File Receving error.";
        }
    }


}

请有人帮助我

问题是 Socket.Receive 不能保证您会收到您要求的所有字节。所以你写:

int receivedBytesLen = clientSock.Receive(clientData);

documentation 说:

If you are using a connection-oriented Socket, the Receive method will read as much data as is available, up to the size of the buffer.

Receive 的调用正在获取当前可用的所有字节。可能是发件人尚未发送所有字节,或者您的网络堆栈尚未收到并使它们可用。

为了可靠地发送和接收数据,接收方必须知道以下两件事之一:它期望有多少字节,或者有一些标记值表明,"that's all, folks." 你不能指望一次 Receive 调用即可获取所有内容。

传输文件时,发件人通常将文件的大小作为要发送的数据的前四个字节。然后您的代码读取前四个字节(确保您获得所有四个字节)以确定大小,然后旋转一个循环,从套接字读取数据,直到收到所有预期的字节。

类似于:

const int MaximumSize = 1000000;
// read the first four bytes
var sizeBytes = ReadBytesFromSocket(socket, 4);
int size = BitConverter.ToInt32(sizeBytes);

var dataBuffer = ReadBytesFromSocket(socket, size);
// you now have your data

byte[] ReadBytesFromSocket(Socket socket, int size)
{
    var buff = new byte[size];
    int totalBytesRead = 0;

    while (totalBytesRead < size)
    {
        int bytesRead = socket.Receive(buff, totalBytesRead, size-totalBytesRead, SocketFlags.None);
        if (bytesRead == 0)
        {
            // nothing received. The socket has been closed.
            // maybe an error.
            break;
        }
        totalBytesRead += bytesRead
    }
    return buff;
}

有关详细信息,请参阅我在 reading streams 上的博客 post(以及链接的第 1 部分和第 2 部分)。博客 post 讨论流,但概念与套接字相同。