C# WPF-сервер и клиентский сокет - PullRequest
0 голосов
/ 12 января 2020

Я пытаюсь сделать небольшой сервер и мульти-клиентское программное обеспечение. Я использую сервер в качестве консольного приложения и клиент в качестве клиента WPF. Мне удалось отправить сообщения через, но я не могу потоковое подключение подключенных пользователей в моем списке. Я хочу показать подключенных пользователей во всех клиентах. Это мой код. Так как я пытался использовать MessageCallBack, я подключил свой клиент и немедленно отключил его. Что я делаю не так?

СЕРВЕР

namespace SocketApp
{
class Server
{
    private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    private static readonly EndPoint epLocal, epRemote;
    private static readonly List<Socket> clientSockets = new List<Socket>();
    private const int BUFFER_SIZE = 2048;
    private const int PORT = 100;
    private static readonly byte[] buffer = new byte[BUFFER_SIZE];

    static void Main(string[] args)
    {
        Console.Title = "Server";
        SetupServer();
        Console.ReadLine(); // When we press enter close everything
        CloseAllSockets();
    }


    private static void SetupServer()
    {
        Console.WriteLine("Setting up server...");
        serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
        serverSocket.Listen(0);
        serverSocket.BeginAccept(AcceptCallback, null);
        Console.WriteLine("Server setup complete");
    }

    /// <summary>
    /// Close all connected client (we do not need to shutdown the server socket as its connections
    /// are already closed with the clients).
    /// </summary>
    private static void CloseAllSockets()
    {
        foreach (Socket socket in clientSockets)
        {
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
        }

        serverSocket.Close();
    }

    private static void AcceptCallback(IAsyncResult AR)
    {
        Socket socket;

        try
        {
            socket = serverSocket.EndAccept(AR);
        }
        catch (ObjectDisposedException) // I can not seem to avoid this (on exit when properly closing sockets)
        {
            return;
        }

        clientSockets.Add(socket);
        socket.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
        Console.WriteLine("{0}", socket.RemoteEndPoint + " connected...");
        foreach (object obj in clientSockets)
        {
            Socket socket2 = (Socket)obj;
            string message = socket2.RemoteEndPoint.ToString();
            byte[] data = Encoding.ASCII.GetBytes(message);
            socket2.Send(data);
        }
        serverSocket.BeginAccept(AcceptCallback, null);
    }

    private static void ReceiveCallback(IAsyncResult AR)
    {
        Socket current = (Socket)AR.AsyncState;
        int received;

        try
        {
            received = current.EndReceive(AR);
        }
        catch (SocketException)
        {
            Console.WriteLine("Client forcefully disconnected");
            // Don't shutdown because the socket may be disposed and its disconnected anyway.
            current.Close();
            clientSockets.Remove(current);
            return;
        }

        byte[] recBuf = new byte[received];
        Array.Copy(buffer, recBuf, received);
        string text = Encoding.ASCII.GetString(recBuf);
        Console.WriteLine("Received Text: " + text);

        if (text.ToLower() == "meeting") // Client requested time
        {
            foreach (object obj in clientSockets)
            {
                string message = "meeting";
                byte[] data = Encoding.ASCII.GetBytes(message);
                Socket socket = (Socket)obj;
                socket.Send(data);
                Console.WriteLine("Meeting invite sent to " + socket.RemoteEndPoint);
            }

        }
        else if (text.ToLower() == "exit") // Client wants to exit gracefully
        {
            // Always Shutdown before closing
            Console.WriteLine(current.RemoteEndPoint + " disconnected");
            current.Shutdown(SocketShutdown.Both);
            current.Close();
            clientSockets.Remove(current);
            return;
        }
        else if (text.ToLower() == "offline") // Client requested time
        {
            foreach (object obj in clientSockets)
            {
                string message = "offline";
                byte[] data = Encoding.ASCII.GetBytes(message);
                Socket socket = (Socket)obj;
                socket.Send(data);
                Console.WriteLine("Offline user: " + socket.RemoteEndPoint);
            }

        }
        else
        {
            Console.WriteLine("Invalid request");
            byte[] data = Encoding.ASCII.GetBytes("Invalid request");
            current.Send(data);
            Console.WriteLine("Warning Sent");
        }


        current.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
    }


}

}

КЛИЕНТ WPF

namespace Client
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private readonly Socket ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    EndPoint epRemote;
    private const int PORT = 100;
    private byte[] buffer;
    private string message { get; set; }
    public string serverMessage { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        ConnectToServer();
        UpdateControls();
        connectedUsers();
    }

    private void connectedUsers()
    {
        //Listen to the ports
        byte[] buffer = new byte[1500];
        ClientSocket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
    }

    private void UpdateControls()
    {
        lblMessage.Content = message;
        //txtFromServer.Text = serverMessage;
    }

    private void ConnectToServer()
    {
        int attempts = 0;

        while (!ClientSocket.Connected)
        {
            try
            {
                attempts++;
                //lblMessage.Text = "Connection attempt " + attempts;
                // Change IPAddress.Loopback to a remote IP to connect to a remote host.
                //ClientSocket.Connect(IPAddress.Loopback, PORT);
                ClientSocket.Connect("localhost", PORT);
            }
            catch (SocketException ex)
            {
                MessageBox.Show(ex.Message + Environment.NewLine + "Connection attempt " + attempts);
            }
        }

        message = "Connected";
        var buffer = new byte[2048];
        try
        {
            if (buffer.ToString().Length == 2048) return;
            int received = ClientSocket.Receive(buffer, SocketFlags.None);
            if (received == 0) return;
            var data = new byte[received];
            Array.Copy(buffer, data, received);
            string text = Encoding.ASCII.GetString(data);
            list_Users.Items.Add(text);
            //txt_ConnectedUsers.Text += text + System.Environment.NewLine;
            //MessageBox.Show(text);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            return;
        }
    }

    private void RequestLoop()
    {
        while (true)
        {
            SendRequest("");
            ReceiveResponse();
        }
    }

    private void SendRequest(string text)
    {
        string request = text;
        SendString(request);

        if (request.ToLower() == "exit")
        {
            Exit();
        }

    }

    /// <summary>
    /// Sends a string to the server with ASCII encoding.
    /// </summary>
    private void SendString(string text)
    {
        try
        {
            byte[] buffer = Encoding.ASCII.GetBytes(text);
            ClientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if(txt_TextMessage.Text == "")
        {
            UpdateControls();
            return;
        }
        else
        {
            SendRequest(txt_TextMessage.Text);
            ReceiveResponse();
            UpdateControls();
        }

    }

    private void Exit()
    {
        SendString("exit"); // Tell the server we are exiting
        ClientSocket.Shutdown(SocketShutdown.Both);
        ClientSocket.Close();
        Environment.Exit(0);
    }

    public void ReceiveResponse()
    {
        var buffer = new byte[2048];
        try
        {
            if (buffer.ToString().Length == 2048) return;
            int received = ClientSocket.Receive(buffer, SocketFlags.None);
            if (received == 0) return;
            var data = new byte[received];
            Array.Copy(buffer, data, received);
            string text = Encoding.ASCII.GetString(data);
            txt_TextFromServer.Text += text + System.Environment.NewLine;
            //MessageBox.Show(text);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            return;
        }
    }

    private void MessageCallBack(IAsyncResult aResult)
    {
        try
        {
            this.Dispatcher.Invoke(() =>
            {
                int size = ClientSocket.EndReceiveFrom(aResult, ref epRemote);
                if (size > 0)
                {
                    byte[] receiveData = new byte[1500];
                    receiveData = (byte[])aResult.AsyncState;
                    ASCIIEncoding eEncoding = new ASCIIEncoding();
                    string receivedMessage = eEncoding.GetString(receiveData);

                    //Populate connected users
                    list_Users.Items.Add(receivedMessage);
                }
                byte[] buffer = new byte[1500];
                ClientSocket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
            });
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }
    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        Exit();
    }
}

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...