Member 14833590 Ответов: 2

Почему мой сервер получает меньше байтов, чем отправляет клиент?


У меня есть это Клиент-серверное приложение C#, и я начал с документации Microsoft Пример Асинхронного Клиентского Сокета | Microsoft Docs[^ Однако мне действительно нужно было изменить некоторые вещи, и мне нужно было бы, чтобы клиент отправил несколько сообщений на сервер, а также получил несколько обратно.
Начиная с нуля, например, я нахожусь в контроллере (который находится в клиенте) и отправляю это сообщение на сервер:
namespace client.ObjectHandler
{
    public class BaseHandler
    {
        private AsynchronousClient asynchronousClient;

        public static String username;

        public BaseHandler(AsynchronousClient asynchronousClient = null)
        {
            this.asynchronousClient = asynchronousClient ?? new AsynchronousClient();
        }

        public User findByUsername(String username)
        {
            StringBuilder Content = new StringBuilder();
            Content.Append("find user ");
            Content.Append(username);
            Content.Append(" <EOF>");

            Message message = new Message { Content = Content.ToString() };
            asynchronousClient.Send(message);
            asynchronousClient.sendDone.WaitOne();

            asynchronousClient.Receive();
            asynchronousClient.receiveDone.WaitOne();
            var result = asynchronousClient.response;
            return result.userContent;
        }
   
    }
}

следовательно, сервер должен выполнять операции(в моем случае доступ к базе данных и т. д.). Это клиентский код:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using core;
using System.IO;

namespace client
{
    public class AsynchronousClient
    {
        // The port number for the remote device.  
        private const int port = 9000;

        // ManualResetEvent instances signal completion.  
        public  ManualResetEvent connectDone =
            new ManualResetEvent(false);
        public  ManualResetEvent sendDone =
            new ManualResetEvent(false);
        public  ManualResetEvent receiveDone =
            new ManualResetEvent(false);

        // The response from the remote device.  
        public Message response = new Message();

        private Socket client;

        private IPHostEntry ipHostInfo;
        private IPAddress ipAddress;
        private IPEndPoint remoteEP;

        public AsynchronousClient()
        {
            // Establish the remote endpoint for the socket.  
            // The name of the
            // remote device is "localhost".  
            ipHostInfo = Dns.GetHostEntry("localhost");
            ipAddress = ipHostInfo.AddressList[0];
            remoteEP = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP socket.  
            client = new Socket(ipAddress.AddressFamily,
                    SocketType.Stream, ProtocolType.Tcp);

            // Connect to the remote endpoint.  
            client.BeginConnect(remoteEP,
                new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();

        }

        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.  
                Socket client = (Socket)ar.AsyncState;

                // Complete the connection.  
                client.EndConnect(ar);

                Console.WriteLine("Socket connected to {0}",
                    client.RemoteEndPoint.ToString());

                // Signal that the connection has been made.  
                connectDone.Set();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public void Receive()
        {
            try
            {
                // Create the state object.  
                StateObject state = new StateObject();
                state.workSocket = client;

                // Begin receiving the data from the remote device.  
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
                
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            
        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the state object and the client socket
                // from the asynchronous state object.  
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;

                // Read data from the remote device.  
                int bytesRead = client.EndReceive(ar);
               
                Message receivedMessage = new Message();

                if (bytesRead > 0)
                {
                    // There might be more data, so store the data received so far.  
                    
                    receivedMessage = (Message)Serializer.FromStream(new MemoryStream(state.buffer));
                    // Get the rest of the data.  
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReceiveCallback), state);
                }
                else
                {
                    // All the data has arrived; put it in response.  
                    
                    response = receivedMessage;
                    
                    // Signal that all bytes have been received.  
                    receiveDone.Set();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public void Send(Message message)
        {
            // Convert the string data to byte data using ASCII encoding.
            MemoryStream stream = Serializer.ToStream(message);
            byte[] byteData = stream.GetBuffer();

            // Begin sending the data to the remote device.  
            client.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), client);
        }

        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.  
                Socket client = (Socket)ar.AsyncState;

                // Complete sending the data to the remote device.  
                int bytesSent = client.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to server.", bytesSent);

                // Signal that all bytes have been sent.  
                sendDone.Set();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}

и код сервера:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using core;
using server;


public class AsynchronousSocketListener
{
    // Thread signal.  
    public static ManualResetEvent allDone = new ManualResetEvent(false);

    private IPHostEntry ipHostInfo;
    private IPAddress ipAddress;
    private IPEndPoint localEndPoint;

    private Socket listener;

    public AsynchronousSocketListener()
    {
        // Establish the local endpoint for the socket.  
        // The DNS name of the computer  
        // running the listener is "localhost".  
        ipHostInfo = Dns.GetHostEntry("localhost");
        ipAddress = ipHostInfo.AddressList[0];
        localEndPoint = new IPEndPoint(ipAddress, 9000);

        // Create a TCP/IP socket.  
        listener = new Socket(ipAddress.AddressFamily,
             SocketType.Stream, ProtocolType.Tcp);
    }

    public void StartListening()
    {
        // Bind the socket to the local endpoint and listen for incoming connections.  
        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(100);

            while (true)
            {
                // Set the event to nonsignaled state.  
                allDone.Reset();

                // Start an asynchronous socket to listen for connections.  
                Console.WriteLine("Waiting for a connection...");
                listener.BeginAccept(
                    new AsyncCallback(AcceptCallback),
                    listener);

                // Wait until a connection is made before continuing.  
                allDone.WaitOne();
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        Console.WriteLine("\nPress ENTER to continue...");
        Console.Read();

    }

    public static void AcceptCallback(IAsyncResult ar)
    {
        // Signal the main thread to continue.  
        allDone.Set();

        // Get the socket that handles the client request.  
        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);

        // Create the state object.  
        StateObject state = new StateObject();
        state.workSocket = handler;
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
            new AsyncCallback(ReadCallback), state);
    }

    public static void ReadCallback(IAsyncResult ar)
    {
        String content = String.Empty;

        // Retrieve the state object and the handler socket  
        // from the asynchronous state object.  
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;

        // Read data from the client socket.
        int bytesRead = handler.EndReceive(ar);
        
        Message receivedMessage = new Message();
        if (bytesRead > 0)
        {
            // There  might be more data, so store the data received so far.  
            
            receivedMessage = (Message)Serializer.FromStream(new MemoryStream(state.buffer));
            // Check for end-of-file tag. If it is not there, read
            // more data.  
            content = receivedMessage.Content;
            if (content.IndexOf("<EOF>") > -1)
            {
                // All the data has been read from the
                // client. Display it on the console.  
                Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
                    content.Length, content);
                HandleMessage.handle(handler, receivedMessage);
                // Echo the data back to the client.
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
               new AsyncCallback(ReadCallback), state);
                //Send(handler, receivedMessage);

            }
            else
            {
                // Not all data received. Get more.  
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReadCallback), state);
            }
        }
    }

    private static void Send(Socket handler, Message message)
    {
        // Convert the string data to byte data using ASCII encoding.
        MemoryStream stream = Serializer.ToStream(message);
        byte[] byteData = stream.GetBuffer();
        // Begin sending the data to the remote device.  
        handler.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), handler);
    }

    private static void SendCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.  
            Socket handler = (Socket)ar.AsyncState;

            // Complete sending the data to the remote device.  
            int bytesSent = handler.EndSend(ar);
            Console.WriteLine("Sent {0} bytes to client.", bytesSent);

            //handler.Shutdown(SocketShutdown.Both);
            //handler.Close();

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

  
}

и способ справиться с handlemessage в это:
using System;
namespace server
{
    public static class HandleMessage
    {
        private static BaseHandler baseHandler;

        public static void handle(Socket handler, Message message)
        {
            baseHandler = new BaseHandler();
            String[] received = message.Content.Split(' ');
            if(received[0].CompareTo("find") == 0)
            {
                if(received[1].CompareTo("user") == 0)
                {
                    var result = baseHandler.filterByUsername(received[2]);

                    Message sentMessage = new Message { userContent = result };
                    MemoryStream stream = Serializer.ToStream(sentMessage);
                    var bytesSent = handler.Send(stream.GetBuffer());
                    
                }
            }
        } 
    }
}


Что я уже пробовал:

Я попытался поставить сервер после отправки(обработчик, сообщение) beginReceive, но мой код блокируется, и я не нахожу ничего полезного

2 Ответов

Рейтинг:
2

Patrice T

Цитата:
Почему мой сервер получает меньше байтов, чем отправляет клиент?

У вас есть много частей кода на клиенте и сервере. Мой первый шаг-сузить круг поиска.
Я бы использовал анализатор пакетов для захвата трафика между клиентом и сервером.
Анализируя захват, вы увидите, где теряются символы.
Анализатор пакетов - Википедия[^]


Рейтинг:
0

Gerry Schmitz

Это протокол вопросов и ответов; вы, вероятно, выходите из синхронизации с вашим неподтвержденным отправлением. Транспортный уровень обрабатывает "буферизацию".