C# 套接字服务器/客户端无法从服务器发送消息

问题描述

我尝试构建一个简单的客户端服务器通信。客户端连接到服务器并发送消息。服务器接受客户端并读取消息。现在服务器应该回答,但这不起作用:(

仅当我关闭服务器端的发送方向时,客户端才会收到服务器应答。 但是我不想关闭任何东西,因为我想发送和接收更多消息。

我认为问题出在方法 Send()SendCallback()

中的服务器端

有人可以帮我吗?

代码是可运行的。)

服务器:

using System;
using System.Net;
using System.Net.sockets;
using System.Text;
using System.Threading;

namespace WebSocket
{
    
    // State object for reading client data asynchronously  
    public class StateObject
    {
        // Size of receive buffer.  
        public const int BufferSize = 1024;

        // Receive buffer.  
        public byte[] buffer = new byte[BufferSize];

        // Received data string.
        public StringBuilder sb = new StringBuilder();

        // Client socket.
        public Socket workSocket = null;
    }

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

        public AsynchronousSocketListener()
        {
        }

        public static void StartListening()
        {
            // Establish the local endpoint for the socket.  
            // The DNS name of the computer  
            // running the listener is "host.contoso.com".  
            // IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");  //ipHostInfo.AddressList[0];
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress,11000);

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

            // 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("[Server] 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($"[Server] {e.ToString()}");
            }

            Console.WriteLine("\n[Server] Press 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,StateObject.BufferSize,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);

            if (bytesRead > 0)
            {
                // There  might be more data,so store the data received so far.  
                state.sb.Append(Encoding.ASCII.GetString(state.buffer,bytesRead));

                // Check for end-of-file tag. If it is not there,read
                // more data.  
                content = state.sb.ToString();
                if (content.IndexOf("<EOF>") > -1)
                {
                    // All the data has been read from the
                    // client. display it on the console.  
                    Console.WriteLine("[Server] Read {0} bytes from socket. Data: {1}",content.Length,content);
                    // Echo the data back to the client.  
                    Send(handler,content); 
                }
                else
                {
                    // Not all data received. Get more.  
                    handler.BeginReceive(state.buffer,state);
                }
            }
        }

        private static void Send(Socket handler,String data)
        {
            // Convert the string data to byte data using ASCII encoding.  
            byte[] byteData = Encoding.ASCII.GetBytes(data);

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

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

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

                handler.Send(new byte[0xFF]);

                // Here is the Problem. It only works if I uncomment the following line. But then I receive an Error when I try to Send again.
                // handler.Shutdown(SocketShutdown.Send);
                // handler.Close();

                // Create the state object.  
                StateObject state = new StateObject();
                state.workSocket = handler;
                handler.BeginReceive(state.buffer,state);

            }
            catch (Exception e)
            {
                Console.WriteLine($"[Server] {e.ToString()}");
            }
            Console.WriteLine("[Server] End of SendCallback");
        }

        public static int Main(String[] args)
        {
            Thread client = new Thread(AsynchronousClient.StartClient);
            client.Start();
            StartListening();
            return 0;
        }
    }
}

客户:

using System;
using System.Net;
using System.Net.sockets;
using System.Threading;
using System.Text;

namespace WebSocket
{

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

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

        // The response from the remote device.  
        private static String response = String.Empty;

        public static void StartClient()
        {
            Console.WriteLine("[Client] Start...");
            // Connect to a remote device.  
            try
            {
                // Establish the remote endpoint for the socket.  
                // The name of the
                // remote device is "host.contoso.com".  
                //IPHostEntry ipHostInfo = Dns.GetHostEntry("host.contoso.com");
                IPAddress ipAddress = IPAddress.Parse("127.0.0.1");  //ipHostInfo.AddressList[0];
                IPEndPoint remoteEP = new IPEndPoint(ipAddress,port);




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

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

                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("\n[Client] ----------- New message -----------");

                    // Send test data to the remote device.
                    Send(client,$"This is a test<EOF>");
                    sendDone.WaitOne();

                    // Receive the response from the remote device.  
                    Receive(client);
                    receiveDone.WaitOne();

                    // Write the response to the console.  
                    Console.WriteLine("[Client] Response received: {0}",response);

                    Thread.Sleep(5000);


                }
                // Release the socket.  
                client.Shutdown(SocketShutdown.Both);
                client.Close();
               

            }
            catch (Exception e)
            {
                Console.WriteLine($"[Client] {e.ToString()}");
            }
        }

        private static 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("[Client] Socket connected to {0}",client.RemoteEndPoint.ToString());

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

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

                // Begin receiving the data from the remote device.  
                client.BeginReceive(state.buffer,new AsyncCallback(ReceiveCallback),state);
            }
            catch (Exception e)
            {
                Console.WriteLine($"[Client] {e.ToString()}");
            }
        }

        private static 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);

                if (bytesRead > 0)
                {
                    // There might be more data,so store the data received so far.  
                    state.sb.Append(Encoding.ASCII.GetString(state.buffer,bytesRead));

                    // Get the rest of the data.  
                    client.BeginReceive(state.buffer,state);
                }
                else
                {
                    // All the data has arrived; put it in response.  
                    if (state.sb.Length > 1)
                    {
                        response = state.sb.ToString();
                    }
                    // Signal that all bytes have been received.  
                    receiveDone.Set();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine($"[Client] {e.ToString()}");
            }
        }

        private static void Send(Socket client,String data)
        {
            // Convert the string data to byte data using ASCII encoding.  
            byte[] byteData = Encoding.ASCII.GetBytes(data);

            // Begin sending the data to the remote device.  
            client.BeginSend(byteData,client);
        }

        private static 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("[Client] Sent {0} bytes to server.",bytesSent);

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

我实际上使用 .NET 5.0

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)