1.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"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
WindowStartupLocation="CenterScreen" ResizeMode="NoResize"
Loaded="MainWindow_OnLoaded"
Title="Server" Height="450" Width="600">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TreeView x:Name="tvRemotes">
</TreeView>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right" Margin="5,0,2,0" Padding="5" Text="本地地址"/>
<TextBox x:Name="tbIP" IsReadOnly="True" Grid.Row="0" Grid.Column="1" Margin="5" Text="127.0.0.1" />
<TextBlock HorizontalAlignment="Right" Margin="5,0,2,0" Padding="5" Grid.Row="1" Grid.Column="0" Text="本地端口:"/>
<TextBox x:Name="tbPort" Grid.Row="1" Grid.Column="1" Margin="5"/>
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal">
<Button x:Name="btnListen" Content="开始监听" Margin="15" Click="BtnListen_OnClick"/>
<Button x:Name="btnDisconnect" Content="断开连接" IsEnabled="False" Margin="15" Click="BtnDisconnect_OnClick"/>
</StackPanel>
<ListView x:Name="lvDebugs" Grid.Row="3" Grid.ColumnSpan="2" Grid.Column="0" AlternationCount="2">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="ListView.AlternationIndex" Value="0">
<Setter Property="Background" Value="White"/>
</Trigger>
<Trigger Property="ListView.AlternationIndex" Value="1">
<Setter Property="Background" Value="WhiteSmoke"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Grid>
</Window>

2.CSharp

 using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading; namespace Server
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private TcpListener listener = null;
private List<Socket> socketList = new List<Socket>(); public class StateObject
{
public Socket workSocket = null;
public const int BUFFER_SIZE = ;
public byte[] buffer = new byte[BUFFER_SIZE];
} public MainWindow()
{
InitializeComponent();
} private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{ } /// <summary>
/// 开启监听
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnListen_OnClick(object sender, RoutedEventArgs e)
{
try
{
listener = new TcpListener(new IPEndPoint(IPAddress.Any, Convert.ToInt32(tbPort.Text)));
listener.Start();
listener.BeginAcceptSocket(new AsyncCallback(AcceptCallback), listener.Server); btnListen.IsEnabled = false;
btnDisconnect.IsEnabled = true;
}
catch (Exception ex)
{
Add2ListView("启动监听异常: " + ex.Message);
}
} private void AcceptCallback(IAsyncResult ar)
{
Socket server = (Socket) ar.AsyncState;
try
{
Socket socket = server.EndAccept(ar);
string strAddr = socket.RemoteEndPoint.ToString();
socketList.Add(socket);
Dispatcher.Invoke(() =>
{
Add2TreeView(strAddr);
Add2ListView(strAddr);
}, DispatcherPriority.Normal);
var bytes = Encoding.UTF8.GetBytes("welcome.");
socket.Send(bytes);
StateObject so = new StateObject();
so.workSocket = socket;
socket.BeginReceive(so.buffer, , StateObject.BUFFER_SIZE, SocketFlags.None,
new AsyncCallback(ReceiveCallback), so); server.BeginAccept(new AsyncCallback(AcceptCallback), server);
}
catch (Exception)
{
// ignored
}
} /// <summary>
/// 断开监听
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void BtnDisconnect_OnClick(object sender, RoutedEventArgs e)
{
try
{
foreach (var socket in socketList)
{
if (socket != null && socket.Connected)
{
socket.Shutdown(SocketShutdown.Both); await Task.Delay();
socket.Close();
}
}
socketList.Clear(); listener.Stop();
// 清空客户端列表
tvRemotes.Items.Clear(); btnListen.IsEnabled = true;
btnDisconnect.IsEnabled = false;
}
catch (Exception ex)
{
Add2ListView("断开监听异常: " + ex.Message);
}
} private void ReceiveCallback(IAsyncResult ar)
{
StateObject so = ar.AsyncState as StateObject;
Socket socket = so.workSocket;
if (socket != null && socket.Connected)
{
int read = socket.EndReceive(ar);
ar.AsyncWaitHandle.Close();
if (read > )
{
Dispatcher.Invoke(() => Add2ListView(text: socket.RemoteEndPoint + ": " + Encoding.UTF8.GetString(so.buffer)),
DispatcherPriority.Normal);
socket.BeginReceive(so.buffer, , StateObject.BUFFER_SIZE, SocketFlags.None,
new AsyncCallback(ReceiveCallback), so);
}
else
{
Dispatcher.Invoke(() =>
{
Add2ListView(socket.RemoteEndPoint + ": 客户端连接已断开.");
for (int i = ; i < tvRemotes.Items.Count; i++)
{
TreeViewItem tvi = (TreeViewItem)tvRemotes.Items[i];
if ((string)tvi.Tag == socket.RemoteEndPoint.ToString())
{
tvRemotes.Items.Remove(tvi);
socketList.Remove(socket);
return;
}
}
},
DispatcherPriority.Normal); socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
} private void Add2TreeView(string strRemote)
{
TreeViewItem tvi = new TreeViewItem();
tvi.Tag = strRemote;
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Horizontal;
sp.Children.Add(new PackIcon { Kind = PackIconKind.Devices });
sp.Children.Add(new TextBlock { Text = $"{strRemote}" });
tvi.Items.Add(sp);
tvRemotes.Items.Add(tvi);
} private void Add2ListView(string text)
{
TextBlock tb = new TextBlock { Text = text };
lvDebugs.Items.Add(tb);
}
}
}

3.运行效果

C#常规TcpListener的更多相关文章

  1. Taurus.MVC 微服务框架 入门开发教程:项目部署:1、微服务应用程序常规部署实现多开,节点扩容。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

  2. CSS三个定位——常规、浮动、绝对定位

    .dage { width: 868px; background: #5B8C75; border: 10px solid #A08C5A; margin-top: -125px; margin-le ...

  3. Windows Server 2008 R2常规安全设置及基本安全策略

    这篇文章主要介绍了Windows Web Server 2008 R2服务器简单安全设置,需要的朋友可以参考下 用的腾讯云最早选购的时候悲催的只有Windows Server 2008 R2的系统,原 ...

  4. C# - 网络编程 之 TcpClient与TcpListener

    TcpClient类 TcpListener类 TCP通信 UDP通信 参考:

  5. Oracle Recovery 01 - 常规恢复之完全恢复

    背景:这里提到的常规恢复指的是数据库有完备可用的RMAN物理备份. 实验环境:RHEL6.4 + Oracle 11.2.0.4 DG primary. 一.常规恢复之完全恢复:不丢失数据 1.1 单 ...

  6. Oracle Recovery 02 - 常规恢复之不完全恢复

    背景:这里提到的常规恢复指的是数据库有完备可用的RMAN物理备份. 实验环境:RHEL6.4 + Oracle 11.2.0.4 单实例. 二.常规恢复之不完全恢复:部分数据丢失 2.1 重做日志文件 ...

  7. git 常规使用小结

    总结下 git 的常规使用: 一般我们使用 git 来维护项目代码. 前提背景: 远程服务器上代码库,包含分支: 1.master - 版本发布分支 2.dev - 平时开发用的分支 一般操作流程: ...

  8. 简单的c# TCP通讯(TcpListener)

      简单的c# TCP通讯(TcpListener) C# 的TCP Socket (同步方式) C# 的TCP Socket (异步方式) C# 的tcp Socket设置自定义超时时间 C# TC ...

  9. Socket聊天室-TcpListener,TcpClient

    参考自:http://blog.csdn.net/liguo9860/article/details/6148614 服务端:

随机推荐

  1. CentOS7时区和时间设置

    [root@saltstack-master ~]# timedatectl set-timezone Asia/Shanghai [root@saltstack-master ~]# ln -sf ...

  2. pikachu-暴力破解漏洞解析

    本篇blog导航 ~暴力破解&暴力破解漏洞概述 ~基于表单的暴力破解实验 ~暴力破解的绕过和防范(验证码&Token)     ~验证码的基础知识     ~验证码绕过(on clie ...

  3. android编译/反编译常用工具及项目依赖关系

    项目依赖关系 apktool:依赖smali/baksmali,XML部分 AXMLPrinter2 JEB:dx 工具依赖 AOSP , 反编译dex 依赖 apktool dex2jar:依赖 A ...

  4. window 下如何恢复被删除的mysql root账户及密码(mysql 8.0.17)

    不久前自学完完sql,下了mysql8.0.17,安装配置好后探索着,想着用root账户登上去能不能删除root账户呢,然后就想给自己一巴掌,,, 如何快速恢复root: 1.关闭mysql服务:wi ...

  5. Windows2008R2 一键安全优化脚本

      ::author vim ::QQ 82996821 ::filename Windows2008R2_safe_auto_set.bat   :start @echo off color 0a ...

  6. vue-socket.io跨域问题的解决方法

    报错信息: Access to XMLHttpRequest at 'http://192.168.37.130:5050/socket.io/?EIO=3&transport=polling ...

  7. Prime_Series_Level-1

    0x01 先收集靶机端口,目录信息 1)nmap扫描端口 开启了ssh服务和apache服务,搜索相关漏洞 只有一个ssh用户名枚举,先放着 2)dirb爆破目录 dirb http://192.16 ...

  8. MNIST 源码解析

    # Copyright 2015 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 ...

  9. Docker--数据管理之Volumes

    前言:我们知道docker容器内产生或修改的数据仅在该容器内有效,即容器关闭,其之前产生或修改的数据也就删除了,这明显不能满足我们大多数场景的需求.当然这只是默认,docker为我们提供了多种保存数据 ...

  10. (办公)记事本_linux压缩命令

    参考谷粒学院的linux视频教程:http://www.gulixueyuan.com/course/300/task/7091/show 在Linux中可以识别的常见的压缩格式有十几种,比如&quo ...