想实现的效果是   //客户端指定一个文件夹,将文件夹下所有文件都传到服务端。
     客户端首先遍历子文件,获取文件名,发送文件名,将文件内容转成byte[],然后发送,发送下一个文件名
     
   //服务端用的是
            TcpListener tcpListener = new TcpListener(ipPoint);
            tcpListener.Start();            //这个的问题是,只能监听到第一个文件,其他的文件监听不到了
            //改进方案,发送的时候将文件夹中存在的文件数量传过来
            while (true)
            {
                //如果没有Connect请求
                if (!tcpListener.Pending())   //LineXXX
                {
                    Thread.Sleep(1000);
                    continue;
                }
                
                 else
                 {
                 //接收文件名,创建文件,写入文件内容。这样完成了一个文件。BlockBBB
                 }
            } 问题出来了,在LineXXX这个地方,第一次没有问题,也就是能够执行BlockBBB.但是,第一次后,再次到LineXXX,这个地方就总是监听不到发送端的 Send(Socket,byte[])了。何解?

解决方案 »

  1.   

        我跟踪了发送端,所有子文件的文件名和byte[] data都被Send了,但是每次Send后调试不能跟踪到发送端的情况。 囧,要么只能在发送端跟踪,要么只能在接收端~
      

  2.   

    private void XXXX(IPEndPoint iPoint)
            {
                Socket serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
                serversocket.Bind(iPoint);
                serversocket.Listen(20);
                while (true)
                {
                    Socket socket = serversocket.Accept();
                    byte[] buffer = new byte[1024];
                    int receiveCount = socket.Receive(buffer);
                    if (receiveCount > 0)
                    {
                        string msg = Encoding.UTF8.GetString(buffer, 0, receiveCount);
                    }
                    else
                    {
                        socket.Close();
                        break;
                    }
                }
            }
      

  3.   

    //发送端代码  private void UpLoadFolder()
            {
                Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("192.168.1.44"), 8888);
                client.Connect(ipPoint);
                DirectoryInfo di = new DirectoryInfo(fb.SelectedPath);
                        foreach (FileInfo fi in di.GetFiles())
                        {
                           
                            //发送文件名
                            string filename = fi.Name;
                            byte[] bt_filename = System.Text.Encoding.Unicode.GetBytes(filename);
                            SendVarData(client, bt_filename);                        byte[] bt_data = new byte[50000];
                            FileStream fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read);
                            //文件大于50000字节
                            if (fs.Length >= 50000)
                            {
                                //发送整包
                                int count = (int)(fs.Length / 50000);
                                for (int i = 0; i <= count - 1; i++)
                                {
                                    fs.Read(bt_data, 0, bt_data.Length);
                                    SendVarData(client, bt_data);
                                    //整包发送完,停顿0.05s
                                    Thread.Sleep(50);
                                }
                                //发送余包
                                byte[] bt_dataleft = new byte[fs.Length % 500000];
                                fs.Read(bt_dataleft, 0, bt_dataleft.Length);
                                SendVarData(client, bt_dataleft);
                                                        }                        //文件小于50000字节
                            else
                            {
                                //byte[]中存在元素是空
                                fs.Read(bt_data, 0, bt_data.Length);
                                SendVarData(client, bt_data);
                            }
                            fs.Close();
                        }
                        client.Close();
            }
    //接收端代码
      
     private void StartReceive()
            {
                //监听所有ip
                //IPEndPoint ipPoint = new IPEndPoint(IPAddress.Any, 8888);
                IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("192.168.1.44"), 8888);
                TcpListener tcpListener = new TcpListener(ipPoint);
                tcpListener.Start();          
                while (true)
                {
                    //如果没有Connect请求
                    if (!tcpListener.Pending())
                    {
                        Thread.Sleep(1000);
                        continue;
                    }                //如果有Connect请求
                    Socket client = tcpListener.AcceptSocket();                  
                        byte[] byte_filename = ReceiveVarData(client);
                        string filename = System.Text.Encoding.Unicode.GetString(byte_filename);
                        //创建文件
                        FileStream fs = new FileStream(dir + "\\" + filename, FileMode.OpenOrCreate, FileAccess.Write);                    //向文件中写入数据
                        while (true)
                        {
                            //每次后台返回的就只是一部分
                            byte[] data = ReceiveVarData(client);
                            if (data.Length == 0)
                            {
                                break;
                            }                        else
                            {
                                //写完一段data后,fs在文件中的位置停留在文件末尾,下次循环时,直接追加在文件结尾
                                fs.Write(data, 0, data.Length);
                            }
                        }
                        //关闭文件
                        fs.Close();   
                }
               
            }
      

  4.   

    没有看到你SendVarData和ReceiveVarData是怎么写的,所以很难说。我猜是一次发送以后关掉了连接,或者怎滴。另外,不是每次都能收到数据(比如说某一段数据发了以后你要过一会儿才能收到),但是你if (data.Length == 0)就break,这种判断也有可能导致程序中断。还是看看你那俩函数咋写的吧
      

  5.   

    Send是浮云,发了不一定收的到;发送和接收的代码配合好了才可以
      

  6.   

    你把UpLoadFolder()这个方法的
    Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("192.168.1.44"), 8888);
    client.Connect(ipPoint);
    放到你的SendVarData这个方法的最前面去,应该就可以了。记得要关闭掉socket。
    不然你就用异步发送。Socket client = tcpListener.AcceptSocket();
    每次接受到一个新socket后才会往下走的,如果这么做的话,你的Listen(20)可能不太够,你还要开个线程去处理那些已经关闭的socket。
      

  7.   

    SendVarData\ReceiveVarData使用的是大众版~~已经过测试。        //发送数据
            public static int SendVarData(Socket s, byte[] data)
            {
                int total = 0;
                int size = data.Length;
                int dataleft = size;
                int sent;       //这次发送让我很费解,不过去掉的话,程序就不可用
                byte[] datasize = new byte[4];
                //文件名png.png 被转成了byte[14],这个是将存到datasize[0]中
                datasize = BitConverter.GetBytes(size);            //第一次发出的byte数 
                //发文件名时,只循环了次
                sent = s.Send(datasize);
           //这次发送让我很费解            while (total < size)
                {
                    sent = s.Send(data, total, dataleft, SocketFlags.None);
                    total += sent;
                    dataleft -= sent;
                }
                return total;
            } //接收数据
            public static byte[] ReceiveVarData(Socket s)
            {
                int total = 0;
                int recv;        //这次接收是为了干嘛?
                byte[] datasize = new byte[4];
                recv = s.Receive(datasize, 0, 4, SocketFlags.None);
            //这次接收是为了干嘛?
              
                int size = BitConverter.ToInt32(datasize, 0);
                int dataleft = size;
                byte[] data = new byte[size];
                while (total < size)
                {
                    recv = s.Receive(data, total, dataleft, SocketFlags.None);
                    if (recv == 0)
                    {
                        data = null;
                        break;
                    }
                    total += recv;
                    dataleft -= recv;
                }
                return data;
            }
      

  8.   


    你的第一个问题
    很简单,你发送了,服务器也接收了。但是呢,你的服务器只是接收了一次。所以你只能收到第一次发送的内容。
    你服务器的监听知道用一个循环来监听,接收是一样的,你只接收了一次。
    第二个问题://接收数据
            public static byte[] ReceiveVarData(Socket s)
            {
                int total = 0;
                int recv;        //这次接收是为了干嘛?!!!!!!很明显,人家这是做了一个协议。第一次取出了这个包中数据 的长度,好在接收的时候不会少接收(丢包)或多接收(粘包)。你看一下发送端,一定有一个类或结构体,
    使用encoding.ascii.getbytes(长度);就可以将一个长度转换成二进制数组。此处的byte【4】就是取出原来存的数。
                byte[] datasize = new byte[4];
                recv = s.Receive(datasize, 0, 4, SocketFlags.None);
            //这次接收是为了干嘛?
              
                int size = BitConverter.ToInt32(datasize, 0);
                int dataleft = size;
                byte[] data = new byte[size];
                while (total < size)//这里只是第一次接收
                {
                    recv = s.Receive(data, total, dataleft, SocketFlags.None);
                    if (recv == 0)
                    {
                        data = null;
                        break;
                    }
                    total += recv;
                    dataleft -= recv;
                }//第一次接收结束之后,你没进行第二次的接收。
                return data;
            }其实你客户端的数据都已经发送到服务器了,都在缓冲区中,你没有读出来
      

  9.   

    单文件传输 已经写出。10个G的单文件测试,已通过,很基础~
    传文件夹,这个已经是最基础的了,“丢包、粘包、内容校验”我的子文件全是2kb的txt,单包大小是50m,试验数据设计上就已经回避了丢包、粘包、内容校验。
      

  10.   


    那这点问题就难不倒你,小case,本机测试还是局域网测试?本机的不能信!~
      

  11.   

    单包大小50m那是不可能的socket自动帮你分包了,如果就做一个传文件的小demo,不发送消息,一启动就传文件,那这样的很好做了。
    传文件夹就不一样了
      

  12.   

    小改两处(1)UpLoadFolder()中每传完一个文件,就关闭一次Socket。
            (2)StartReceive() 中没接收完一个文件,就就关闭一次Socket.
           这样做,接收端的收到的byte[] data不会被写入同一个文件中。“跟踪显示所有文件信息已经发送”、“但是在接收端只收到一个文件”,是因为发送的所有的文件信息被写到1个文件中去了,楼主收到的那个文件中,包含了发送端7个文件的信息。
     
    //接收端
     
     private void StartReceive()
            {
                //监听所有ip
                //IPEndPoint ipPoint = new IPEndPoint(IPAddress.Any, 8888);
                IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("192.168.1.44"), 8888);
                TcpListener tcpListener = new TcpListener(ipPoint);
                tcpListener.Start();
     
                while (true)
                {
                    //如果没有Connect请求
                    if (!tcpListener.Pending())
                    {
                        Thread.Sleep(1000);
                        continue;
                    }                //如果有Connect请求
                    //创建接收端Socket
                    Socket client = tcpListener.AcceptSocket();                  
                        byte[] byte_filename = ReceiveVarData(client);
                        string filename = System.Text.Encoding.Unicode.GetString(byte_filename);
                        //创建文件
                        FileStream fs = new FileStream(dir + "\\" + filename, FileMode.OpenOrCreate, FileAccess.Write);                    //向文件中写入数据
                        while (true)
                        {
                            //每次后台返回的就只是一部分
                            byte[] data = ReceiveVarData(client);
                            if (data.Length == 0)
                            {
                                break;
                            }                        else
                            {
                                //写完一段data后,fs在文件中的位置停留在文件末尾,下次循环时,直接追加在文件结尾
                                fs.Write(data, 0, data.Length);
                            }
                        }
                        //关闭文件
                        fs.Close();
                        //每接收完一个文件,要关闭Socket,否则接收的数据被写入一个文件
                        client.Close();      
                }
                
               
            }//发送端//发送文件夹中所有子文件
            private void UpLoadFolder()
            {
                DirectoryInfo di = new DirectoryInfo(fb.SelectedPath);
                        foreach (FileInfo fi in di.GetFiles())
                        {                        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("192.168.1.44"), 8888);
                            client.Connect(ipPoint);                        //发送文件名
                            string filename = fi.Name;
                            byte[] bt_filename = System.Text.Encoding.Unicode.GetBytes(filename);
                            SendVarData(client, bt_filename);                        byte[] bt_data = new byte[50000];
                            FileStream fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read);
                            //文件大于50000字节
                            if (fs.Length >= 50000)
                            {
                                //发送整包
                                int count = (int)(fs.Length / 50000);
                                for (int i = 0; i <= count - 1; i++)
                                {
                                    fs.Read(bt_data, 0, bt_data.Length);
                                    SendVarData(client, bt_data);
                                    //整包发送完,停顿0.05s
                                    Thread.Sleep(50);
                                }
                                //发送余包
                                byte[] bt_dataleft = new byte[fs.Length % 500000];
                                fs.Read(bt_dataleft, 0, bt_dataleft.Length);
                                SendVarData(client, bt_dataleft);
                            }                        //文件小于50000字节
                            else
                            {
                                //byte[]中存在元素是空
                                fs.Read(bt_data, 0, bt_data.Length);
                                SendVarData(client, bt_data);
                            }
                            //每次传完一个文件,必须关闭Socket,否则多个文件的内容会写到一个文件中去。
                            fs.Close();
                            client.Close();
                        }           
            }
      

  13.   

    //发送端//发送文件夹中所有子文件
      private void UpLoadFolder()
      {
      DirectoryInfo di = new DirectoryInfo(fb.SelectedPath);
      foreach (FileInfo fi in di.GetFiles())
      {  Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("192.168.1.44"), 8888);
      client.Connect(ipPoint);  //发送文件名
      string filename = fi.Name;
      byte[] bt_filename = System.Text.Encoding.Unicode.GetBytes(filename);
      SendVarData(client, bt_filename);  byte[] bt_data = new byte[50000];
      FileStream fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read);
      //文件大于50000字节
      if (fs.Length >= 50000)
      {
      //发送整包
      int count = (int)(fs.Length / 50000);
      for (int i = 0; i <= count - 1; i++)
      {
      fs.Read(bt_data, 0, bt_data.Length);
      SendVarData(client, bt_data);
      //整包发送完,停顿0.05s
      Thread.Sleep(50);
      }
      //发送余包
      byte[] bt_dataleft = new byte[fs.Length % 500000];
      fs.Read(bt_dataleft, 0, bt_dataleft.Length);
      SendVarData(client, bt_dataleft);
      }  //文件小于50000字节
      else
      {
      //byte[]中存在元素是空
      fs.Read(bt_data, 0, bt_data.Length);
      SendVarData(client, bt_data);
      }
      //每次传完一个文件,必须关闭Socket,否则多个文件的内容会写到一个文件中去。
      fs.Close();
      client.Close();
      }   
      }
      

  14.   

    文件传输问题解决了
       现在看到另一个问题
        Send端的文件夹下 7个1kb的txt,到了接收夹中就成了7个50kb的,文件大小变大了~~
      

  15.   

    发送端作如下修改,接收到的文件与发送的文件同大 //发送文件夹中所有子文件
            private void UpLoadFolder()
            {
                DirectoryInfo di = new DirectoryInfo(fb.SelectedPath);
                        foreach (FileInfo fi in di.GetFiles())
                        {                        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("192.168.1.44"), 8888);
                            client.Connect(ipPoint);                        //发送文件名
                            string filename = fi.Name;
                            byte[] bt_filename = System.Text.Encoding.Unicode.GetBytes(filename);
                            SendVarData(client, bt_filename);                        //byte[] bt_data = new byte[50000];
                            FileStream fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read);
                            //文件大于50000字节
                            if (fs.Length >= 50000)
                            {
                                //发送整包
                                byte[] bt_data = new byte[50000];
                                int count = (int)(fs.Length / 50000);
                                for (int i = 0; i <= count - 1; i++)
                                {
                                    fs.Read(bt_data, 0, bt_data.Length);
                                    SendVarData(client, bt_data);
                                    //整包发送完,停顿0.05s
                                    Thread.Sleep(50);
                                }
                                //发送余包
                                byte[] bt_dataleft = new byte[fs.Length % 500000];
                                fs.Read(bt_dataleft, 0, bt_dataleft.Length);
                                SendVarData(client, bt_dataleft);
                            }                        //文件小于50000字节
                            else
                            {
                                //byte[]中存在元素是空
                                byte[] bt_data = new byte[(int)(fs.Length)];
                                fs.Read(bt_data, 0, (int)(bt_data.Length));
                                SendVarData(client, bt_data);
                            }
                            //每次传完一个文件,必须关闭Socket,否则多个文件的内容会写到一个文件中去。
                            fs.Close();
                            client.Close();
                        }           
            }
      

  16.   

    你做 异步的 监听回调 
    AsyncCallback 这个回调函数 方法