2017-05-26 26 views
-2

我编写了一个客户机/服务器应用程序来发送文件。它适用于服务器和客户端在同一台机器上,但是当我将服务器放在另一台机器上时,服务器读取套接字时出现错误。套接字通信在同一台机器上工作,但不在不同机器之间

这是服务器的代码:

class conexion 
{ 
    int sizeofonpacket = 9999; 
    string filsc=""; 
    string titre = ""; 
    bool sendfilcomand = false; 
    int conteur1 = 0; 
    int conteur2 = 0; 
    BinaryWriter sf; 
    TcpListener listiner; 
    TcpClient client; 
    NetworkStream netStream; 

    public conexion(IPAddress ip, int port) 
    { 
     listiner = new TcpListener(ip, port); 
     listiner.Start(); 
     client = listiner.AcceptTcpClient(); 
     netStream = client.GetStream(); 
     Console.Write("client is present \r\n "); 
    } 

    public void read() 
    { 
     while (client.Connected) 
     { 
      string returndata; 
      int size = 0; 
      string c = ""; 
      byte[] bs = new byte[4]; 
      byte[] b = new byte[1]; 

      try 
      { 
       //read the comand of client "s" for string or "b" for binary file if it is "s" it read the string that client write 
       //if it is "b" we read the string "dfgjsdgfjdsgfjhdsgfj" it is not important 
       Console.Write("ready \r\n "); 
       netStream.Read(b, 0, 1); 

       c = Encoding.UTF8.GetString(b); 
       Console.WriteLine("\r\n comand :" + c); 
       b = new byte[4]; 
       netStream.Read(b, 0, 4); 
       returndata = Encoding.UTF8.GetString(b); 
       size = Int32.Parse(returndata); 
       Console.WriteLine("\r\n size de packet int =" + size); 
       b = new byte[size]; 
       netStream.Read(b, 0, size); 
      } 
      catch 
      { 
       Console.WriteLine("\r\n conexion echoue"); 
       listiner.Stop(); 
      } 

      switch (c) 
      { 
       case "b": 
        if (sendfilcomand == false) //if sendfilcomand is false we read first the title 
        { 
         sendfilcomand = true; 

         break; 
        } 
        sendfilcomand = false; 
        filsc = titre; 
        Console.WriteLine("\r\nle titr est:" + titre); 

        titre = ""; 
        sf = new BinaryWriter(new FileStream(filsc, FileMode.Create)); 

        conteur2 = 0; 
        conteur1 = size; 
        crebfile(b); 
        Console.WriteLine("\r\n creat file for " + conteur2 + " to " + conteur1); 
        b = new byte[sizeofonpacket]; 
        while (size != 0) 
        { 
         try 
         { 
          netStream.Read(bs, 0, 4); 

          returndata = Encoding.UTF8.GetString(bs); 
          size = Int32.Parse(returndata); 

          conteur1 = size; 
          Console.WriteLine("sizee a get" + size); 

          if (size == 0) 
          { 
           Console.WriteLine("yout est termine"); 
           sf.Close(); 
           conteur1 = 0; 
           conteur2 = 0; 
           break; 
          } 
          else if (size != sizeofonpacket) 
          { 
           b = new byte[size]; 
          } 
          netStream.Read(b, 0, size); 
         } 
         catch 
         { 
          Console.WriteLine("\r\n imposible to read "); 
         } 

         crebfile(b); 
         b.Initialize(); 
        } 

        sf.Close(); 
        conteur1 = 0; 
        conteur2 = 0; 
        break; 

       case "s": 
        returndata = Encoding.UTF8.GetString(b); 
        Console.WriteLine("\r\n" + returndata); 

        if (sendfilcomand) 
        { 
         titre = returndata; 
         Console.WriteLine("titre a get" + titre); 

         break; 
        } 
        break; 

       default: 
        Console.WriteLine("\r\n rien comand"); 
        break; 
      } 
     } 
    } 

    public string quadripl(string s) 
    { 
     while (s.Length < 4) 
     { 
      s = "0" + s; 
     } 
     return s; 
    } 

    public void crebfile(byte[] byts) 
    { 
     try 
     { 
      sf.Write(byts, 0, conteur1); 
     } 
     catch 
     { 
      Console.WriteLine("imposible de crer le fichier"); 
     } 
    } 
} 

这里是客户端代码:

class conexion 
{ 
    string filsr; 
    int sizeofonpacket = 9999; 
    bool sendfilcomand = false; 
    bool getfilcomand = false; 
    int bali; 
    int fali; 
    Stream file; 
    TcpListener listiner; 
    TcpClient client; 
    NetworkStream netStream; 

    public conexion(string ip, int port) 
    { 
     listiner = null; 
     Console.Write("star client "); 
     client = new TcpClient(ip, 3568); 
     netStream = client.GetStream(); 
    } 

    public void send() 
    { 
     while (client.Connected) 
     { 
      //enter the comand "s" or "b" 
      string c = ""; 
      Console.WriteLine("\r\n ecrir comand:"); 
      c = Console.ReadLine(); 

      string s = ""; 
      if (c == "s") 
      { 
       Console.WriteLine("\r\n entrer string:"); 
       s = Console.ReadLine(); 
      } 
      string size = ""; 
      Byte[] sendBytes = null; 
      //try 
      { 
       switch (c) 
       { 
        case "b": 
         Console.WriteLine("\r\n comand binary file"); 
         netStream.Write(Encoding.UTF8.GetBytes(c), 0, 1); 
         if (sendfilcomand == false) //we will first send the patsh of file after we will send data of file 
         { 
          sendBytes = Encoding.UTF8.GetBytes("dfgjsdgfjdsgfjhdsgfj"); //this is not important 
          size = quadripl(sendBytes.Length.ToString()); 
          netStream.Write(Encoding.UTF8.GetBytes(size), 0, Encoding.UTF8.GetBytes(size).Length); 
          netStream.Write(sendBytes, 0, sendBytes.Length); 
          sendfilcomand = true; 
          s = getitr(); 
          c = "s"; 
          goto case "s"; 
         } 
         sendfilcomand = false; //now we will send data 
         filsr = actitr(); //the title is save in "C:/Users/Ce-Pc/Desktop/titreactuel.txt" 
         file = new FileStream(filsr, FileMode.Open); 
         fali = (int)file.Length; 
         bali = 0; 
         byte[] bs = new byte[4]; 
         Console.WriteLine("\r\n star sending "); 
         do 
         { 

          sendBytes = filebtobyte(filsr); //read part of file to send 
          Console.WriteLine("\r\n terminer " + bali + " " + " " + fali); 
          size = quadripl(sendBytes.Length.ToString()); //just for add the zero 
          Console.WriteLine("\r\n le size de fichier binair est " + size); 
          netStream.Write(Encoding.UTF8.GetBytes(size), 0, Encoding.UTF8.GetBytes(size).Length); 

          netStream.Write(sendBytes, 0, sendBytes.Length); 

         } while (bali != -1); //when we come to last part of the file (filebtobyte give -1 to bali) 
         bali = 0; 
         size = quadripl("0"); 
         Console.WriteLine("\r\n terminer fiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiin "); 
         netStream.Write(Encoding.UTF8.GetBytes(size), 0, Encoding.UTF8.GetBytes(size).Length); 
         netStream.Read(bs, 0, 4); 
         break; 
        case "s": 
         Console.WriteLine("\r\n comand string"); 
         netStream.Write(Encoding.UTF8.GetBytes(c), 0, 1); 
         size = quadripl(s.Length.ToString()); 
         sendBytes = Encoding.UTF8.GetBytes(size); 
         Console.WriteLine("\r\n size=" + size); 
         netStream.Write(sendBytes, 0, sendBytes.Length); 
         sendBytes = Encoding.UTF8.GetBytes(s); 
         netStream.Write(sendBytes, 0, sendBytes.Length); 

         if (sendfilcomand) 
         { 
          c = "b"; 
          goto case "b"; 
         } 
         break; 
        default: 
         Console.WriteLine("\r\n rien comand"); 
         break; 
       } 
      } 
      catch 
      { 
       Console.WriteLine("\r\n imposible de transfer"); 
      } 
     } 
     Console.Write("client est deconect \r\n "); 
    } 

//////////////////the functions////////////////////////////////// 

    public byte[] filebtobyte(string s) 
    { 
     byte[] byts = null; 
     try 
     { 
      if (fali - bali < sizeofonpacket) 
      { 
       byts = new byte[fali - bali]; 
       file.Read(byts, 0, fali - bali); 
       file.Close(); 
       bali = -1; 
      } 
      else 
      { 
       byts = new byte[sizeofonpacket]; 
       file.Read(byts, 0, sizeofonpacket); 
       bali += sizeofonpacket; 
      } 
     } 
     catch 
     { 
      Console.WriteLine("imposible de trouver le fichier"); 
     } 
     return byts; 
    } 
    public string quadripl(string s) 
    { 
     while (s.Length < 4) 
     { s = "0" + s; } 
     return s; 
    } 

    public string getitr() 
    { 
     StreamReader titrfil = new StreamReader("C:/Users/Ce-Pc/Desktop/titre.txt"); 
     string sss = ""; 
     try 
     { 
      sss = titrfil.ReadLine(); 
      Console.WriteLine("\r\n le chemin " + sss); 
      titrfil.Close(); 
     } 
     catch 
     { 
      Console.WriteLine("\r\n imposible"); 
     } 
     return sss; 
    } 
    public string actitr() 
    { 
     StreamReader titrfil = new StreamReader("C:/Users/Ce-Pc/Desktop/titreactuel.txt"); 
     string sss = ""; 
     try 
     { 
      sss = titrfil.ReadLine(); 
      Console.WriteLine("\r\n le chemin " + sss); 
      titrfil.Close(); 
     } 
     catch 
     { 
      Console.WriteLine("\r\n imposible"); 
     } 
     return sss; 
    } 
} 
+2

[这](https://stackoverflow.com/a/16001812/ 92546)的答案可能会流露出一些光芒。请注意'NetworkStream.Read'返回读取的字节数。你似乎不在乎,只是假设你会得到你想要的。当你在不同的机器上运行客户机和服务器时,它们之间会存在一个真正的网络,这些网络之间往往会分割大量的传输数据,而这些数据可能并不明显,只是在一个只是混洗缓冲区的系统上运行。 – HABO

+0

谢谢你的回答 ,但我认为tcp协议保证发送信息 –

+0

当你使用'netStream.Read(b,0,4);'而没有得到返回值,你怎么知道四个字节被读取? 'netStream.Read(b,0,size);'会造成更多问题。当大小超过约1500字节的典型以太网帧大小时,会出现碎片。尝试将数据包的大小限制在较小的值,例如1200字节。然后拿到一份[WireShark](https://www.wireshark.org/),看看机器之间真正的移动。 – HABO

回答

0

你检查两台机器之间的防火墙?

尝试从客户端PC上的命令提示符下Telnet测试连接到端口的服务器PC上:

telnet <server ip> 3568 

如果失败,有在网络层面的问题(可能是防火墙有关)。

此外,仔细检查正在使用同一端口的客户端和服务器(你不显示在上面的代码服务器端口)

+0

不,我不小心它是防火墙 因为发送字符串是worck 而且小写字母可以发送但if它是一个大锉刀 它不发送文件的所有数据 –

0

您的代码被切断,我不知道你把什么,所以我无法准确预测答案。这里有4个可能的答案:

请仔细阅读整个回答

  • 防火墙可能阻止连接(如瑞安提到)。您可以在控制面板中禁用它
  • 请确保您输入了正确的服务器地址以启动TCP侦听器(并且从不使用本地默认IP:127.0.0.1)。要找到正确的IP地址,请打开cmd,在“无线LAN适配器Wi-Fi:”部分中键入'ipconfig',复制Ipv4地址。对于客户端,您必须输入从其他机器生成的Ipv4地址。 Ipv4以黄色突出显示。 enter image description here

  • 如果两种解决方案都不起作用,那么我不得不问你他们是否在同一个无线网络中。如果没有,那么如果你是从互联网上的现场服务器运行而不是在路由器上运行,那么它不会工作(当然)。

  • 如果它不是客户端/服务器中的错误,那么它必须与您的代码发送/接收。通过互联网发送字节[]并不能保证对方将整体接收(它被分成小包),你的代码必须知道什么时候开始接收和何时停止接收。您可以在数据的开头添加一个小标题,它会告诉文件有多长,剩下多少字节需要读取。


更新:

你想通过小片来接收数据作为一个整体,而不是。所以我创造了一些功能,可以帮助您发送和接收数据更容易:

static void sendMessage(string c_1) 
    { 
     byte[] command = Encoding.ASCII.GetBytes(c_1); 
     byte[] commandLength = Encoding.ASCII.GetBytes(command.Length.ToString()); 
     List<byte> commandLengthInByteArray = commandLength.ToList(); 
     while (true) 
     { 
      if (commandLengthInByteArray.ToArray().Length < 50) 
      { 
       commandLengthInByteArray.Add(Convert.ToByte('x')); 
      } 
      else 
      { 
       break; 
      } 
     } 
     byte[] parsedCommandLength = commandLengthInByteArray.ToArray(); 
     sck.Send(parsedCommandLength); 
     sck.Send(command); 
    } 
    static void sendMessage_ftp(byte[] data) 
    { 
     byte[] commandLength = Encoding.ASCII.GetBytes(data.Length.ToString()); 
     List<byte> commandLengthInByteArray = commandLength.ToList(); 
     while (true) 
     { 
      if (commandLengthInByteArray.ToArray().Length < 50) 
      { 
       commandLengthInByteArray.Add(Convert.ToByte('x')); 
      } 
      else 
      { 
       break; 
      } 
     } 
     byte[] parsedCommandLength = commandLengthInByteArray.ToArray(); 
     sck.Send(parsedCommandLength); 
     sck.Send(data); 
    } 

static byte[] getResponse(Socket sck) 
    { 
     byte[] CommandLengthInByteArray = ReadBytes(50, sck); 
     List<byte> commandLengthInByteArrayList = new List<byte>(); 
     foreach (byte b in CommandLengthInByteArray) 
     { 
      if (b.ToString() != "120") 
      { 
       commandLengthInByteArrayList.Add(b); 
      } 
     } 
     Int32 fileSize = Convert.ToInt32(Encoding.ASCII.GetString(commandLengthInByteArrayList.ToArray())); 
     byte[] data = ReadBytes(fileSize, sck); 
     return data; 
    } 
    static byte[] ReadBytes(Int32 size, Socket sck) 
    { 
     //The size of the amount of bytes you want to recieve, eg 1024 
     var bytes = new byte[size]; 
     Int32 total = 0; 
     do 
     { 
      var read = sck.Receive(bytes, total, size - Convert.ToInt32(total), SocketFlags.None); 
      if (read == 0) 
      { 
       //If it gets here and you received 0 bytes it means that the Socket has Disconnected gracefully (without throwing exception) so you will need to handle that here 
      } 
      total += read; 
      //If you have sent 1024 bytes and Receive only 512 then it wil continue to recieve in the correct index thus when total is equal to 1024 you will have recieved all the bytes 
     } while (total != size); 
     return bytes; 
    } 

如何使用它:

  • 要发送短信:sendMessage("SomeTextHere");
  • 要发送的文件(> 1 GB)sendMessage_ftp(File.ReadAllBytes(@"C:\Users\StackExchange\Desktop\Image.png"));

  • 接收整个文件或文本(不是我的作品):

    byte[] messageOrFile = getResponse(sck);


但是...

你必须摆脱使用TcpClient,转而使用System.Net.Sockets

您必须:

  • 替换:TcpClient client;Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

  • 替换:client = listiner.AcceptTcpClient();client = listiner.AcceptSocket();

+0

在服务器端设置IP也很重要 - 它可以是0.0.0.0或它自己的IP地址(与客户端程序中输入的IP地址相同),它不应该设置为127.0.0.1或客户端计算机的地址。 –

+0

这不是一个防火墙或IP错误的客户端和服务器连接 和我的代码知道什么时候开始接收和何时停止接收,因为即使是大的fille(50 MB)可以发送如果我在同一台机器 客户端可以发送字符串和小fille 问题是当我发送文件的大数据在这种情况下数据不发送corectly –

+0

@MadaraItachi我看到你的问题。再看看我的解决方案! – Adola

相关问题