2015-09-27 36 views
0

我在c#中创建了一个简单的服务器和客户端程序。服务器将发送一个字符串数组给客户端,客户端将显示它,客户端将向服务器发送一个id,服务器将显示它。我的示例代码如下。当我运行它们时,服务器端出现异常。我已标记在我收到exception.My示例代码如下一行:在c#套接字中从服务器获取异常

服务器:

using System; 
using System.Collections.Generic; 
using System.Net; 
using System.Net.Sockets; 
using System.IO; 
using System.Text; 
using System.Xml.Serialization; 

namespace server 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
     TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234); 
     tcpListener.Start(); 
     while (true) 
     {      
      TcpClient tcpClient = tcpListener.AcceptTcpClient(); 
      byte[] data = new byte[1024]; 
      NetworkStream ns = tcpClient.GetStream(); 
      string[] arr1 = new string[] { "one", "two", "three" }; 
      var serializer = new XmlSerializer(typeof(string[])); 
      serializer.Serialize(tcpClient.GetStream(), arr1); 
      tcpClient.Close(); 

       int recv = ns.Read(data, 0, data.Length); //getting exception in this line 

      string id = Encoding.ASCII.GetString(data, 0, recv); 

      Console.WriteLine(id); 

      }    
     } 
    } 
} 

客户端:

using System; 
using System.Collections.Generic; 
using System.Net; 
using System.Net.Sockets; 
using System.IO; 
using System.Text; 
using System.Xml.Serialization; 

namespace Client 
{ 
    class Program 
    { 
     static void Main(string[] args) 
    { 
     try 
     { 
      byte[] data = new byte[1024]; 
      string stringData; 

      TcpClient tcpClient = new TcpClient("127.0.0.1", 1234); 
      NetworkStream ns = tcpClient.GetStream();    

      var serializer = new XmlSerializer(typeof(string[])); 
      var stringArr = (string[])serializer.Deserialize(tcpClient.GetStream()); 

      foreach (string s in stringArr) 
      { 
       Console.WriteLine(s); 
      } 

      string input = Console.ReadLine(); 
      ns.Write(Encoding.ASCII.GetBytes(input), 0, input.Length); 
      ns.Flush(); 


     } 
     catch (Exception e) 
     { 
      Console.Write(e.Message); 
     } 

     Console.Read(); 
    } 
} 
} 

我得到的例外是:

An unhandled exception of type 'System.ObjectDisposedException' occurred in System.dll 
    Additional information: Cannot access a disposed object. 

代码中有什么问题吗?我需要做什么来避免这种异常?

回答

0

在我看来,在你的服务器代码你关闭TCP客户端,您继续阅读数据之前。这就是你获得例外的原因。

此外,您正在尝试读取1024个字节,但客户端不会发送1024个字符(除非客户端发送的字符串不可能被用户输入的字符串编码为1024字节数组)服务器将会阻塞并且什么都不做,因为它正在等待客户端发送1024字节。

管理读/写数据流的一种好方法是通过BinaryReaderBinaryWriter类。

考虑下面的代码,以解决您的问题(它包含你的代码的一些改进):

服务器:

class Program 
{ 
    static void Main(string[] args) 
    { 
     TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234); 
     tcpListener.Start(); 
     while (true) 
     { 
      using (TcpClient tcpClient = tcpListener.AcceptTcpClient()) 
      { 

       using (var network_stream = tcpClient.GetStream()) 
       { 

        using (BinaryReader reader = new BinaryReader(network_stream)) 
        { 
         using (BinaryWriter writer = new BinaryWriter(network_stream)) 
         { 
          string[] arr1 = new string[] { "one", "two", "three" }; 

          writer.Write(arr1.Length); 

          foreach (var item in arr1) 
          { 
           writer.Write(item); 
          } 


          var id = reader.ReadString(); 

          Console.WriteLine("Id: " + id); 

         } 

        } 
       } 

      } 

     } 
    } 
} 

客户:

class Program 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      using (TcpClient tcpClient = new TcpClient("127.0.0.1", 1234)) 
      { 
       using (NetworkStream network_stream = tcpClient.GetStream()) 
       { 

        using (BinaryReader reader = new BinaryReader(network_stream)) 
        { 
         using (BinaryWriter writer = new BinaryWriter(network_stream)) 
         { 
          int number_of_strings = reader.ReadInt32(); 

          string[] lines = new string[number_of_strings]; 

          for(int i = 0 ; i < number_of_strings ; i++) 
          { 
           lines[i] = reader.ReadString(); //Store the strings if you want to 

           Console.WriteLine(lines[i]); 

          } 

          Console.WriteLine("Please input id:"); 

          string id = Console.ReadLine(); 

          writer.Write(id); 

         } 

        } 

       } 
      } 

     } 
     catch (Exception e) 
     { 
      Console.Write(e.Message); 
     } 

     Console.Read(); 
    } 
} 
+0

谢谢。有用 !!! – ACE

+0

另外一件事:如果我添加StreamWriter sWriter = new StreamWriter(tcpClient.GetStream());在客户端和StreamReader的结尾处reader1 = new StreamReader(tcpClient.GetStream()); 在你的给定代码的最后一行后面的服务器末尾,我在这条线上的服务器上收到一个异常。其实我试图发送文件名和文件大小从客户端到服务器,这就是为什么加入这一行。这里有什么不对吗?@Yacoub Massad – ACE

+0

我不确定。我不认为你应该有两个阅读器('BinaryReader'和'StreamReader')。你为什么需要这样做?使用'BinaryWriter'和'BinaryReader'。您可以使用这些对象将文件大小写入/读取为整数。另外,'BinaryWriter'有一个[overload](https://msdn.microsoft.com/en-us/library/ms143302(v = vs.110).aspx),允许你写byte []。用它来发送文件的内容。 'BinaryReader'具有相应的[重载](https://msdn.microsoft.com/en-us/library/ms143295(v = vs.110).aspx),它允许您读取二进制数据。 –

0

TcpClient的实施Idisposible接口最好是调用TcpClient的

tcpClient.Dispose(); 

其他

tcpClient.GetStream().Close(); 
tcpClient.Close(); 

关闭客户端不关闭流处理方法。

var serializer = new XmlSerializer(typeof(string[])); 
      serializer.Serialize(tcpClient.GetStream(), arr1); 
      tcpClient.GetStream().Close() 
      tcpClient.Close(); 
+0

收到此错误:“系统。 Net.Sockets.TcpClient.Dispose(布尔)“是由于其保护级别无法访问@Midhun Mundayadan – ACE

+0

@ACE你是否试过关闭Getstream –

+0

是的,得到同样的例外@Midhun Mundayadan – ACE

0

您正在使用NetworkStream你有ClosedTcpClient之后(其配置它)。见更新而下面:

while (true) 
{      
    var tcpClient = tcpListener.AcceptTcpClient(); 
    var data = new byte[1024]; 
    var arr1 = new string[] { "one", "two", "three" }; 

    var serializer = new XmlSerializer(typeof(string[])); 
    serializer.Serialize(tcpClient.GetStream(), arr1); 

    var ns = tcpClient.GetStream(); 
    var recv = ns.Read(data, 0, data.Length); //getting exception in this line 

    var id = Encoding.ASCII.GetString(data, 0, recv); 

    Console.WriteLine(id); 

    ns.Close(); 
    tcpClient.Close(); 
}  
+0

在这种情况下,我没有得到客户端控制台中的字符串数组输出@ d.moncada – ACE

+0

@ACE看到更新 –

+0

我geting相同的结果。不显示在客户端控制台上的字符串数组@D.moncada – ACE