2017-05-26 28 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

相關問題