Приложение клиент-сервер C# WPF
Делаю лабораторную, нужно сделать приложение клиент-сервер в виде чата. Само по себе приложение готово, но я не могу понять как сделать кнопки "disconnect" у приложения клиента и "Stop server" у приложения сервера, чтобы они корректно завершали работу приложений и закрывали каналы соединения. В моем коде при использовании этих кнопок приложение вылетает. Буду рад любой помощи.
Вот код:
Приложение сервер
using System.Windows;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System;
namespace server
{
public partial class MainWindow : Window
{
int n = 0;
int port = 8888;
static TcpListener listener;
TcpClient client = null;
NetworkStream stream = null;
bool ListenerCheck = true;
bool ServerIsStarded = false;
public MainWindow()
{
InitializeComponent();
}
public void start_Click(object sender, RoutedEventArgs e)
{
listener = new TcpListener(IPAddress.Parse("127.0.0.1"), port);
if (ListenerCheck == true)
{
listener.Start();
ServerLog.Items.Add("The server is running...");
Thread listenThread = new Thread(() => listen());
listenThread.Start();
ListenerCheck = false;
ServerIsStarded = true;
}
else Dispatcher.BeginInvoke(new Action(() => ServerLog.Items.Add("The server has already been started.")));
}
public void listen()
{
while (ServerIsStarded)
{
try
{
client = listener.AcceptTcpClient();
Dispatcher.BeginInvoke(new Action(() => ServerLog.Items.Add("A new client is connected")));
Thread clientThread = new Thread(() => Process(client));
clientThread.Start();
}
catch (Exception ex)
{
Dispatcher.BeginInvoke(new Action(() => ServerLog.Items.Add(ex.Message)));
}
}
}
public void Process(TcpClient tcpClient)
{
TcpClient client = tcpClient;
try
{
stream = client.GetStream();
byte[] data = new byte[64];
while (true)
{
StringBuilder builder = new StringBuilder();
int bytes = 0;
do
{
bytes = stream.Read(data, 0, data.Length);
builder.Append(Encoding.Unicode.GetString(data, 0, bytes));
}
while (stream.DataAvailable);
string message = builder.ToString();
Dispatcher.BeginInvoke(new Action(() => ServerLog.Items.Add(message)));
Dispatcher.BeginInvoke(new Action(() => counter()));
data = Encoding.Unicode.GetBytes(message);
stream.Write(data, 0, data.Length);
}
}
catch (Exception ex)
{
Dispatcher.BeginInvoke(new Action(() => ServerLog.Items.Add(ex.Message)));
}
finally
{
if (stream != null)
stream.Dispose();
stream.Close();
if (client != null)
client.Dispose();
client.Close();
}
}
private void stop_Click(object sender, RoutedEventArgs e)
{
ServerIsStarded = false;
if (stream != null)
{
stream.Dispose();
stream.Close(300);
}
if (client != null && client.Connected)
{
client.Dispose();
client.Close();
}
if (listener != null)
{
listener.Stop();
ServerLog.Items.Add("The server was stopped.");
ListenerCheck = true;
}
else Dispatcher.BeginInvoke(new Action(() => ServerLog.Items.Add("The server was not started")));
}
void counter()
{
countm.Text = Convert.ToString(n = n + 1);
}
}
}
Приложение клиент
using System.Windows;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System;
namespace Client
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
int outmessage = 0;
int inmessage = 0;
TcpClient client = null;
NetworkStream stream = null;
int port = 8888;
string address = "127.0.0.1";
public void Connect_Click(object sender, RoutedEventArgs e)
{
try
{
client = new TcpClient(address, port);
stream = client.GetStream();
Dispatcher.BeginInvoke(new Action(() => ClientLog.Items.Add("The connection is established.")));
}
catch (Exception ex)
{
ClientLog.Items.Add(ex.Message);
}
if (client != null)
{
Thread listenThread = new Thread(() => listen());
listenThread.Start();
}
}
void listen()
{
try
{
while (true)
{
byte[] data = new byte[64];
StringBuilder builder = new StringBuilder();
int bytes = 0;
do
{
bytes = stream.Read(data, 0, data.Length);
builder.Append(Encoding.Unicode.GetString(data, 0, bytes));
}
while (stream.DataAvailable);
string message = builder.ToString();
Dispatcher.BeginInvoke(new Action(() => ClientLog.Items.Add("Server: " + message)));
Dispatcher.BeginInvoke(new Action(() => CountIn()));
}
}
catch (Exception ex)
{
Dispatcher.BeginInvoke(new Action(() => ClientLog.Items.Add(ex.Message)));
}
finally
{
stream.Dispose();
stream.Close();
client.Dispose();
client.Close();
}
}
private void Send_Click(object sender, RoutedEventArgs e)
{
string message = Message.Text;
message = String.Format("{0}: {1}", Name.Text, message);
byte[] data = Encoding.Unicode.GetBytes(message);
if (client != null && client.Connected)
{
stream.Write(data, 0, data.Length);
countout.Text = Convert.ToString(outmessage = outmessage + 1);
}
else Dispatcher.BeginInvoke(new Action(() => ClientLog.Items.Add("The connection was not established.")));
}
void CountIn()
{
countin.Text = Convert.ToString(inmessage = inmessage + 1);
}
private void Disconnect_Click(object sender, RoutedEventArgs e)
{
if (client != null)
{
stream.Dispose();
stream.Close();
client.Close();
client.Dispose();
ClientLog.Items.Add("Сonnection closed.");
}
else Dispatcher.BeginInvoke(new Action(() => ClientLog.Items.Add("The connection was not established.")));
}
}
}
И на всякий случай код разметки xaml:
Для сервера:
<Window x:Class="server.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:server"
mc:Ignorable="d"
Title="Server" Height="426.703" Width="311.989" ResizeMode="NoResize">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35*"/>
<ColumnDefinition Width="757*"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="ServerLog" HorizontalAlignment="Left" Height="278" Margin="10,32,0,0" VerticalAlignment="Top" Width="272" Grid.ColumnSpan="2" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Visible"/>
<Button x:Name="start" Content="Start server" HorizontalAlignment="Left" Margin="10,340,0,0" VerticalAlignment="Top" Width="75" Grid.ColumnSpan="2" Click="start_Click"/>
<Button x:Name="stop" Content="Stop server" HorizontalAlignment="Left" Margin="194,340,0,0" VerticalAlignment="Top" Width="75" Grid.Column="1" Click="stop_Click"/>
<Label Content="Server log:" HorizontalAlignment="Left" Margin="10,6,0,0" VerticalAlignment="Top" Grid.ColumnSpan="2" Background="{x:Null}"/>
<Label Content="Number of 
messages:" Grid.Column="1" HorizontalAlignment="Left" Margin="109,-2,0,0" VerticalAlignment="Top" Width="121" FontSize="9"/>
<TextBlock x:Name="countm" Grid.Column="1" HorizontalAlignment="Left" Margin="188,9,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" FontSize="10"/>
<Label Content="In:" Grid.Column="1" HorizontalAlignment="Left" Margin="168,4,0,0" VerticalAlignment="Top" Height="23" FontSize="10"/>
</Grid>
</Window>
Для клиента:
<Window x:Class="Client.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Client"
mc:Ignorable="d"
Title="Client" Height="435" Width="508.607" ResizeMode="NoResize">
<Grid>
<ListBox x:Name="ClientLog" HorizontalAlignment="Left" Height="215" Margin="10,36,0,0" VerticalAlignment="Top" Width="473" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Visible"/>
<Label Content="Client log:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="64"/>
<TextBox x:Name="Message" HorizontalAlignment="Left" Height="45" Margin="10,318,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="473" Grid.Row="1"/>
<Button x:Name="Send" Content="Send" HorizontalAlignment="Left" Margin="10,368,0,0" VerticalAlignment="Top" Width="75" Grid.Row="1" Click="Send_Click"/>
<Label Content="Message:
" HorizontalAlignment="Left" Margin="10,292,0,0" VerticalAlignment="Top" Height="27" Grid.Row="1"/>
<TextBox x:Name="Name" HorizontalAlignment="Left" Height="23" Margin="55,263,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="101" Grid.Row="1"/>
<Label Content="Name:" HorizontalAlignment="Left" Margin="10,259,0,0" VerticalAlignment="Top" Width="54" Height="28" Grid.Row="1"/>
<Button x:Name="Connect" Content="Connect" HorizontalAlignment="Left" Margin="310,263,0,0" VerticalAlignment="Top" Width="75" Height="23" Grid.Row="1" Click="Connect_Click"/>
<Button x:Name="Disconnect" Content="Disconnect" HorizontalAlignment="Left" Margin="408,263,0,0" VerticalAlignment="Top" Width="75" Height="23" Grid.Row="1" Click="Disconnect_Click"/>
<Label Content="Number of 
messages:" HorizontalAlignment="Left" Margin="362,-3,0,0" VerticalAlignment="Top" Width="121" FontSize="9"/>
<Label Content="In:" HorizontalAlignment="Left" Margin="423,-2,0,0" VerticalAlignment="Top" FontSize="8" Height="23"/>
<Label Content="Out:
" HorizontalAlignment="Left" Margin="417,10,0,0" VerticalAlignment="Top" FontSize="8" Height="23" Width="25"/>
<TextBlock x:Name="countin" HorizontalAlignment="Left" Margin="441,3,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" FontSize="8"/>
<TextBlock x:Name="countout" HorizontalAlignment="Left" Margin="441,15,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" Width="33" FontSize="8"/>
</Grid>
</Window>