Почему мой сервер получает меньше байтов, чем отправляет клиент?
У меня есть это Клиент-серверное приложение 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, но мой код блокируется, и я не нахожу ничего полезного