使用C#中的套接字在同一会话中发送多个消息,接收多个答案

时间:2018-11-02 21:56:01

标签: c# wpf sockets

在发布自己之前,我到处都在寻找这个问题的答案。我尝试过的一切对我来说都没有用。对于这个项目,我正在使用带有套接字的客户端-服务器模型在WPF中构建MasterMind游戏。建立连接后,服务器将随机选择一个答案,并处理用户所作的猜测。但是由于某种原因,只有第一个猜测才能正确通过该过程。此后,第二个猜测将返回与第一个猜测相同的响应-似乎是异常导致客户端返回了它从服务器接收到的前一个响应-而此后的猜测仅引发了一个不同的异常,表明该异常连接已关闭。我知道我的客户端没有关闭它,但是我不知道如何使服务器保持连接活动。我添加了一个“ keepAlive”选项,并且尝试了所有我所能找到的没有运气的东西。我在这里发布了相关的类,但是如果您想要完整的源代码并尝试实际运行它,则可以从我的github下载它:https://github.com/calewis1995/Games/tree/master/MasterMind2.0

这是我的服务器:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace MMServer {
    public class MMServer {
        public static ManualResetEvent allDone = new ManualResetEvent(false);
        private static MasterMind masterMind = null;

        public MMServer() {}

        public static void Main(string[] args) {
            StartListening();            
        }

        public static void StartListening() {
            // Establish the local endpoint for the socket. 
            IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

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

            // 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.Read();
            }

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

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

            Socket listener = (Socket)ar.AsyncState;            
            Socket handler = listener.EndAccept(ar);            
            masterMind = new MasterMind();
            ServerStateObject state = new ServerStateObject {
                workSocket = handler
            };            
            handler.BeginReceive(state.buffer, 0, ServerStateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
        }

        public static void ReadCallback(IAsyncResult ar) {
            string content = string.Empty;
            ServerStateObject state = (ServerStateObject)ar.AsyncState;
            Socket handler = state.workSocket;

            // Read data from the client socket.   
            int bytesRead = handler.EndReceive(ar);
            handler.BeginReceive(state.buffer, 0, ServerStateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);

            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));
                content = state.sb.ToString();

                if (content.IndexOf("<EOF>") > -1) {
                    Console.WriteLine("Player's Guess: {0}", content);
                    string reply = masterMind.GetReply(content.Replace("<EOF>", ""));
                    Send(handler, reply);
                } else {
                    // Not all data received. Get more.  
                    handler.BeginReceive(state.buffer, 0, ServerStateObject.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 { 
                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.Close();
            } catch (Exception e) {
                Console.WriteLine(e.ToString());
                Console.Read();
            }
        }        
    }
}

这是我的客户:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;

namespace MasterMind2._0 {
    public class MMClient {
        // 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);
        private static Socket clientSocket = null;
        private static string response = string.Empty;

        public static void StartClient() {
            // Connect to a remote device.  
            try {
                // Establish the remote endpoint for the socket.
                IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

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

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

                // Write the response to the console.  
                Console.WriteLine("Response received : {0}", response);                
            } catch (Exception e) {
                Console.WriteLine(e.ToString());
            }
        }

        public static string SendGuessAndReceiveAnswer(string guess) {
            Send(clientSocket, guess + "<EOF>");
            sendDone.WaitOne();

            Receive(clientSocket);
            receiveDone.WaitOne();

            return response;
        }

        public static void Close() {
            // Release the socket.  
            clientSocket.Shutdown(SocketShutdown.Both);
            clientSocket.Close();
        }

        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());
                // 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.  
                ClientStateObject state = new ClientStateObject {
                    workSocket = client
                };

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

        private static void ReceiveCallback(IAsyncResult ar) {
            try {  
                ClientStateObject state = (ClientStateObject)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));

                    // Get the rest of the data.  
                    client.BeginReceive(state.buffer, 0, ClientStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), 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(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, 0, byteData.Length, 0, new AsyncCallback(SendCallback), 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("Sent {0} bytes to server.", bytesSent);
                // Signal that all bytes have been sent.  
                sendDone.Set();
            } catch (Exception e) {
                Console.WriteLine(e.ToString());
            }
        }
    }
}

这是WPF背后的c#,它与我的客户端套接字代码通信:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Drawing;
using MMServer;

namespace MasterMind2._0 {
    public partial class MainWindow : Window {
        private List<Ellipse> guessList;
        private List<Ellipse> responseList;
        private int ColorLimit { get; } = 4;
        private Ellipse ellipse = null;

        public MainWindow() {
            InitializeComponent();
            guessList = new List<Ellipse> { Guess1_1, Guess1_2, Guess1_3, Guess1_4,
                                            Guess2_1, Guess2_2, Guess2_3, Guess2_4,
                                            Guess3_1, Guess3_2, Guess3_3, Guess3_4,
                                            Guess4_1, Guess4_2, Guess4_3, Guess4_4,
                                            Guess5_1, Guess5_2, Guess5_3, Guess5_4,
                                            Guess6_1, Guess6_2, Guess6_3, Guess6_4,
                                            Guess7_1, Guess7_2, Guess7_3, Guess7_4,
                                            Guess8_1, Guess8_2, Guess8_3, Guess8_4,
                                            Guess9_1, Guess9_2, Guess9_3, Guess9_4,
                                            Guess10_1, Guess10_2, Guess10_3, Guess10_4,
                                            Guess11_1, Guess11_2, Guess11_3, Guess11_4,
                                            Guess12_1, Guess12_2, Guess12_3, Guess12_4};
            responseList = new List<Ellipse> { Response1_1, Response1_2, Response1_3, Response1_4,
                                               Response2_1, Response2_2, Response2_3, Response2_4,
                                               Response3_1, Response3_2, Response3_3, Response3_4,
                                               Response4_1, Response4_2, Response4_3, Response4_4,
                                               Response5_1, Response5_2, Response5_3, Response5_4,
                                               Response6_1, Response6_2, Response6_3, Response6_4,
                                               Response7_1, Response7_2, Response7_3, Response7_4,
                                               Response8_1, Response8_2, Response8_3, Response8_4,
                                               Response9_1, Response9_2, Response9_3, Response9_4,
                                               Response10_1, Response10_2, Response10_3, Response10_4,
                                               Response11_1, Response11_2, Response11_3, Response11_4,
                                               Response12_1, Response12_2, Response12_3, Response12_4};
            MMClient.StartClient();            
        }

        private void NewGameButton_Click(object sender, RoutedEventArgs e) {

        }

        private void SubmitButton_Click(object sender, RoutedEventArgs e) {
            int numOfColors = 0;
            string guess = "";

            foreach (Ellipse el in guessList) {
                if (el.IsEnabled && numOfColors < 4) {
                    System.Drawing.ColorConverter converter = new System.Drawing.ColorConverter();
                    System.Drawing.Color color = (System.Drawing.Color)converter.ConvertFromString(el.Fill.ToString());
                    KnownColor knownColor = color.ToKnownColor();
                    string colorString = knownColor.ToString();
                    guess += colorString + " ";
                    numOfColors++;
                    el.IsEnabled = false;
                }
            }
            guess = guess.TrimEnd(' ');
            string response = MMClient.SendGuessAndReceiveAnswer(guess).Replace("<EOF>", "");
            ProcessResponse(response);
        }

        private void ProcessResponse(string response) {
            if (response.Contains(MasterMind.youLose)) {
                MessageBox.Show(response, "Game Over", MessageBoxButton.OK, MessageBoxImage.Information);
            } else if (response.Equals(MasterMind.nextGuess)) {
                MessageBox.Show(response, "Empty Guess", MessageBoxButton.OK, MessageBoxImage.Error);
            } else if (response.Equals(MasterMind.youWin)) {
                MessageBox.Show(response, "Game Over", MessageBoxButton.OK, MessageBoxImage.Information);
            } else {
                int index = 0;
                foreach (Ellipse el in responseList) {
                    if (index < response.Length) {
                        if (el.IsEnabled) {
                            BrushConverter converter = new BrushConverter();
                            if (response[index] == 'W') {
                                System.Windows.Media.Brush newFill = (System.Windows.Media.Brush)converter.ConvertFromString("White");
                                el.Fill = newFill;
                            } else if (response[index] == 'B') {
                                System.Windows.Media.Brush newFill = (System.Windows.Media.Brush)converter.ConvertFromString("Black");
                                el.Fill = newFill;
                            }
                            index++;
                            el.IsEnabled = false;
                        }
                    }
                }
            }
        }

        protected override void OnMouseDown(MouseButtonEventArgs e) {
            base.OnMouseDown(e);
            ellipse = (Ellipse)e.Source;
        }

        protected override void OnMouseMove(MouseEventArgs e) {
            base.OnMouseMove(e);
            if (e.LeftButton == MouseButtonState.Pressed) {
                DataObject data = new DataObject();
                data.SetData(DataFormats.StringFormat, ellipse.Fill.ToString());
                data.SetData("Object", ellipse);
                DragDrop.DoDragDrop(ellipse, data, DragDropEffects.Copy);
            }
        }

        private void Guess_DragOver(object sender, DragEventArgs e) {
            e.Effects = DragDropEffects.Copy;
        }

        private void Guess_OnDrop(object sender, DragEventArgs e) {
            if (e.Data.GetDataPresent(DataFormats.StringFormat)) {
                string color = (string)e.Data.GetData(DataFormats.StringFormat);
                BrushConverter converter = new BrushConverter();

                if (converter.IsValid(color)) {
                    System.Windows.Media.Brush newFill = (System.Windows.Media.Brush)converter.ConvertFromString(color);
                    ((Ellipse)sender).Fill = newFill;
                }
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
            MMClient.Close();
        }
    }
}

任何帮助将不胜感激。谢谢!

0 个答案:

没有答案