C#常规TcpListener
1.Xaml
1 <Window x:Class="Server.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:Server" 7 mc:Ignorable="d" 8 xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes" 9 WindowStartupLocation="CenterScreen" ResizeMode="NoResize" 10 Loaded="MainWindow_OnLoaded" 11 Title="Server" Height="450" Width="600"> 12 <Grid> 13 <Grid.ColumnDefinitions> 14 <ColumnDefinition Width="Auto"/> 15 <ColumnDefinition Width="1*"/> 16 </Grid.ColumnDefinitions> 17 <TreeView x:Name="tvRemotes"> 18 </TreeView> 19 <Grid Grid.Column="1"> 20 <Grid.RowDefinitions> 21 <RowDefinition Height="Auto"/> 22 <RowDefinition Height="Auto"/> 23 <RowDefinition Height="Auto"/> 24 <RowDefinition Height="1*"/> 25 </Grid.RowDefinitions> 26 <Grid.ColumnDefinitions> 27 <ColumnDefinition /> 28 <ColumnDefinition Width="Auto"/> 29 </Grid.ColumnDefinitions> 30 <TextBlock HorizontalAlignment="Right" Margin="5,0,2,0" Padding="5" Text="本地地址"/> 31 <TextBox x:Name="tbIP" IsReadOnly="True" Grid.Row="0" Grid.Column="1" Margin="5" Text="127.0.0.1" /> 32 <TextBlock HorizontalAlignment="Right" Margin="5,0,2,0" Padding="5" Grid.Row="1" Grid.Column="0" Text="本地端口:"/> 33 <TextBox x:Name="tbPort" Grid.Row="1" Grid.Column="1" Margin="5"/> 34 <StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal"> 35 <Button x:Name="btnListen" Content="开始监听" Margin="15" Click="BtnListen_OnClick"/> 36 <Button x:Name="btnDisconnect" Content="断开连接" IsEnabled="False" Margin="15" Click="BtnDisconnect_OnClick"/> 37 </StackPanel> 38 <ListView x:Name="lvDebugs" Grid.Row="3" Grid.ColumnSpan="2" Grid.Column="0" AlternationCount="2"> 39 <ListView.ItemContainerStyle> 40 <Style TargetType="ListViewItem"> 41 <Style.Triggers> 42 <Trigger Property="ListView.AlternationIndex" Value="0"> 43 <Setter Property="Background" Value="White"/> 44 </Trigger> 45 <Trigger Property="ListView.AlternationIndex" Value="1"> 46 <Setter Property="Background" Value="WhiteSmoke"/> 47 </Trigger> 48 </Style.Triggers> 49 </Style> 50 </ListView.ItemContainerStyle> 51 </ListView> 52 </Grid> 53 </Grid> 54 </Window>
2.CSharp
1 using MaterialDesignThemes.Wpf; 2 using System; 3 using System.Collections.Generic; 4 using System.Net; 5 using System.Net.Sockets; 6 using System.Text; 7 using System.Threading.Tasks; 8 using System.Windows; 9 using System.Windows.Controls; 10 using System.Windows.Threading; 11 12 namespace Server 13 { 14 /// <summary> 15 /// MainWindow.xaml 的交互逻辑 16 /// </summary> 17 public partial class MainWindow : Window 18 { 19 private TcpListener listener = null; 20 private List<Socket> socketList = new List<Socket>(); 21 22 public class StateObject 23 { 24 public Socket workSocket = null; 25 public const int BUFFER_SIZE = 1024; 26 public byte[] buffer = new byte[BUFFER_SIZE]; 27 } 28 29 public MainWindow() 30 { 31 InitializeComponent(); 32 } 33 34 private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) 35 { 36 37 } 38 39 /// <summary> 40 /// 开启监听 41 /// </summary> 42 /// <param name="sender"></param> 43 /// <param name="e"></param> 44 private void BtnListen_OnClick(object sender, RoutedEventArgs e) 45 { 46 try 47 { 48 listener = new TcpListener(new IPEndPoint(IPAddress.Any, Convert.ToInt32(tbPort.Text))); 49 listener.Start(); 50 listener.BeginAcceptSocket(new AsyncCallback(AcceptCallback), listener.Server); 51 52 btnListen.IsEnabled = false; 53 btnDisconnect.IsEnabled = true; 54 } 55 catch (Exception ex) 56 { 57 Add2ListView("启动监听异常: " + ex.Message); 58 } 59 } 60 61 private void AcceptCallback(IAsyncResult ar) 62 { 63 Socket server = (Socket) ar.AsyncState; 64 try 65 { 66 Socket socket = server.EndAccept(ar); 67 string strAddr = socket.RemoteEndPoint.ToString(); 68 socketList.Add(socket); 69 Dispatcher.Invoke(() => 70 { 71 Add2TreeView(strAddr); 72 Add2ListView(strAddr); 73 }, DispatcherPriority.Normal); 74 var bytes = Encoding.UTF8.GetBytes("welcome."); 75 socket.Send(bytes); 76 StateObject so = new StateObject(); 77 so.workSocket = socket; 78 socket.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, 79 new AsyncCallback(ReceiveCallback), so); 80 81 server.BeginAccept(new AsyncCallback(AcceptCallback), server); 82 } 83 catch (Exception) 84 { 85 // ignored 86 } 87 } 88 89 /// <summary> 90 /// 断开监听 91 /// </summary> 92 /// <param name="sender"></param> 93 /// <param name="e"></param> 94 private async void BtnDisconnect_OnClick(object sender, RoutedEventArgs e) 95 { 96 try 97 { 98 foreach (var socket in socketList) 99 { 100 if (socket != null && socket.Connected) 101 { 102 socket.Shutdown(SocketShutdown.Both); 103 104 await Task.Delay(10); 105 socket.Close(); 106 } 107 } 108 socketList.Clear(); 109 110 listener.Stop(); 111 // 清空客户端列表 112 tvRemotes.Items.Clear(); 113 114 btnListen.IsEnabled = true; 115 btnDisconnect.IsEnabled = false; 116 } 117 catch (Exception ex) 118 { 119 Add2ListView("断开监听异常: " + ex.Message); 120 } 121 } 122 123 private void ReceiveCallback(IAsyncResult ar) 124 { 125 StateObject so = ar.AsyncState as StateObject; 126 Socket socket = so.workSocket; 127 if (socket != null && socket.Connected) 128 { 129 int read = socket.EndReceive(ar); 130 ar.AsyncWaitHandle.Close(); 131 if (read > 0) 132 { 133 Dispatcher.Invoke(() => Add2ListView(text: socket.RemoteEndPoint + ": " + Encoding.UTF8.GetString(so.buffer)), 134 DispatcherPriority.Normal); 135 socket.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, 136 new AsyncCallback(ReceiveCallback), so); 137 } 138 else 139 { 140 Dispatcher.Invoke(() => 141 { 142 Add2ListView(socket.RemoteEndPoint + ": 客户端连接已断开."); 143 for (int i = 0; i < tvRemotes.Items.Count; i++) 144 { 145 TreeViewItem tvi = (TreeViewItem)tvRemotes.Items[i]; 146 if ((string)tvi.Tag == socket.RemoteEndPoint.ToString()) 147 { 148 tvRemotes.Items.Remove(tvi); 149 socketList.Remove(socket); 150 return; 151 } 152 } 153 }, 154 DispatcherPriority.Normal); 155 156 socket.Shutdown(SocketShutdown.Both); 157 socket.Close(); 158 } 159 } 160 } 161 162 private void Add2TreeView(string strRemote) 163 { 164 TreeViewItem tvi = new TreeViewItem(); 165 tvi.Tag = strRemote; 166 StackPanel sp = new StackPanel(); 167 sp.Orientation = Orientation.Horizontal; 168 sp.Children.Add(new PackIcon { Kind = PackIconKind.Devices }); 169 sp.Children.Add(new TextBlock { Text = $"{strRemote}" }); 170 tvi.Items.Add(sp); 171 tvRemotes.Items.Add(tvi); 172 } 173 174 private void Add2ListView(string text) 175 { 176 TextBlock tb = new TextBlock { Text = text }; 177 lvDebugs.Items.Add(tb); 178 } 179 } 180 }
3.运行效果