如何让客户端和服务器保持联系

时间:2019-05-27 09:45:52

标签: .net sockets tcp serversocket

我正在尝试使用.net套接字构建自己的异步客户端/服务器应用。

使用这两个示例,基本功能起作用。

Server

Client

此示例在连接后向服务器发送一个字符串,服务器回复并回显它收到的字符串,然后返回给客户端。

此回复后,客户端将关闭。

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

在我的场景中,我尝试连接到服务器,然后通过用户输入从客户端将数据发送到服务器。我回覆<OK>

在上面链接的此示例中,客户端在发送后始终等待回调(因此,我的回复<OK>)。

我没有像示例中那样关闭客户端,因为我想按需发送连续的字符串。我需要服务器继续侦听和回复以确认收到字符串。

我很确定我对应该发生和不应该发生的事情缺少一些核心了解。

现在,我可以发送一个字符串,服务器会回复,客户端会收到此<ok>。然后,我尝试发送另一个字符串,但是服务器从不“接收”该字符串。我猜服务器现在在发送字符串后也正在等待回调,但是如果我在接收到客户端之后将某些东西返回给服务器,那么整个循环会继续并重复吗?

在回复“确定”后,如何使服务器等待更多“新”数据?

我是否必须告诉它再次“收听”任何新数据?好像是重新启动连接,这不是我的意图...

我希望能对我在这里缺少的东西有所了解...

(PS服务器在发送时连接了回调事件。我这样保留它,因为这是我链接,实现的代码示例。我是否必须更改服务器的发送例程?(不等待回调)?

我的服务器代码:

          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 = ipHostInfo.AddressList[1];

            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
            xServerLog.AddLine("Server started: Listening on: " + localEndPoint.Address.ToString());
            xServerLog.ipAddress = localEndPoint.Address.ToString();
            xServerLog.port = port;

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

            // Bind the socket to the local endpoint and listen for incoming connections.  
            try
            {
                myTCPserver.Bind(localEndPoint);
                myTCPserver.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...");

                    xServerLog.AddLine("Waiting for connections...");

                    myTCPserver.BeginAccept(
                        new AsyncCallback(AcceptCallback),
                        myTCPserver);

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

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

            Console.WriteLine("\nPress ENTER to continue...");
            xServerLog.AddLine("I think things are done here...");

         //   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);

            if (bytesRead > 0)
            {
                // There  might be more data, so store the data received so far.  
                state.sb.Append(Encoding.ASCII.GetString(
                    state.buffer, 0, 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("Read {0} bytes from socket. \n Data : {1}",
                    //    content.Length, content);

                    xServerLog.AddLine("RX:" + content);


                    // Echo the data back to the client.  
                    Send(handler, "<OK>");
                }
                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, 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, 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);

                xServerLog.AddLine("TX:OK"); // + bytesSent.ToString() + " bytes to client");

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

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

        public void Start()
        {
            StartListening();
            //  return 0;
        }

我的客户代码

  class xtcpClient
{

    // State object for receiving data from remote device.  
    public class StateObject
    {
        // Client socket.  
        public Socket workSocket = null;
        // Size of receive buffer.  
        public const int BufferSize = 256;
        // Receive buffer.  
        public byte[] buffer = new byte[BufferSize];
        // Received data string.  
        public StringBuilder sb = new StringBuilder();
    }

    public class AsynchronousClient
    {
        //remote ip port
        //  private static string remoteServerIP = "0.0.0.1";

        private static IPAddress rIP;// = IPAddress.Parse(remoteServerIP);
        private static IPEndPoint remoteEP; // = new IPEndPoint(rIP, port);

        // Create a TCP/IP socket.  
        private static Socket myTCPClient; // = new Socket(rIP.AddressFamily,SocketType.Stream, ProtocolType.Tcp);

        // The port number for the remote device.  
        private static 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;

        private static string serverResponse = string.Empty;

        private static void _open_client()
        {

            remoteEP = new IPEndPoint(rIP, port);

            myTCPClient = new Socket(rIP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

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

        //////////private static void StartClient(IPAddress remoteIP, int remotePort)
        //////////{
        //////////    // Connect to a remote device.  
        //////////    try
        //////////    {
        //////////        _open_client();
        //////////        //rIP = remoteIP;
        //////////        //port = remotePort;

        //////////        // 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 = ipHostInfo.AddressList[1];

        //////////        // Send test data to the remote device.  
        //////////        //   string sendReply = "";

        //////////        //  sendReply = Send(myTCPClient, "echo 123<EOF>"); //send an initial test echo 
        //////////        //   xClientLog.AddLine("Sent: Echo<EOF>");
        //////////        //  xClientLog.AddLine("Server Replied: " + sendReply);

        //////////        // Write the response to the console.  
        //////////        //  Console.WriteLine("Response received : {0}", response);
        //////////        //  xClientLog.AddLine("Response received: " + response);

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

        public void _close_connection()
        {
            // Release the socket.  
            myTCPClient.Shutdown(SocketShutdown.Both);
            myTCPClient.Close();
        }
        private static string Send(Socket client, String data)
        {

            if (client is null)
            {
                _open_client();
            }


            // 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, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), client); //fire sendcallback when done sending...

            sendDone.WaitOne();

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

            return serverResponse; //return server response

        }
        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("Sent {0} bytes to server.", bytesSent);
                xClientLog.AddLine("Sent bytes to server: " + bytesSent);


                // Signal that all bytes have been sent.  
                sendDone.Set(); //signal the send event to finish, it will start listening for a reply...
            }
            catch (Exception e)
            {
                Console.WriteLine(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("Socket connected to {0}",
                    client.RemoteEndPoint.ToString());
                xClientLog.AddLine("Socket connected to: " + client.RemoteEndPoint.ToString());

                // Signal that the connection has been made.  
                connectDone.Set();
            }
            catch (Exception e)
            {
                Console.WriteLine(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, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state); //fire receivcallback event when done receining
            }
            catch (Exception e)
            {
                Console.WriteLine(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, 0, bytesRead));

                    serverResponse = state.sb.ToString();
                    if (serverResponse.IndexOf("<OK>") > -1) {
                        // All the data has been read from the server
                        xClientLog.AddLine("RX:" + serverResponse);
                        receiveDone.Set();
                    }
                    else
                    {
                        // Get the rest of the data.  
                        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                            new AsyncCallback(ReceiveCallback), state);
                    }

                }

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



        //public static int Main(String[] args)
        //{
        //    StartClient();
        //    return 0;
        //}
        public void startClient(string remoteIP, int remotePort)
        {
            try
            {
                rIP = IPAddress.Parse(remoteIP);
                port = remotePort;

                _open_client();
            }
            catch (Exception e)
            {

                System.Windows.MessageBox.Show(e.Message + Environment.NewLine + e.InnerException.Message);
            }

        }
        public string sendData(string DataToSend)
        {
            return (Send(myTCPClient, DataToSend));
        }
    }
}

1 个答案:

答案 0 :(得分:0)

可能是因为服务器上的每个“接受呼叫”都接受一个新客户端。如果您想无限期地接受,您可以尝试这样的方法,以确保新客户始终有一个“接受接受”的电话:

while (true) {
var clientSocket = listeningSocket.Accept();
Task.Factory.StartNew(() => HandleClient(clientSocket));
}

客户端也有可能关闭连接。如果服务器使用Shutdown方法关闭Socket连接,并且已收到所有可用数据,则Receive方法将完成并且不返回任何内容。