【问题标题】:Why has the server stopped responding after a change in source code?为什么更改源代码后服务器停止响应?
【发布时间】:2020-06-13 11:18:48
【问题描述】:

我需要通过 TCP 实现 HTTP 协议。我已经有了一个运行良好的 TCP/IP 客户端-服务器程序。

现在,我对源代码做了一些小的改动,使它的行为类似于an HTTP client-server。但是,不幸的是它停止了工作。

以下代码...

    public void Write(string str)
    {
        if (IsConnected)
        {
            byte[] strBytes = Encoding.UTF8.GetBytes(str);
            byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
            Array.Reverse(lenBytes);
            writer.Write(lenBytes);
            writer.Write(strBytes);
            writer.Flush();
        }
        else
        {
            throw new Exception("Client " + ID + " is not connected!");
        }
    }

    public string Read()
    {
        if (IsConnected)
        {
            byte[] lenBytes = reader.ReadBytes(4);
            Array.Reverse(lenBytes);
            int len = BitConverter.ToInt32(lenBytes, 0);
            byte[] bytes = reader.ReadBytes(len);
            string str = Encoding.UTF8.GetString(bytes);

            return str;
        }
        else
        {
            throw new Exception("Client " + ID + " is not connected!");
        }
    }

改为:

    public void Write(string str)
    {
        if (IsConnected)
        {
            byte[] send = Encoding.ASCII.GetBytes(str);
            writer.Write(send);
            writer.Flush();
        }
        else
        {
            throw new Exception("Client " + ID + " is not connected!");
        }
    }

    public string Read()
    {
        if (IsConnected)
        {
            StreamReader sr = new StreamReader(stream);
            string str = sr.ReadToEnd();

            return str;
        }
        else
        {
            throw new Exception("Client " + ID + " is not connected!");
        }
    }

这里有什么问题?


详细的源代码

服务器程序和客户端程序都使用以下类。

修改:

namespace MyClientServer
{
    public class ClientClass
    {
        private string Host { get; set; }
        private int Port { get; set; }

        private bool IsConnected = false;

        public string ID { get; private set; }
        public TcpClient Tcp { get; private set; }

        NetworkStream stream;
        private StreamReader sr;
        private StreamWriter writer;

        public ClientClass()
        {
            Random rnd = new Random();
            ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
        }

        //constructor for server program.
        public ClientClass(TcpListener listener)
        {
            Tcp = listener.AcceptTcpClient();

            Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
            Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;

            IsConnected = true;

            stream = Tcp.GetStream();
            sr = new StreamReader(stream);
            writer = new StreamWriter(stream);

            ID = Read();

            Console.WriteLine("Client [{0}] is now connected.", ID);

        }

        public bool Connect()
        {
            if (IsConnected == false)
            {
                Console.WriteLine("Client [{0}] is now connected.", ID);

                IsConnected = true;

                Tcp = new TcpClient(Host, Port);

                stream = Tcp.GetStream();
                sr = new StreamReader(stream);
                writer = new StreamWriter(stream);

                return true;
            }

            return false;
        }

        //constructor for client.
        public ClientClass(string host, int port)
        {
            Random rnd = new Random();
            ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
            Host = host;
            Port = port;
        }

        public void Write(string str)
        {
            if (IsConnected)
            {
                byte[] send = Encoding.ASCII.GetBytes(str);
                writer.Write(send);
                writer.Flush();
            }
            else
            {
                throw new Exception("Client " + ID + " is not connected!");
            }
        }

        public string Read()
        {
            if (IsConnected)
            {
                StreamReader sr = new StreamReader(stream);
                string str = sr.ReadToEnd();

                return str;
            }
            else
            {
                throw new Exception("Client " + ID + " is not connected!");
            }
        }

        public void PrintID()
        {
            Console.WriteLine("Client ID = {0}", ID);
        }

        public void SendIdToServer()
        {
            this.Write(ID);
        }

        public bool Disconnect()
        {
            if (IsConnected)
            {
                if (Tcp != null)
                {
                    Tcp.Close();
                    Tcp = null;

                    Console.WriteLine("\nClient [{0}] is now disconnected.", ID);

                    return true;
                }
            }

            return false;
        }        
    }
}

原文:

namespace MyClientServer
{
    public class ClientClass
    {
        private string Host { get; set; }
        private int Port { get; set; }

        private bool IsConnected = false;

        public string ID { get; private set; }
        public TcpClient Tcp { get; private set; }

        private BinaryReader reader;
        private BinaryWriter writer;

        public ClientClass()
        {
            Random rnd = new Random();
            ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
        }

        //constructor for server program.
        public ClientClass(TcpListener listener)
        {
            Tcp  = listener.AcceptTcpClient();

            Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
            Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;

            IsConnected = true;

            NetworkStream stream = Tcp.GetStream();
            reader = new BinaryReader(stream);
            writer = new BinaryWriter(stream);

            ID = Read();

            Console.WriteLine("Client [{0}] is now connected.", ID);

        }

        public bool Connect()
        {
            if (IsConnected == false)
            {
                Console.WriteLine("Client [{0}] is now connected.", ID);

                IsConnected = true;

                Tcp = new TcpClient(Host, Port);

                NetworkStream stream = Tcp.GetStream();
                reader = new BinaryReader(stream);
                writer = new BinaryWriter(stream);

                return true;
            }

            return false;
        }

        //constructor for client.
        public ClientClass(string host, int port)
        {
            Random rnd = new Random();
            ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
            Host = host;
            Port = port;
        }

        public void Write(string str)
        {
            if (IsConnected)
            {
                byte[] strBytes = Encoding.UTF8.GetBytes(str);
                byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
                Array.Reverse(lenBytes);
                writer.Write(lenBytes);
                writer.Write(strBytes);
                writer.Flush();
            }
            else
            {
                throw new Exception("Client " + ID + " is not connected!");
            }
        }

        public string Read()
        {
            if (IsConnected)
            {
                byte[] lenBytes = reader.ReadBytes(4);
                Array.Reverse(lenBytes);
                int len = BitConverter.ToInt32(lenBytes, 0);
                byte[] bytes = reader.ReadBytes(len);
                string str = Encoding.UTF8.GetString(bytes);

                return str;
            }
            else
            {
                throw new Exception("Client " + ID + " is not connected!");
            }
        }

        public void PrintID()
        {
            Console.WriteLine("Client ID = {0}", ID);
        }

        public void SendIdToServer()
        {
            this.Write(ID);
        }

        public bool Disconnect()
        {
            if (IsConnected)
            {
                if (Tcp != null)
                {
                    Tcp.Close();
                    Tcp = null;

                    Console.WriteLine("\nClient [{0}] is now disconnected.", ID);

                    return true;
                }
            }

            return false;
        }
    }
}

【问题讨论】:

  • Windows 中的流在关闭之前不会结束。当它用于读取文件时,Windows 将关闭流。当一个流用于连接两个进程时,一个进程需要关闭流。当流与 TCP 一起使用时,流在连接关闭时关闭。
  • 为什么是Encoding.ASCII.GetBytes(str)? ASCII 编码器能理解这里所有的字符串内容吗?阅读器还将 StreamReader 初始化为 StreamReader sr = new StreamReader(stream);,它假定 UTF8 编码(NO-BOM,因此不检查。)。
  • @Jimi, Why Encoding.ASCII.GetBytes(str)? --- 因为,HTTP 使用简单的文本,,,,, 读者还初始化了StreamReader as StreamReader sr = new StreamReader(stream);,它假定 UTF8 编码(NO-BOM,因此它不检查。)。 --- UTF8 在新代码中完全删除。
  • 不,您在新代码中有StreamReader sr = new StreamReader(stream);。 StreamReader 假设 Stream 是 UTF-8 编码的。如果所有字符都被限制在 ASCII 表中,那么读者和作者两者可以交谈。如果是这种情况,那么在 StreamReader 构造函数中指定 ASCII 编码(我没有阅读所有其余部分 - 这是我书中的游戏终结者)。我不知道什么是简单文本。您通过 HTTP 连接发送字节。

标签: c# http tcpclient tcplistener


【解决方案1】:

我听取了@Jimi的建议,也看了this link的源码。

现在我的源代码如下所示:

    public string Read()
    {
        if (IsConnected)
        {
            byte[] buffer = new byte[Tcp.ReceiveBufferSize];//create a byte array
            int bytesRead = stream.Read(buffer, 0, Tcp.ReceiveBufferSize);//read count
            string str = Encoding.ASCII.GetString(buffer, 0, bytesRead);//convert to string
            return str;
        }
        else
        {
            throw new Exception("Client " + ID + " is not connected!");
        }
    }

    public void Write(string str)
    {
        if (IsConnected)
        {
            byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(str);
            stream.Write(bytesToSend, 0, bytesToSend.Length);
            stream.Flush();
        }
        else
        {
            throw new Exception("Client " + ID + " is not connected!");
        }
    }

而且,它工作正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多