三、CS代码
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace CSharpeCode.Demo_TcpProtocol
{
public partial class Frm_TcpServer : Form
{
TcpServerTool tcpServerTool;
#region 窗体:初始化、加载、关闭
public Frm_TcpServer()
{
InitializeComponent();
}
private void Frm_TcpClient_Load(object sender, EventArgs e)
{
ControlStyleUpdata(picBox_ConnectStatu, Color.Gray);
}
private void Frm_TcpServer_FormClosing(object sender, FormClosingEventArgs e)
{
if (tcpServerTool != null)
{
tcpServerTool.Disconnect();
}
}
#endregion
#region 控件圆角方法
public void ControlStyleUpdata(Control control)
{
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(control.ClientRectangle);
Region region = new Region(gp);
control.Region = region;
gp.Dispose();
region.Dispose();
}
public void ControlStyleUpdata(Control control, Color bcColor)
{
control.BackColor = bcColor;
ControlStyleUpdata(control);
}
#endregion
#region 鼠标单击事件
private void btn_Open_Click(object sender, EventArgs e)
{
bool isOpen = btn_Open.Text.Equals("打开") ? true : false;
if (isOpen)
{
tcpServerTool = new TcpServerTool(tbx_IpAddress.Text, tbx_Port.Text);
tcpServerTool.ExecuteMessageChanged += TcpTool_ExecuteMessageChangedCallback;
tcpServerTool.ClientCountChanged += TcpTool_OnCountChangedCallback;
tcpServerTool.Open();
}
else
{
tcpServerTool.Disconnect();
}
if (tcpServerTool.IsListened) picBox_ConnectStatu.BackColor = Color.LimeGreen;
else picBox_ConnectStatu.BackColor = Color.Gray;
btn_Open.Text = tcpServerTool.IsListened ? "关闭" : "打开";
}
private void btn_Send_Click(object sender, EventArgs e)
{
if (tcpServerTool != null)
{
if (checkBox_SendGroup.Checked)
{
tcpServerTool.SendGroup(rtbx_SendData.Text);
}
else
{
tcpServerTool.Send(cbx_ClientList.Text, rtbx_SendData.Text);
}
}
}
private void btn_ClearReceiveData_Click(object sender, EventArgs e)
{
rtbx_ReceiveData.Text = string.Empty;
}
private void btn_ClearSendData_Click(object sender, EventArgs e)
{
rtbx_SendData.Text = string.Empty;
}
#endregion
private void TcpTool_ExecuteMessageChangedCallback(object sender, string message)
{
MessageShow(message);
}
public void TcpTool_OnCountChangedCallback(object sender, string endPoint)
{
MessageShow($"{sender}:{endPoint}");
ClientListUpdata(endPoint, sender.ToString());
}
public void MessageShow(string data)
{
rtbx_ReceiveData.Invoke(new Action(() =>
{
rtbx_ReceiveData.AppendText($"{DateTime.Now}】{data}{System.Environment.NewLine}");
}));
}
public void ClientListUpdata(string endPoint, string mode)
{
cbx_ClientList.Invoke(new Action(() =>
{
switch (mode.ToString().ToLower())
{
case "add":
cbx_ClientList.Items.Add(endPoint);
break;
case "remove":
cbx_ClientList.Items.Remove(endPoint);
break;
default:
break;
}
if (cbx_ClientList.Items.Count==1) cbx_ClientList.SelectedIndex = 0;
if (cbx_ClientList.Items.Count == 0) cbx_ClientList.Text = string.Empty;
}));
}
}
}
3.1.3 服务端辅助类
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace CSharpeCode.Demo_TcpProtocol
{
public class TcpServerTool
{
#region 事件委托
public event EventHandler<string> ExecuteMessageChanged;
public event EventHandler<string> ClientCountChanged;
#endregion
#region 字段、属性
private string _ip = "127.0.0.1";
private int _port = 9000;
private string _ipPort = "127.0.0.1:9000";
private bool _isConnected = false;
private bool _isListened = false;
private NetworkStream _stream;
private Socket _serverSocket;
private Thread listenThread = null;
private List<string> _clientIpPortList = new List<string>();
private List<Socket> _clientSocketList = new List<Socket>();
private List<Thread> _clientSocketThreadList = new List<Thread>();
public string IP { get => _ip; set => _ip = value; }
public int Port { get => _port; set => _port = value; }
public bool IsConnected { get => _isConnected; set => _isConnected = value; }
public bool IsListened { get => _isListened; set => _isListened = value; }
public NetworkStream Stream { get => _stream; set => _stream = value; }
public Socket ServerSocket { get => _serverSocket; set => _serverSocket = value; }
public List<string> ClientIpPortList { get => _clientIpPortList; set => _clientIpPortList = value; }
public List<Socket> ClientSocketList { get => _clientSocketList; set => _clientSocketList = value; }
public List<Thread> ClientSocketThreadList { get => _clientSocketThreadList; set => _clientSocketThreadList = value; }
public string IpPort { get => _ipPort; set => _ipPort = value; }
#endregion
#region 构造方法
public TcpServerTool(string ip, int port)
{
this.IP = ip;
this.Port = port;
}
public TcpServerTool(string ip, string port)
{
this.IP = ip;
if (int.TryParse(port, out int portStr))
{
this.Port = portStr;
}
}
#endregion
public void Disconnect()
{
IsListened = false;
IsConnected = false;
foreach (Thread item in ClientSocketThreadList)
{
item.Abort();
}
foreach (Socket item in ClientSocketList)
{
item.Close();
}
listenThread?.Abort();
listenThread = null;
Stream?.Close();
ServerSocket?.Close();
ServerSocket = null;
Stream = null;
ClientSocketThreadList?.Clear();
ClientSocketList?.Clear();
ClientIpPortList?.Clear();
}
public void Open()
{
try
{
IPAddress ipAddress = IPAddress.Parse(IP);
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ServerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Port);
ServerSocket.Bind(localEndPoint);
ExecuteMessageChanged?.Invoke(this, $"开始侦听准备...");
ServerSocket.Listen(10);
listenThread = new Thread(OnListenClient);
listenThread.IsBackground = true;
listenThread.Start();
IsListened = true;
ExecuteMessageChanged?.Invoke(this, $"本地终端:{ServerSocket.LocalEndPoint}");
ExecuteMessageChanged?.Invoke(this, $"协议:{ServerSocket.LocalEndPoint.AddressFamily}");
ExecuteMessageChanged?.Invoke(this, $"准备完成,开始侦听客户端连接...");
}
catch (Exception ex)
{
ExecuteMessageChanged?.Invoke(this, $"创建连接失败....");
ExecuteMessageChanged?.Invoke(this, $"{ex.Message}");
}
}
public void OnListenClient()
{
try
{
while (true)
{
Socket socket = ServerSocket.Accept();
ExecuteMessageChanged?.Invoke(this, $"收到来自【{socket.LocalEndPoint}】远程终端的连接请求...");
string sendTestData = "Test Connect...";
ExecuteMessageChanged?.Invoke(this, $"尝试发送数据:{sendTestData}");
Send(socket, sendTestData);
Thread thread = new Thread(Received);
thread.Name = (ClientSocketThreadList.Count + 1) + "";
thread.IsBackground = true;
thread.Start(socket);
ClientIpPortList.Add(socket.RemoteEndPoint.ToString());
ClientSocketList.Add(socket);
ClientSocketThreadList.Add(thread);
ClientCountChanged?.Invoke("Add", socket.RemoteEndPoint.ToString());
}
}
catch (Exception ex)
{
ExecuteMessageChanged?.Invoke(this, $"侦听异常:{ex.Message}");
}
}
public void Received(object socketClientPara)
{
Socket socketServer = socketClientPara as Socket;
string remoteEndPoint = socketServer.RemoteEndPoint.ToString(); ;
while (true)
{
try
{
byte[] buffer = new byte[1024 * 1024];
if (socketServer == null) break;
int dataLength = socketServer.Receive(buffer);
string dataReceived = Encoding.ASCII.GetString(buffer, 0, dataLength);
ExecuteMessageChanged.Invoke(this, "接收数据:");
ExecuteMessageChanged.Invoke(this, $"{socketServer.RemoteEndPoint}->{dataReceived}");
}
catch (Exception ex)
{
if (IsListened)
{
ClientIpPortList.Remove(remoteEndPoint);
ClientCountChanged?.Invoke("Remove", remoteEndPoint);
Stream = null;
ExecuteMessageChanged.Invoke(this, "客户端已断开连接!");
ExecuteMessageChanged.Invoke(this, $"接收异常:{ex.Message}");
ClientSocketList.Find(s => s.RemoteEndPoint.Equals(remoteEndPoint))?.Close();
ClientSocketList.Remove(socketServer);
break;
}
}
}
}
public void Send(string ipPort, string data)
{
try
{
if (IsListened)
{
string socketIpPort = ClientIpPortList.Find(s => s.Equals(ipPort));
Socket socket = ClientSocketList.Find(s => s.RemoteEndPoint.ToString().Equals(ipPort));
if (socket !=null)
{
Stream = new NetworkStream(socket);
string dataToSend = data;
byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend);
Stream.Write(dataBytes, 0, dataBytes.Length);
ExecuteMessageChanged?.Invoke(this, $"发送数据长度:{dataBytes.Length}");
}
else
{
ExecuteMessageChanged?.Invoke(this, $"发送失败!socket = null");
}
}
}
catch (Exception ex)
{
ExecuteMessageChanged?.Invoke(this, $"发送异常:{ex.Message}");
}
}
public void Send(Socket socket,string data)
{
try
{
if (IsListened)
{
if (Stream != null)
{
string dataToSend = data;
byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend);
Stream.Write(dataBytes, 0, dataBytes.Length);
ExecuteMessageChanged?.Invoke(this, $"发送数据长度:{dataBytes.Length}");
}
else
{
Stream = new NetworkStream(socket);
string dataToSend = data;
byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend);
Stream.Write(dataBytes, 0, dataBytes.Length);
ExecuteMessageChanged?.Invoke(this, $"发送数据长度:{dataBytes.Length}");
}
}
}
catch (Exception ex)
{
ExecuteMessageChanged?.Invoke(this, $"发送异常:{ex.Message}");
}
}
public void SendGroup(string data)
{
try
{
if (IsListened)
{
foreach (Socket socket in ClientSocketList)
{
Stream = new NetworkStream(socket);
string dataToSend = data;
byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend);
Stream.Write(dataBytes, 0, dataBytes.Length);
ExecuteMessageChanged.Invoke(this, $"发送到终端:{socket.RemoteEndPoint}");
ExecuteMessageChanged.Invoke(this, $"协议版本:{socket.RemoteEndPoint.AddressFamily}");
ExecuteMessageChanged.Invoke(this, $"发送数据长度:{dataBytes.Length}");
}
}
}
catch (Exception ex)
{
ExecuteMessageChanged.Invoke(this, $"发送异常:{ex.Message}");
}
}
}
}