DCS/ruiyiweiUX/Assets/GeneralTools/Scripts/Socket/TCPServer.cs

201 lines
6.9 KiB
C#
Raw Normal View History

2026-06-09 13:59:11 +08:00
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using UnityEngine;
namespace GeneralTools
{
public class TCPServer : SocketBase
{
Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
Thread threadWatch = null; // 负责监听客户端连接请求的 线程;
Socket socketWatch = null;
public TCPServer(string ip, int port, int _listenLong = 100)
{
InitSocket(ip, port, _listenLong);
}
//初始化
void InitSocket(string ip, int port, int _listenLong)
{
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress address = string.IsNullOrEmpty(ip) ? IPAddress.Any : IPAddress.Parse(ip);
IPEndPoint endPoint = new IPEndPoint(address, port);
try
{
socketWatch.Bind(endPoint);
}
catch (SocketException se)
{
Debug.LogError(se.Message);
return;
}
socketWatch.Listen(_listenLong);
threadWatch = new Thread(WatchConnecting);
threadWatch.IsBackground = true;
threadWatch.Start();
}
void WatchConnecting()
{
while (true) // 持续不断的监听客户端的连接请求;
{
if (socketClose)
return;
// 开始监听客户端连接请求Accept方法会阻断当前的线程
Socket sokConnection = null;
try
{
sokConnection = socketWatch.Accept();
}
catch (SocketException)
{
continue;
}
if (sokConnection == null)
continue;
// 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字;
// 想列表控件中添加客户端的IP信息
// 将与客户端连接的 套接字 对象添加到集合中;
dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);
Thread thr = new Thread(RecMsg);
thr.IsBackground = true;
thr.Start(sokConnection);
dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr); // 将新建的线程 添加 到线程的集合中去。
}
}
void RecMsg(object sokConnectionparn)
{
Socket sokClient = sokConnectionparn as Socket;
string remoteEndPoint = sokClient.RemoteEndPoint.ToString();
while (true)
{
if (socketClose)
return;
byte[] arrMsgRec = new byte[reveiceByteSize];
// 将接受到的数据存入到输入 arrMsgRec中
int length = -1;
try
{
length = sokClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
}
catch (Exception e)
{
// 从 通信套接字 集合中删除被中断连接的通信套接字;
dict.Remove(remoteEndPoint);
// 从通信线程集合中删除被中断连接的通信线程对象;
dictThread.Remove(remoteEndPoint);
// 从列表中移除被中断的连接IP
break;
}
if (length == 0)
{
// 从 通信套接字 集合中删除被中断连接的通信套接字;
dict.Remove(remoteEndPoint);
// 从通信线程集合中删除被中断连接的通信线程对象;
dictThread.Remove(remoteEndPoint);
// 从列表中移除被中断的连接IP
break;
}
//保存接收到的数据
RecordReceiveMsg(arrMsgRec, length, sokClient.LocalEndPoint, sokClient.RemoteEndPoint);
}
}
public override void SendMsg(string strMsg)
{
byte[] _sendData = String2Bytes(strMsg, encoding);
foreach (Socket s in dict.Values)
{
try
{
s.Send(_sendData, _sendData.Length, SocketFlags.None);
}
catch (Exception se)
{
Debug.LogError(se.Message);
}
}
}
public override void SendMsg(byte[] byteMsg)
{
base.SendMsg(byteMsg);
foreach (Socket s in dict.Values)
{
try
{
s.Send(byteMsg, byteMsg.Length, SocketFlags.None);
}
catch (Exception se)
{
Debug.LogError(se.Message);
}
}
}
public override void SendMsg(IPEndPoint remote, string strMsg)
{
base.SendMsg(remote, strMsg);
byte[] _sendData = String2Bytes(strMsg, encoding);
string remoteStr = remote.ToString();
if (dict.ContainsKey(remoteStr))
{
try
{
dict[remoteStr].Send(_sendData, _sendData.Length, SocketFlags.None);
}
catch (Exception se)
{
Debug.LogError(se.Message);
}
}
}
public override void SendMsg(IPEndPoint remote, byte[] byteMsg)
{
base.SendMsg(remote, byteMsg);
string remoteStr = remote.ToString();
if (dict.ContainsKey(remoteStr))
{
try
{
dict[remoteStr].Send(byteMsg, byteMsg.Length, SocketFlags.None);
}
catch (Exception se)
{
Debug.LogError(se.Message);
}
}
}
//连接关闭
public override void SocketQuit()
{
base.SocketQuit();
foreach (var dic in dict)
{
if (dic.Value != null)
{
dic.Value.Close();
}
}
foreach (var dic in dictThread)
{
if (dic.Value != null)
{
dic.Value.Interrupt();
dic.Value.Abort();
}
}
if (socketWatch != null)
socketWatch.Close();
if (threadWatch != null)
{
threadWatch.Interrupt();
threadWatch.Abort();
}
}
}
}