コード例 #1
0
        private void button1_Click(object sender, EventArgs e)
        {
            //创建监听线程
            // Create a TCPListener to accept client connections
            TcpListener listener = new TcpListener(IPAddress.Any, _port);

            listener.Start();

            TcpClient client = listener.AcceptTcpClient(); // Get client connection


            NetworkStream clientStream = client.GetStream();

            //BinaryReader br = new BinaryReader(clientStream);

            byte[] pathBytes = new byte[client.ReceiveBufferSize];
            int    bytesRead = clientStream.Read(pathBytes, 0, client.ReceiveBufferSize);

            _path = Encoding.UTF8.GetString(pathBytes, 0, bytesRead);



            //BinaryReader src = new BinaryReader(new BufferedStream(client.GetStream()));
            //int stringLength = src.Read(); // Returns an unsigned byte as an int
            //if (stringLength == -1)
            //    throw new EndOfStreamException();
            //byte[] stringBuf = new byte[stringLength];
            //src.Read(stringBuf, 0, stringLength);


            //拿到文件路径,判断存在性
            //_path = System.Text.Encoding.Default.GetString(pathBytes);

            label1.Text = _path;

            if (File.Exists(_path))
            {
                //文件存在,需要返回命令帧
                Mode.ServerCmd serverCmd = new Mode.ServerCmd();
                //文件存在
                serverCmd.IsExist = true;

                //获取文件大小
                System.IO.FileInfo f = new FileInfo(_path);
                serverCmd.Length = f.Length;

                //发送给客户端,写一个同样大小的空文件,以dat结尾作调试用

                byte[] bytesToSend = Convertor.StructToBytes(serverCmd);
                client.GetStream().Write(bytesToSend, 0, bytesToSend.Length);

                //服务器收到从客户端传来的准备好的消息

                Mode.ClientCmd clientCmd = new Mode.ClientCmd();

                byte[] structBytes = new byte[client.ReceiveBufferSize];
                clientStream.Read(structBytes, 0, client.ReceiveBufferSize);
                Mode.ClientCmd cmdFromClient = (Mode.ClientCmd)Convertor.BytesToStruct(structBytes, clientCmd.GetType());

                //测试是否准备好——客户端已经建好空文件,记得校验md5
                //MessageBox.Show(cmdFromClient.IsReady.ToString());

                //开始发送数据
                //1.创建一个预指令
                Mode.PreData preData = new Mode.PreData();
                //文件剩余传输量
                preData.Left = serverCmd.Length;
                //每次传输量
                preData.Period = 1024;

                //文件对象
                FileStream fs = new FileStream(_path, FileMode.Open, FileAccess.Read);

                //读文件,从当前位置开始
                //当前位置为0
                int curPos = 0;

                while (preData.Left > 0)
                {
                    clientStream.Read(structBytes, 0, client.ReceiveBufferSize);
                    cmdFromClient = (Mode.ClientCmd)Convertor.BytesToStruct(structBytes, clientCmd.GetType());

                    //客户端准备好接收数据
                    if (cmdFromClient.IsReady)
                    {
                        //命令字节数组
                        //byte[] cmdBytes = Convertor.StructToBytes(preData);

                        //如果剩余量比每次传输的片段值大,证明还可以按原来的量传输
                        if (preData.Left > preData.Period)
                        {
                            //本次传送完成后剩余文件大小
                            preData.Left -= preData.Period;

                            //命令字节数组
                            byte[] cmdBytes = Convertor.StructToBytes(preData);

                            byte[] periodbytes = new byte[preData.Period];

                            //文件大小超过4G要怎么办???暂时先取int的范围
                            fs.Read(periodbytes, 0, periodbytes.Length);
                            //文件流现在在periodbytes里面,和命令拼接后发送给客户端


                            string tmp      = Encoding.UTF8.GetString(periodbytes);
                            byte[] sumBytes = new byte[cmdBytes.Length + periodbytes.Length];
                            System.Buffer.BlockCopy(cmdBytes, 0, sumBytes, 0, cmdBytes.Length);
                            System.Buffer.BlockCopy(periodbytes, 0, sumBytes, cmdBytes.Length, periodbytes.Length);

                            //将拼接后的字节数组发出去
                            client.GetStream().Write(sumBytes, 0, sumBytes.Length);
                            client.GetStream().Flush();
                            //更新当前位置
                            curPos     += preData.Period;
                            fs.Position = curPos;
                        }
                        else
                        {
                            //传差量
                            preData.Period = (int)preData.Left;

                            //本次传送完成后剩余文件大小
                            preData.Left -= preData.Period;
                            //命令字节数组
                            byte[] cmdBytes = Convertor.StructToBytes(preData);

                            byte[] periodbytes = new byte[preData.Period];
                            fs.Read(periodbytes, 0, periodbytes.Length);
                            //写完了
                            //文件流现在在periodbytes里面,和命令拼接后发送给客户端
                            byte[] sumBytes = new byte[cmdBytes.Length + periodbytes.Length];
                            System.Buffer.BlockCopy(cmdBytes, 0, sumBytes, 0, cmdBytes.Length);
                            System.Buffer.BlockCopy(periodbytes, 0, sumBytes, cmdBytes.Length, periodbytes.Length);
                            //将拼接后的字节数组发出去

                            string tmp = Encoding.UTF8.GetString(periodbytes);
                            curPos += preData.Period;

                            client.GetStream().Write(sumBytes, 0, sumBytes.Length);
                            client.GetStream().Flush();
                            fs.Position = curPos;
                        }
                    }
                }

                //关闭文件
                fs.Close();
                MessageBox.Show("传输完成!");
                //MessageBox.Show("文件存在");
            }
            else
            {
                MessageBox.Show("无此文件");
            }
            client.Close();
            listener.Stop();
        }