在c#套接字中从服务器获取异常

本文关键字:服务器 获取 异常 套接字 | 更新日期: 2023-09-27 18:14:39

我用c#创建了一个简单的服务器和客户端程序。服务器将发送一个字符串数组到客户端,客户端将显示它,客户端将发送一个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 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.

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

在c#套接字中从服务器获取异常

在我看来,在您的服务器代码中,您在继续读取数据之前关闭TCP客户端。这就是你得到异常的原因。

同样,你正在尝试读取1024字节,但是客户端没有发送1024字节(除非客户端发送的字符串是来自用户的输入被编码成1024字节数组的可能性不大),所以服务器将简单地阻塞并且什么也不做,因为它正在等待客户端发送1024字节。

管理从/到流读写数据的一个好方法是通过BinaryReader和BinaryWriter类。

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

服务器:

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();
    }
}

在您拥有ClosedTcpClient(处置它)之后,您正在使用NetworkStream

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();
}       

tcpClient实现不可能的接口,最好在tcpClient中调用dispose方法

tcpClient.Dispose();
其他

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

关闭客户端不会关闭流。

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