Получить ответ от сервера

Клиент подключается к серверу, отправляет ему любое сообщение и в ответ получает длинную строку. Код чтения ответа:

   byte[] buffer = new byte[1024];
   int bytesRead = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);

   string msg = Encoding.UTF8.GetString(buffer, 0, bytesRead);
   Console.WriteLine($"Answer: {msg}");

Понятно, что так он примет только первые 1024 байта. Как получить весь ответ, не увеличивая размер буфера? По-идее, цикл нужен. Но цикл виснет после нескольких итераций.
Код цикла:

   while (true)
   {
      byte[] buffer = new byte[1024];
      int bytesRead = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);

      if (bytesRead == 0)
      {
          Console.WriteLine("zero");
          break;
      }

      string msg = Encoding.UTF8.GetString(buffer, 0, bytesRead);
      Console.WriteLine($"Answer: {msg.Length}");
   }

Сервер:

namespace Server
{
    internal class Program
    {
        static void Main(string[] args)
        {
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 5555);
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            server.Bind(endPoint);
            server.Listen(1);
            while (true)
            {
                Socket client = server.Accept();
                Console.WriteLine($"{client.RemoteEndPoint} is connected");

                while (true)
                {
                    try
                    {
                        byte[] buffer = new byte[1024];
                        int bytesRead = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                        if (bytesRead == 0)
                        {
                            Console.WriteLine($"{client.RemoteEndPoint} is disconnected");
                            client.Shutdown(SocketShutdown.Both);
                            break;
                        }

                        string msg = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                        Console.WriteLine(msg);

                        string answer;
                        string fn = "info.json";
                        if (File.Exists(fn))
                        {
                            answer = File.ReadAllText(fn);
                        }
                        else
                        {
                            answer = "fuck off";
                        }
                        SendMessage(client, answer);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        Console.WriteLine($"{client.RemoteEndPoint} is disconnected");
                        client.Shutdown(SocketShutdown.Both);
                        break;
                    }
                }
            }

            server.Shutdown(SocketShutdown.Both);
        }

        private static void SendMessage(Socket client, string msg)
        {
            byte[] msgBytes = Encoding.UTF8.GetBytes(msg);
            client.Send(msgBytes);
        }
    }
}

Клиент:

namespace Client
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string ip = "127.0.0.1";
            int port = 5555;
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            client.Connect(ip, port);
            if (client.Connected)
            {
                while (true)
                {
                    string s = Console.ReadLine();
                    if (s == "")
                    {
                        break;
                    }
                    byte[] bytes = Encoding.UTF8.GetBytes(s);
                    client.Send(bytes);

                    byte[] buffer = new byte[1024];
                    int bytesRead = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);

                    string msg = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    Console.WriteLine($"Answer: {msg}");
                }

                client.Disconnect(false);
            }

            client.Shutdown(SocketShutdown.Both);
        }
    }
}

Блин, кажется разобрался :thinking: У клиента внешний цикл корявый.

Переписал вот так.
Сервер:

namespace Server
{
    internal class Program
    {
        static void Main(string[] args)
        {
            const int serverPort = 5555;
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, serverPort);
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            server.Bind(endPoint);
            server.Listen(1);

            Console.WriteLine($"Server started on port {serverPort}");

            while (true)
            {
                Socket client = null;
                try
                {
                    client = server.Accept();
                    Console.WriteLine($"{client.RemoteEndPoint} is connected");

                    byte[] buffer = new byte[1024];
                    int bytesRead = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                    if (bytesRead == 0)
                    {
                        Console.WriteLine("Zero bytes received");
                        DisconnectClient(client);
                        continue;
                    }

                    string msg = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
                    Console.WriteLine(msg);

                    string fn = "info.json";
                    string answer = File.Exists(fn) ? File.ReadAllText(fn) : "fuck off";
                    SendMessage(client, answer);

                    DisconnectClient(client);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    DisconnectClient(client);
                }
            }

            StopServer(server);
        }

        private static void SendMessage(Socket client, string msg)
        {
            byte[] msgBytes = Encoding.UTF8.GetBytes(msg);
            client.Send(msgBytes);
        }

        private static void DisconnectClient(Socket client)
        {
            Console.WriteLine($"{client.RemoteEndPoint} is disconnected");
            client.Shutdown(SocketShutdown.Both);
            client.Close();
        }

        private static void StopServer(Socket socket)
        {
            try
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                if (ex is SocketException)
                {
                    System.Diagnostics.Debug.WriteLine($"Socket error {(ex as SocketException).ErrorCode}");
                }
                socket.Close();
            }
        }
    }
}

Клиент:

namespace Client
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string ip = "127.0.0.1";
            int port = 5555;
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            client.Connect(ip, port);
            while (client.Connected)
            {
                string s = Console.ReadLine();
                if (s == "")
                {
                    break;
                }
                byte[] bytes = Encoding.UTF8.GetBytes(s);
                client.Send(bytes);

                MemoryStream mem = new MemoryStream();
                while (true)
                {
                    byte[] buffer = new byte[1024];
                    int bytesRead = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                    if (bytesRead == 0)
                    {
                        Console.WriteLine("zero");
                        break;
                    }

                    mem.Write(buffer, 0, bytesRead);
                }


                byte[] messageBytes = mem.GetBuffer();
                mem.Dispose();
                string msg = Encoding.UTF8.GetString(messageBytes, 0, messageBytes.Length);
                Console.WriteLine($"Answer: {msg}");

                client.Disconnect(false);
            }

            client.Shutdown(SocketShutdown.Both);

            Console.WriteLine("Press ENTER to EXIT...");
            Console.ReadLine();
        }
    }
}

Теперь работает. Только процедура остановки сервера какая-то странная. В данном случае до нее вообще не доходит (потому что цикл бесконечный). Но если переписать так чтобы доходило, выдаёт ошибку:


Запрос на отправку или получение данных  (when sending on a datagram socket using a sendto call) no address was supplied
Socket error 10057

Так а зачем серверу доходить туда )

Обычно их останавливают остановкой процесса/сервиса ОС, ну или Ctrl+C.

Непонятно кто и где. Надо смотреть стектрейс исключения.

Возможно ламерский врпрос.
Но нафига создавать ответ размером больше размера буфера?

Встречный ламерский вопрос :grin:
А как тогда передавать данные, которые намного больше размера буфера, например файл? :thinking: Ну или просто длинную строку, например JSON?

Ну как зачем? Ресурсы освободить :point_up: Если сервер гуёвый - должна быть возможность останавливать его без ошибок.

        private static void Run()
        {
            const int serverPort = 5555;
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, serverPort);
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            server.Bind(endPoint);
            server.Listen(0);

            StopServer(server);
        }

        private static void StopServer(Socket socket)
        {
            try
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                if (ex is SocketException)
                {
                    System.Diagnostics.Debug.WriteLine($"Socket error {(ex as SocketException).ErrorCode}");
                }
                socket.Close();
            }
        }

выдаёт:

Вызвано исключение: "System.Net.Sockets.SocketException" в System.dll
Запрос на отправку или получение данных  (when sending on a datagram socket using a sendto call) no address was supplied
Socket error 10057

стектрейс:


"server.exe" (CLR v4.0.30319: server.exe). Загружено "C:\Windows\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_ru_b77a5c561934e089\mscorlib.resources.dll". Сборка модуля выполнена без символов.
   в System.Net.Sockets.Socket.Shutdown(SocketShutdown how)
   в server.Program.StopServer(Socket socket) в H:\Projects\CSharp\server\server\Program.cs:строка 47