0

基本上我制作了两个 C# 应用程序,一个客户端和一个服务器。客户端连接到服务器(通过套接字),然后发送一个包含一些文本的数据包,服务器应该回复。我的问题是:服务器仅在关闭时(ALT+F4)才发送(或客户端接收)响应数据包。我需要一些帮助。我将在这两个项目的源代码下方复制粘贴。客户:

public class StateObject
{
    public Socket skt = null;
    public const int BufferSize = 256;
    public byte[] buffer = new byte[BufferSize];
    public StringBuilder sb = new StringBuilder();
}

public class AsynchronousClient
{
    private const int port = 11000;
    private static ManualResetEvent connectDone =
        new ManualResetEvent(false);
    private static ManualResetEvent sendDone =
        new ManualResetEvent(false);
    private static ManualResetEvent receiveDone =
        new ManualResetEvent(false);
    private static String response = String.Empty;
    public static string command;
    public static Socket client;
    public static void StartClient()
    {
        try
        {
            IPHostEntry ipHostInfo = Dns.GetHostEntry(IPAddress.Parse("127.0.0.1"));
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
            client = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);
            client.BeginConnect(remoteEP,
                new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();
            while (true)
            {
                command = Console.ReadLine();
                if (command == "exit")
                {
                    Console.WriteLine("Terminating...");
                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                    Environment.Exit(0);
                }
                else
                {
                    Send(client, command + "<EOF>");
                    sendDone.WaitOne();
                    Receive(client);
                    receiveDone.WaitOne();
                    Console.WriteLine("Response received : {0}", ProcessResponse(response));
                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                }
                //Console.CancelKeyPress += (sender, e) =>
                //{
                //    Console.WriteLine("Terminating...");
                //    client.Shutdown(SocketShutdown.Both);
                //    client.Close();
                //    Environment.Exit(0);
                //};
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
    static public string ProcessResponse(string pkt)
    {
        string response = null;
        response = pkt.Replace("<EOF>","");
        return response;
    }
    private static void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            Socket client = (Socket)ar.AsyncState;
            client.EndConnect(ar);
            Console.WriteLine("Socket connected to {0}",
                client.RemoteEndPoint.ToString());
            connectDone.Set();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void Receive(Socket client)
    {
        try
        {
            StateObject state = new StateObject();
            state.skt = client;
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReceiveCallback), state);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.skt;
            int bytesRead = client.EndReceive(ar);
            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
            }
            else
            {
                if (state.sb.Length > 1)
                {
                    response = state.sb.ToString();
                }
                receiveDone.Set();
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void Send(Socket client, String data)
    {
        byte[] byteData = Encoding.ASCII.GetBytes(data);
        client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
    }

    private static void SendCallback(IAsyncResult ar)
    {
        try
        {
            Socket client = (Socket)ar.AsyncState;
            int bytesSent = client.EndSend(ar);
            Console.WriteLine("Sent {0} bytes to server.", bytesSent);
            sendDone.Set();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    public static int Main(String[] args)
    {
        StartClient();
        return 0;
    }

服务器:

public class Program
{
    public class StateObject
    {
        public Socket skt = null;
        public const int buffersize = 1024;
        public byte[] buffer = new byte[buffersize];
        public StringBuilder sb = new StringBuilder();
    }
    public class AsynchronousSocketListener
    {
        public static ManualResetEvent allDone = new ManualResetEvent(false);
        public AsynchronousSocketListener() { }
        public static Socket handler;
        public static void StartListening()
        {
            byte[] bytes = new Byte[1024];
            IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);

            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(100);
                while (true)
                {
                    allDone.Reset();
                    Console.WriteLine("Waiting for a connection...");
                    listener.BeginAccept(
                        new AsyncCallback(AcceptCallback),
                        listener);
                    allDone.WaitOne();
                }

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

            Console.WriteLine("\nPress ENTER to continue...");
            Console.Read();
        }
        public static void AcceptCallback(IAsyncResult ar)
        {
            allDone.Set();
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);
            StateObject state = new StateObject();
            state.skt = handler;
            handler.BeginReceive(state.buffer, 0, StateObject.buffersize, 0, new AsyncCallback(ReadCallback), state);
        }
        public static void ReadCallback(IAsyncResult ar)
        {
            String content = String.Empty;
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.skt;
            int bytesRead = handler.EndReceive(ar);

            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(
                state.buffer, 0, bytesRead));
                content = state.sb.ToString();
                if (content.IndexOf("<EOF>") > -1)
                {
                    Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, ProcessResponse(content));
                    Send(handler, content);
                }
                else
                {
                    handler.BeginReceive(state.buffer, 0, StateObject.buffersize, 0,
                    new AsyncCallback(ReadCallback), state);
                }
            }
        }
        private static void Send(Socket handler, String data)
        {
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
        }
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                handler = (Socket)ar.AsyncState;
                int bytesSent = handler.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to client.", bytesSent);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        static public string ProcessResponse(String pkt)
        {
            string response = null;
            response = pkt.Replace("<EOF>", "");
            return response;
        }
    }
    public static void Main(string[] args)
    {
        AsynchronousSocketListener.StartListening();
    }
}
4

1 回答 1

1

在您的客户接收回调中:

private static void ReceiveCallback(IAsyncResult ar)
{
    try
    {
        StateObject state = (StateObject)ar.AsyncState;
        Socket client = state.skt;
        int bytesRead = client.EndReceive(ar);
        if (bytesRead > 0)
        {
            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReceiveCallback), state);
        }
        else
        {
            if (state.sb.Length > 1)
            {
                response = state.sb.ToString();
            }
            receiveDone.Set();
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }
}

else除非套接字被显式关闭(或连接中存在某种其他错误),否则您永远不会掉入块中。因此receiveDone永远不会被设置,你的主循环只是卡在等待“响应”。

<EOF>如果您想在收到“完整消息”时对其进行处理,请在将当前字符串附加到缓冲区后检查您的值,如下所示:

            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

                // it's not a "response" unless it's terminated with "<EOF>" right?
                response = state.sb.ToString();
                if (response.IndexOf("<EOF>") != -1)
                {
                    state.sb.Clear();
                    receiveDone.Set();
                }
                else
                {
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReceiveCallback), state);
                }
            }
            else
            {
                if (state.sb.Length > 1)
                {
                    response = state.sb.ToString(); // this is a partial response, not terminated with "<EOF>"
                }
                receiveDone.Set();
            }

请注意,正在使用的响应机制非常有限,因为它会因为同时传入的多条消息而失败,例如:Hello<EOF> World!<EOF> 它将这两条消息视为一条长消息。(我意识到您的示例仅发送一条“消息”。)

除了“内容”消息之外,您几乎肯定将不得不在任何发送“控制”消息的实际应用程序中处理这种情况。要处理这个问题,您需要<EOF>使用 IndexOf() 并提取到该点的文本并处理该“完整消息”。之后,只要<EOF>仍然发现处理其他未决消息,您就会继续循环。您还必须从 StringBuilder 中删除那些已处理的完整消息,以便在<EOF>保留在原地,以便当部分消息进入时,新数据可以附加到现有数据中。这是因为您的数据在发送时也可能被拆分,从而导致接收到多个“块”数据,即使在您发送时它在逻辑上是一个“完整消息”。因此,一次发送可能会导致一次或多次接收,Complete Message<EOF>例如. 您的代码必须能够处理 TCP 通信的这些现实......Complete Message<EOF>

于 2013-05-15T19:36:32.700 回答