Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# TCP客户端\服务器-客户端不';我不总是看书_C#_Tcp_Network Programming_Tcpclient_Networkstream - Fatal编程技术网

C# TCP客户端\服务器-客户端不';我不总是看书

C# TCP客户端\服务器-客户端不';我不总是看书,c#,tcp,network-programming,tcpclient,networkstream,C#,Tcp,Network Programming,Tcpclient,Networkstream,客户端代码: TcpClient client = new TcpClient(); NetworkStream ns; private void Form1_Load(object sender, EventArgs e) { try { client.Connect("127.0.0.1", 560); ns = client.GetStream(); byte[] buffer = ReadFully(ns, client.A

客户端代码:

TcpClient client = new TcpClient();
NetworkStream ns;
private void Form1_Load(object sender, EventArgs e)
{
    try
    {
        client.Connect("127.0.0.1", 560);
        ns = client.GetStream();
        byte[] buffer = ReadFully(ns, client.Available);

        //working with the buffer...
    }
    catch
    {
        //displaying error...
    }
}

public static byte[] ReadFully(NetworkStream stream , int initialLength)
{
    // If we've been passed an unhelpful initial length, just
    // use 32K.
    if (initialLength < 1)
    {
        initialLength = 32768;
    }

    byte[] buffer = new byte[initialLength];
    long read = 0;

    int chunk;
    while ((chunk = stream.Read(buffer, (int)read, buffer.Length - (int)read)) > 0)
    {
        read += chunk;

        // If we've reached the end of our buffer, check to see if there's
        // any more information
        if (read == buffer.Length)
        {
            int nextByte = stream.ReadByte();

            // End of stream? If so, we're done
            if (nextByte == -1)
            {
                return buffer;
            }

            // Nope. Resize the buffer, put in the byte we've just
            // read, and continue
            byte[] newBuffer = new byte[buffer.Length * 2];
            Array.Copy(buffer, newBuffer, buffer.Length);
            newBuffer[read] = (byte)nextByte;
            buffer = newBuffer;
            read++;
        }
    }
    // Buffer is now too big. Shrink it.
    byte[] ret = new byte[read];
    Array.Copy(buffer, ret, read);
    return ret;
}
    private static TcpListener tcpListener;
        private static Thread listenThread;
        private static int clients;
        static void Main(string[] args)
        {
            tcpListener = new TcpListener(IPAddress.Any, 560);
            listenThread = new Thread(new ThreadStart(ListenForClients));
            listenThread.Start();
        }

        private static void ListenForClients()
        {
            tcpListener.Start();
            Console.WriteLine("Server started.");

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = tcpListener.AcceptTcpClient();

                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private static void HandleClientComm(object client)
        {
            clients++;
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            ASCIIEncoding encoder = new ASCIIEncoding();
            Console.WriteLine("Client connected. ({0} connected)", clients.ToString());

            #region sendingHandler
            byte[] buffer = encoder.GetBytes(AddressBookServer.Properties.Settings.Default.contacts);

            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            #endregion
        }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace SimpleClient
{
    internal class Client
    {
        private static void Main(string[] args)
        {
            try
            {
                TcpClient client = new TcpClient();
                NetworkStream ns;
                client.Connect("127.0.0.1", 560);
                ns = client.GetStream();
                byte[] buffer = ReadNBytes(ns, 4);
                    // read out the length field we know is there, because the server always sends it.
                int msgLenth = BitConverter.ToInt32(buffer, 0);
                buffer = ReadNBytes(ns, msgLenth);

                //working with the buffer...
                ASCIIEncoding encoder = new ASCIIEncoding();
                string msg = encoder.GetString(buffer);
                Console.WriteLine(msg);
                client.Close();
            }
            catch
            {
                //displaying error...
            }
        }

        public static byte[] ReadNBytes(NetworkStream stream, int n)
        {
            byte[] buffer = new byte[n];
            int bytesRead = 0;

            int chunk;
            while (bytesRead < n)
            {
                chunk = stream.Read(buffer, (int) bytesRead, buffer.Length - (int) bytesRead);
                if (chunk == 0)
                {
                    // error out
                    throw new Exception("Unexpected disconnect");
                }
                bytesRead += chunk;
            }
            return buffer;
        }
    }
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SimpleServer
{
    class Server
    {
        private static TcpListener tcpListener;
        private static int clients;
        static void Main(string[] args)
        {
            tcpListener = new TcpListener(IPAddress.Any, 560);
            tcpListener.Start();
            Console.WriteLine("Server started.");

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = tcpListener.AcceptTcpClient();

                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private static void HandleClientComm(object client)
        {
            int clientCount = Interlocked.Increment(ref clients);
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            ASCIIEncoding encoder = new ASCIIEncoding();
            Console.WriteLine("Client connected. ({0} connected)", clientCount);

            #region sendingHandler
            byte[] buffer = encoder.GetBytes("Some Contacts as a string!");
            byte[] lengthBuffer = BitConverter.GetBytes(buffer.Length);
            clientStream.Write(lengthBuffer, 0, lengthBuffer.Length);
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            tcpClient.Close();
            #endregion
        }
    }
}

从代码中可以看到,我正在尝试将
AddressBookServer.Properties.Settings.Default.contacts
(一个字符串,不是空的)发送到连接的客户端

问题在于,有时(这是wierd部分)客户端接收到字符串,有时它在
ns.Read
行上一直被阻塞,等待接收某些内容

我尝试通过在
ns.Read
之后的行上放置断点进行调试,我发现当它不工作时,它永远不会到达该行,因此它不会接收服务器发送的消息

我的问题:我如何修复它


我的假设:服务器在客户端接收到消息之前发送消息,因此客户端从未接收到消息。

正如Mark Gravell指出的,这是一个框架问题。下面是一个简单的客户端和服务器,向您展示如何在消息上使用长度前缀来框显消息。请记住,这只是一个让您开始的示例。我不认为它是准备好的代码:

客户端代码:

TcpClient client = new TcpClient();
NetworkStream ns;
private void Form1_Load(object sender, EventArgs e)
{
    try
    {
        client.Connect("127.0.0.1", 560);
        ns = client.GetStream();
        byte[] buffer = ReadFully(ns, client.Available);

        //working with the buffer...
    }
    catch
    {
        //displaying error...
    }
}

public static byte[] ReadFully(NetworkStream stream , int initialLength)
{
    // If we've been passed an unhelpful initial length, just
    // use 32K.
    if (initialLength < 1)
    {
        initialLength = 32768;
    }

    byte[] buffer = new byte[initialLength];
    long read = 0;

    int chunk;
    while ((chunk = stream.Read(buffer, (int)read, buffer.Length - (int)read)) > 0)
    {
        read += chunk;

        // If we've reached the end of our buffer, check to see if there's
        // any more information
        if (read == buffer.Length)
        {
            int nextByte = stream.ReadByte();

            // End of stream? If so, we're done
            if (nextByte == -1)
            {
                return buffer;
            }

            // Nope. Resize the buffer, put in the byte we've just
            // read, and continue
            byte[] newBuffer = new byte[buffer.Length * 2];
            Array.Copy(buffer, newBuffer, buffer.Length);
            newBuffer[read] = (byte)nextByte;
            buffer = newBuffer;
            read++;
        }
    }
    // Buffer is now too big. Shrink it.
    byte[] ret = new byte[read];
    Array.Copy(buffer, ret, read);
    return ret;
}
    private static TcpListener tcpListener;
        private static Thread listenThread;
        private static int clients;
        static void Main(string[] args)
        {
            tcpListener = new TcpListener(IPAddress.Any, 560);
            listenThread = new Thread(new ThreadStart(ListenForClients));
            listenThread.Start();
        }

        private static void ListenForClients()
        {
            tcpListener.Start();
            Console.WriteLine("Server started.");

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = tcpListener.AcceptTcpClient();

                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private static void HandleClientComm(object client)
        {
            clients++;
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            ASCIIEncoding encoder = new ASCIIEncoding();
            Console.WriteLine("Client connected. ({0} connected)", clients.ToString());

            #region sendingHandler
            byte[] buffer = encoder.GetBytes(AddressBookServer.Properties.Settings.Default.contacts);

            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            #endregion
        }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace SimpleClient
{
    internal class Client
    {
        private static void Main(string[] args)
        {
            try
            {
                TcpClient client = new TcpClient();
                NetworkStream ns;
                client.Connect("127.0.0.1", 560);
                ns = client.GetStream();
                byte[] buffer = ReadNBytes(ns, 4);
                    // read out the length field we know is there, because the server always sends it.
                int msgLenth = BitConverter.ToInt32(buffer, 0);
                buffer = ReadNBytes(ns, msgLenth);

                //working with the buffer...
                ASCIIEncoding encoder = new ASCIIEncoding();
                string msg = encoder.GetString(buffer);
                Console.WriteLine(msg);
                client.Close();
            }
            catch
            {
                //displaying error...
            }
        }

        public static byte[] ReadNBytes(NetworkStream stream, int n)
        {
            byte[] buffer = new byte[n];
            int bytesRead = 0;

            int chunk;
            while (bytesRead < n)
            {
                chunk = stream.Read(buffer, (int) bytesRead, buffer.Length - (int) bytesRead);
                if (chunk == 0)
                {
                    // error out
                    throw new Exception("Unexpected disconnect");
                }
                bytesRead += chunk;
            }
            return buffer;
        }
    }
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SimpleServer
{
    class Server
    {
        private static TcpListener tcpListener;
        private static int clients;
        static void Main(string[] args)
        {
            tcpListener = new TcpListener(IPAddress.Any, 560);
            tcpListener.Start();
            Console.WriteLine("Server started.");

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = tcpListener.AcceptTcpClient();

                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private static void HandleClientComm(object client)
        {
            int clientCount = Interlocked.Increment(ref clients);
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            ASCIIEncoding encoder = new ASCIIEncoding();
            Console.WriteLine("Client connected. ({0} connected)", clientCount);

            #region sendingHandler
            byte[] buffer = encoder.GetBytes("Some Contacts as a string!");
            byte[] lengthBuffer = BitConverter.GetBytes(buffer.Length);
            clientStream.Write(lengthBuffer, 0, lengthBuffer.Length);
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            tcpClient.Close();
            #endregion
        }
    }
}
代码有时工作,有时失败的原因是客户端.Available可以返回0。当它执行时,您正在将字节设置为读取32k,因此读取调用正在等待这些字节进入。他们从来没有这样做过,而且由于服务器从未关闭套接字,所以read也不会出错

希望这能让你朝着正确的方向前进

编辑:

TcpClient client = new TcpClient();
NetworkStream ns;
private void Form1_Load(object sender, EventArgs e)
{
    try
    {
        client.Connect("127.0.0.1", 560);
        ns = client.GetStream();
        byte[] buffer = ReadFully(ns, client.Available);

        //working with the buffer...
    }
    catch
    {
        //displaying error...
    }
}

public static byte[] ReadFully(NetworkStream stream , int initialLength)
{
    // If we've been passed an unhelpful initial length, just
    // use 32K.
    if (initialLength < 1)
    {
        initialLength = 32768;
    }

    byte[] buffer = new byte[initialLength];
    long read = 0;

    int chunk;
    while ((chunk = stream.Read(buffer, (int)read, buffer.Length - (int)read)) > 0)
    {
        read += chunk;

        // If we've reached the end of our buffer, check to see if there's
        // any more information
        if (read == buffer.Length)
        {
            int nextByte = stream.ReadByte();

            // End of stream? If so, we're done
            if (nextByte == -1)
            {
                return buffer;
            }

            // Nope. Resize the buffer, put in the byte we've just
            // read, and continue
            byte[] newBuffer = new byte[buffer.Length * 2];
            Array.Copy(buffer, newBuffer, buffer.Length);
            newBuffer[read] = (byte)nextByte;
            buffer = newBuffer;
            read++;
        }
    }
    // Buffer is now too big. Shrink it.
    byte[] ret = new byte[read];
    Array.Copy(buffer, ret, read);
    return ret;
}
    private static TcpListener tcpListener;
        private static Thread listenThread;
        private static int clients;
        static void Main(string[] args)
        {
            tcpListener = new TcpListener(IPAddress.Any, 560);
            listenThread = new Thread(new ThreadStart(ListenForClients));
            listenThread.Start();
        }

        private static void ListenForClients()
        {
            tcpListener.Start();
            Console.WriteLine("Server started.");

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = tcpListener.AcceptTcpClient();

                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private static void HandleClientComm(object client)
        {
            clients++;
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            ASCIIEncoding encoder = new ASCIIEncoding();
            Console.WriteLine("Client connected. ({0} connected)", clients.ToString());

            #region sendingHandler
            byte[] buffer = encoder.GetBytes(AddressBookServer.Properties.Settings.Default.contacts);

            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            #endregion
        }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace SimpleClient
{
    internal class Client
    {
        private static void Main(string[] args)
        {
            try
            {
                TcpClient client = new TcpClient();
                NetworkStream ns;
                client.Connect("127.0.0.1", 560);
                ns = client.GetStream();
                byte[] buffer = ReadNBytes(ns, 4);
                    // read out the length field we know is there, because the server always sends it.
                int msgLenth = BitConverter.ToInt32(buffer, 0);
                buffer = ReadNBytes(ns, msgLenth);

                //working with the buffer...
                ASCIIEncoding encoder = new ASCIIEncoding();
                string msg = encoder.GetString(buffer);
                Console.WriteLine(msg);
                client.Close();
            }
            catch
            {
                //displaying error...
            }
        }

        public static byte[] ReadNBytes(NetworkStream stream, int n)
        {
            byte[] buffer = new byte[n];
            int bytesRead = 0;

            int chunk;
            while (bytesRead < n)
            {
                chunk = stream.Read(buffer, (int) bytesRead, buffer.Length - (int) bytesRead);
                if (chunk == 0)
                {
                    // error out
                    throw new Exception("Unexpected disconnect");
                }
                bytesRead += chunk;
            }
            return buffer;
        }
    }
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SimpleServer
{
    class Server
    {
        private static TcpListener tcpListener;
        private static int clients;
        static void Main(string[] args)
        {
            tcpListener = new TcpListener(IPAddress.Any, 560);
            tcpListener.Start();
            Console.WriteLine("Server started.");

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = tcpListener.AcceptTcpClient();

                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private static void HandleClientComm(object client)
        {
            int clientCount = Interlocked.Increment(ref clients);
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            ASCIIEncoding encoder = new ASCIIEncoding();
            Console.WriteLine("Client connected. ({0} connected)", clientCount);

            #region sendingHandler
            byte[] buffer = encoder.GetBytes("Some Contacts as a string!");
            byte[] lengthBuffer = BitConverter.GetBytes(buffer.Length);
            clientStream.Write(lengthBuffer, 0, lengthBuffer.Length);
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            tcpClient.Close();
            #endregion
        }
    }
}
我忘了在我原来的帖子里提到endianess。您可以在此处查看有关endianess和使用位转换器的文档:

基本上,您需要确保服务器和客户端都在具有相同endianess的体系结构上运行,或者根据需要处理从一个endianess到另一个endianess的转换

编辑2(回答评论中的问题):

TcpClient client = new TcpClient();
NetworkStream ns;
private void Form1_Load(object sender, EventArgs e)
{
    try
    {
        client.Connect("127.0.0.1", 560);
        ns = client.GetStream();
        byte[] buffer = ReadFully(ns, client.Available);

        //working with the buffer...
    }
    catch
    {
        //displaying error...
    }
}

public static byte[] ReadFully(NetworkStream stream , int initialLength)
{
    // If we've been passed an unhelpful initial length, just
    // use 32K.
    if (initialLength < 1)
    {
        initialLength = 32768;
    }

    byte[] buffer = new byte[initialLength];
    long read = 0;

    int chunk;
    while ((chunk = stream.Read(buffer, (int)read, buffer.Length - (int)read)) > 0)
    {
        read += chunk;

        // If we've reached the end of our buffer, check to see if there's
        // any more information
        if (read == buffer.Length)
        {
            int nextByte = stream.ReadByte();

            // End of stream? If so, we're done
            if (nextByte == -1)
            {
                return buffer;
            }

            // Nope. Resize the buffer, put in the byte we've just
            // read, and continue
            byte[] newBuffer = new byte[buffer.Length * 2];
            Array.Copy(buffer, newBuffer, buffer.Length);
            newBuffer[read] = (byte)nextByte;
            buffer = newBuffer;
            read++;
        }
    }
    // Buffer is now too big. Shrink it.
    byte[] ret = new byte[read];
    Array.Copy(buffer, ret, read);
    return ret;
}
    private static TcpListener tcpListener;
        private static Thread listenThread;
        private static int clients;
        static void Main(string[] args)
        {
            tcpListener = new TcpListener(IPAddress.Any, 560);
            listenThread = new Thread(new ThreadStart(ListenForClients));
            listenThread.Start();
        }

        private static void ListenForClients()
        {
            tcpListener.Start();
            Console.WriteLine("Server started.");

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = tcpListener.AcceptTcpClient();

                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private static void HandleClientComm(object client)
        {
            clients++;
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            ASCIIEncoding encoder = new ASCIIEncoding();
            Console.WriteLine("Client connected. ({0} connected)", clients.ToString());

            #region sendingHandler
            byte[] buffer = encoder.GetBytes(AddressBookServer.Properties.Settings.Default.contacts);

            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            #endregion
        }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace SimpleClient
{
    internal class Client
    {
        private static void Main(string[] args)
        {
            try
            {
                TcpClient client = new TcpClient();
                NetworkStream ns;
                client.Connect("127.0.0.1", 560);
                ns = client.GetStream();
                byte[] buffer = ReadNBytes(ns, 4);
                    // read out the length field we know is there, because the server always sends it.
                int msgLenth = BitConverter.ToInt32(buffer, 0);
                buffer = ReadNBytes(ns, msgLenth);

                //working with the buffer...
                ASCIIEncoding encoder = new ASCIIEncoding();
                string msg = encoder.GetString(buffer);
                Console.WriteLine(msg);
                client.Close();
            }
            catch
            {
                //displaying error...
            }
        }

        public static byte[] ReadNBytes(NetworkStream stream, int n)
        {
            byte[] buffer = new byte[n];
            int bytesRead = 0;

            int chunk;
            while (bytesRead < n)
            {
                chunk = stream.Read(buffer, (int) bytesRead, buffer.Length - (int) bytesRead);
                if (chunk == 0)
                {
                    // error out
                    throw new Exception("Unexpected disconnect");
                }
                bytesRead += chunk;
            }
            return buffer;
        }
    }
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SimpleServer
{
    class Server
    {
        private static TcpListener tcpListener;
        private static int clients;
        static void Main(string[] args)
        {
            tcpListener = new TcpListener(IPAddress.Any, 560);
            tcpListener.Start();
            Console.WriteLine("Server started.");

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = tcpListener.AcceptTcpClient();

                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private static void HandleClientComm(object client)
        {
            int clientCount = Interlocked.Increment(ref clients);
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            ASCIIEncoding encoder = new ASCIIEncoding();
            Console.WriteLine("Client connected. ({0} connected)", clientCount);

            #region sendingHandler
            byte[] buffer = encoder.GetBytes("Some Contacts as a string!");
            byte[] lengthBuffer = BitConverter.GetBytes(buffer.Length);
            clientStream.Write(lengthBuffer, 0, lengthBuffer.Length);
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
            tcpClient.Close();
            #endregion
        }
    }
}
1) 为什么client.available可以返回0

这是一个时间问题。客户端正在连接到服务器,然后立即询问哪些字节可用。根据正在运行的其他进程、可用处理器的时间片等,客户机可能会在服务器有机会发送任何内容之前询问可用的内容。在这种情况下,它将返回0

2) 为什么我要使用Interlocked来增加客户端

您最初编写的代码增加了新创建的线程中运行HandleClientComm(…)的客户端。如果两个或多个客户端同时连接,则当多个线程试图增加客户端时,可能会出现争用情况。最终的结果是,客户的收入将低于应有水平

3) 为什么我要随时改变方法

您的Readfull版本(我将其更改为ReadNBytes)接近正确,但存在一些缺陷:

  • 如果原始initialLength为零或更小,则将initialLenth设置为32768。永远不要猜测需要从套接字读取多少字节。正如MarkGravell提到的,您需要使用长度前缀或某种分隔符来框接消息
  • NetworkStream.Read阻塞直到读取了一些字节,或者如果套接字从下面关闭,则返回0。不需要调用stream.ReadByte,因为如果套接字断开连接,chunk就已经是0了。做出这样的更改简化了方法,特别是因为我们知道根据简单的头需要读取多少字节
  • 既然我们知道了要读多少书,我们就可以准确地预先分配我们需要的东西。这消除了在返回时重新调整缓冲区大小的必要性。我们可以把分配的东西退回
4) 我如何知道长度缓冲区大小是4

我序列化的长度是32位。您可以在BitConverter.GetBytes(int值)的文档中看到这一点。我们知道一个字节是8位,所以只要把32除以8,就得到4

5) 为什么这还没有准备好生产/如何改进代码

  • 基本上没有真正的错误处理。NetworkStream.Read()可以引发多个异常,我没有处理任何一个异常。添加正确的错误处理将大大有助于使其做好生产准备

  • 除了粗略的运行之外,我还没有真正测试过代码。它需要在各种条件下进行测试

  • 没有为客户端提供重新连接或重试的功能,尽管您可能不需要这样做

  • 这是作为一个简单的例子编写的,实际上可能无法满足您试图满足的需求。由于不了解这些需求,我不能说这适合您的生产环境(不管是什么)

  • 从概念上讲,ReadNBytes是可以的,但是如果有人向您发送恶意消息,声称消息长度为2G字节或其他,您将尝试盲目地分配2G字节。大多数字节级协议(对传输内容的描述)指定消息的最大大小。这需要进行检查,如果消息实际上可能很大,则需要对其进行不同的处理,而不仅仅是分配缓冲区,可能是在读取时写入文件或其他输出流。同样,由于不知道您的全部要求,我无法确定那里需要什么


希望这能有所帮助。

首先,您的
Read
呼叫中断。您假设您将一次性读取整个内容,并且忽略返回值。你不应该做这两件事。我是网络编程新手,你能用固定的代码和解释来回答吗?是的,就是这样。“读取操作读取尽可能多的可用数据,最多读取大小参数指定的字节数。”至于修复它,如果不了解您的协议,就很难做到这一点。客户应该怎么做