界面布局设置

This commit is contained in:
zhengxuan.zhang
2023-10-08 14:12:16 +08:00
parent 8bef038966
commit 790f217e62
20 changed files with 9808 additions and 25 deletions
+371
View File
@@ -0,0 +1,371 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HexcalMC.Hexcal
{
public class TcpIpServer
{
/// <summary>
/// 使用模式,默认=1,接收任意数据显示;2=前两个字节为数据长度
/// </summary>
public int UseMode = 1;
string strServerIP = "127.0.0.1"; //服务器的IP地址
string strServerPort = "8080"; //端口号
public enum EnumTcpIpServer : int
{
StartListen = 1,
ClientConnect = 2,
SocketException = 8,
ConnectException = 9,
Exception = -1
}
#region 510,
System.Windows.Forms.Timer ServerTimer = new System.Windows.Forms.Timer();
private void ServerTimerLoop(object sender, EventArgs e)
{
ServerTimer.Interval = 20000; //监听timer的间隔
if (DictSocket != null)
{
if (DictSocket.Count != 0)
{
DictSocket.Values.ToArray();
for (int i = DictSocket.Values.ToArray().Length - 1; i >= 0; i--)
{
if (DictSocket.Values.ToArray()[i].Poll(10, SelectMode.SelectRead)) //10毫秒,检查套接字状态, SelectMode 参数指定要监视的套接字的类别。
{
// DictSocket.Remove(DictSocket.Keys.ToArray()[i]);
RaisedStatus(EnumTcpIpServer.ConnectException,
"连接已断开:" + DictSocket.Keys.ToArray()[i]); //刷新界面显示,触发一个连接异常状态枚举,并将消息传递为异常的状态
RemoveSocketClient(DictSocket.Keys.ToArray()[i]);
}
}
}
}
}
#endregion
Thread m_WatchThread = null; // 负责监听客户端连接请求的线程;
Socket m_WatchSocket = null;
Dictionary<string, Thread> DictThread = new Dictionary<string, Thread>();
Dictionary<string, Socket> DictSocket = new Dictionary<string, Socket>();
bool bStartListen = false;
public string[] SocketNames
{
get { return (string[])DictSocket.Keys.ToArray(); }
}
//=========================================================================
public TcpIpServer(string ServerIP, string ServerPort)
{
strServerIP = ServerIP;
strServerPort = ServerPort;
}
public bool StartListen()
{
try
{
ServerTimer.Tick += new EventHandler(ServerTimerLoop); //510,增加时钟,判断是否有断掉的连接。
ServerTimer.Start();
m_WatchSocket =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建负责监听的套接字,注意其中的参数;
IPAddress m_IpAddr = IPAddress.Parse(strServerIP); //获得文本框中的IP对象;
IPEndPoint m_EndPoint = new IPEndPoint(m_IpAddr, int.Parse(strServerPort)); //创建包含ip和端口号的网络节点对象;
try
{
m_WatchSocket.Bind(m_EndPoint); // 将负责监听的套接字绑定到唯一的ip和端口上;
}
catch (SocketException se)
{
MessageBox.Show("异常:" + se.Message);
return false;
}
bStartListen = true;
m_WatchSocket.Listen(10); // 设置监听队列的长度
m_WatchThread = new Thread(WatchThread); // 创建负责监听的线程
m_WatchThread.IsBackground = true;
m_WatchThread.Start();
RaisedStatus(EnumTcpIpServer.StartListen, "服务器启动监听成功!IP=" + strServerIP + ", Port=" + strServerPort);
return true;
}
catch (Exception ex)
{
MessageBox.Show("启动服务器监听失败:" + ex.Message);
return false;
}
}
public void StopListen()
{
try
{
bStartListen = false;
m_WatchSocket.Close();
m_WatchSocket.Dispose();
m_WatchSocket = null;
DictThread.Clear();
DictSocket.Clear();
}
catch
{
}
}
public bool ConnectStatus
{
get
{
if (m_WatchSocket == null)
return false;
return m_WatchSocket.Connected && m_WatchThread != null;
}
}
public bool WatchStatus
{
get { return bStartListen; }
}
//监听线程
void WatchThread()
{
try
{
while (bStartListen) // 持续不断的监听客户端的连接请求;
{
// 开始监听客户端连接请求,Accept方法会阻断当前的线程;
Socket sokClient = m_WatchSocket.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的套接字;
#region 510,
if (DictSocket != null)
{
if (DictSocket.Count != 0)
{
DictSocket.Values.ToArray();
for (int i = DictSocket.Values.ToArray().Length - 1; i >= 0; i--)
{
if (DictSocket.Values.ToArray()[i].Poll(10, SelectMode.SelectRead))
{
//DictSocket.Remove(DictSocket.Keys.ToArray()[i]);
RemoveSocketClient(DictSocket.Keys.ToArray()[i]);
}
}
}
}
#endregion
DictSocket.Add(sokClient.RemoteEndPoint.ToString(), sokClient); // 将与客户端连接的套接字对象添加到集合中;
RaisedStatus(EnumTcpIpServer.ClientConnect,
"客户端连接成功!RemoteEndPoint=" + sokClient.RemoteEndPoint.ToString());
Thread thread = new Thread(ReceiveThread);
thread.IsBackground = true;
thread.Start(sokClient);
DictThread.Add(sokClient.RemoteEndPoint.ToString(), thread); // 将新建的线程 添加 到线程的集合中去。
}
}
catch
{
}
}
//接收线程
void ReceiveThread(object sokObj)
{
Socket sokClient = sokObj as Socket;
while (bStartListen)
{
// 定义一个2M的缓存区;
byte[] arrMsgRec = new byte[sokClient.Available];
// 将接受到的数据存入到输入 arrMsgRec中;
int length = -1;
try
{
length = sokClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
}
catch (SocketException se)
{
RaisedStatus(EnumTcpIpServer.SocketException, "异常:SocketException=" + se.Message);
RemoveSocketClient(sokClient.RemoteEndPoint.ToString());
return;
}
catch (Exception ex)
{
RaisedStatus(EnumTcpIpServer.ConnectException, "异常:Exception=" + ex.Message);
RemoveSocketClient(sokClient.RemoteEndPoint.ToString());
return;
}
try
{
if (UseMode == 1)
{
if (length > 0)
{
// TcpIpDfn.SongLiang_arrMsgRec = arrMsgRec; //510
string strData = System.Text.Encoding.Default.GetString(arrMsgRec); // 将接受到的字节数据转化成字符串;
//strData = strData.Substring(0, length);
//RaisedMessage(sokClient.RemoteEndPoint.ToString(), strData.Replace("\0", "<0>"));
RaisedMessage(sokClient.RemoteEndPoint.ToString(), strData.Replace("\0", "."));
}
}
else if (UseMode == 2)
{
if (length > 0 && arrMsgRec.Length > 2)
{
// TcpIpDfn.SongLiang_arrMsgRec = arrMsgRec; //510
string strData =
System.Text.Encoding.Default.GetString(arrMsgRec, 2,
arrMsgRec.Length - 2); // 将接受到的字节数据转化成字符串;
RaisedMessage(sokClient.RemoteEndPoint.ToString(), strData);
}
}
}
catch (Exception ex)
{
RaisedStatus(EnumTcpIpServer.Exception, "获取Socket数据异常:ex=" + ex.Message);
}
}
}
//删除客户端对象
void RemoveSocketClient(string strRemoteEndPoint)
{
// 从通信套接字集合中 删除被中断连接的通信套接字;
DictSocket.Remove(strRemoteEndPoint);
// 从通信线程集合中 删除被中断连接的通信线程对象;
DictThread.Remove(strRemoteEndPoint);
}
//发送消息
public void SendMessage(string strSocketKey, string strMsg)
{
byte[] arrMsg = System.Text.Encoding.Default.GetBytes(strMsg);
DictSocket[strSocketKey].Send(arrMsg);
}
public void SendMessage(string strSocketKey, byte[] arrMsg)
{
DictSocket[strSocketKey].Send(arrMsg);
}
/// <summary> 发送数据函数(字符串, 自动添加长度(byte格式))</summary>
public string SendMessage2(string strSocketKey, string strMsg)
{
try
{
if (DictSocket[strSocketKey].Connected)
{
byte[] arrLength = new byte[2];
arrLength = BitConverter.GetBytes(Convert.ToInt16(strMsg.Length));
byte[] WriteBuffer = Encoding.Default.GetBytes(strMsg);
WriteBuffer = arrLength.Concat(WriteBuffer).ToArray();
DictSocket[strSocketKey].Send(WriteBuffer);
return "";
}
return "NotConnect";
}
catch (Exception ex)
{
return "error:" + ex.Message;
}
}
public void SendMessageToAllClients(string strMsg)
{
byte[] arrMsg = System.Text.Encoding.Default.GetBytes(strMsg);
foreach (Socket soc in DictSocket.Values)
{
soc.Send(arrMsg);
}
}
public void SendMessageToAllClients(byte[] arrMsg)
{
foreach (Socket soc in DictSocket.Values)
{
soc.Send(arrMsg);
}
}
public delegate void EventHandler_RaisedStatus(EnumTcpIpServer Type, string Msg);
public event EventHandler_RaisedStatus OnRaisedStatus;
// 异步或同步触发自定义事件,并在目标控件是 Windows Forms 控件的情况下添加到目标控件的消息队列中。它主要的目的是使得自定义事件处理程序在UI线程上执行,以避免线程上的卡顿或UI更新问题。
private void RaisedStatus(EnumTcpIpServer ReturnType, string Msg)
{
try
{
if (OnRaisedStatus != null)
{
if (OnRaisedStatus.Target is System.Windows.Forms.Control)
{
Control targetForm = OnRaisedStatus.Target as System.Windows.Forms.Control;
targetForm.BeginInvoke(OnRaisedStatus, new object[] { ReturnType, Msg });
}
else
{
OnRaisedStatus(ReturnType, Msg);
}
}
}
catch (Exception)
{
}
}
public delegate void EventHandler_RaisedMessage(string ClientIP, string Msg);
public event EventHandler_RaisedMessage OnRaisedMessage;
private void RaisedMessage(string ClientIP, string Msg)
{
try
{
if (OnRaisedMessage != null)
{
if (OnRaisedMessage.Target is System.Windows.Forms.Control)
{
Control targetForm = OnRaisedMessage.Target as System.Windows.Forms.Control;
targetForm.BeginInvoke(OnRaisedMessage, new object[] { ClientIP, Msg });
}
else
{
OnRaisedMessage(ClientIP, Msg);
}
}
}
catch (Exception)
{
}
}
}
}