123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- namespace StandardLibrary
- {
- /// <summary>
- /// TCP服务器类
- /// </summary>
- class Tcp_Server
- {
- #region 字段声明
- /// <summary>
- /// TCP服务器接收到客户端连接请求事件
- /// </summary>
- public Action<string, bool> TcpConnectEvent;
- /// <summary>
- /// TCP服务器接收到客户端发送消息事件
- /// </summary>
- public Action<string, byte[]> TcpReceiveEvent;
- /// <summary>
- /// 负责监听客户端连接请求的线程
- /// </summary>
- private Thread threadWatch = null;
- /// <summary>
- /// //服务器套接字
- /// </summary>
- private Socket socketWatch = null;
- /// <summary>
- /// //客户端IP与套接字的集合
- /// </summary>
- private Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();
- /// <summary>
- /// //客户端IP与线程的集合
- /// </summary>
- private Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
- private string _serverIp = "127.0.0.1";
- private int _serverPort = 1234;
- #endregion
- public string ServerIp
- {
- get { return _serverIp; }
- set { _serverIp = value; }
- }
- public int ServerPort
- {
- get { return _serverPort; }
- set { _serverPort = value; }
- }
- /// <summary>
- /// 打开侦听
- /// </summary>
- /// <param name="listenIP">侦听的IP</param>
- /// <param name="listenPort">侦听的端口号</param>
- public bool OpenTcpListen()
- {
- try
- {
- socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建负责监听的套接字
- IPAddress address = IPAddress.Parse(_serverIp);//获得IP地址
- IPEndPoint endPoint = new IPEndPoint(address, _serverPort);//创建包含ip和端口号的网络节点对象
- socketWatch.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- socketWatch.Bind(endPoint);//将负责监听的套接字绑定到唯一的ip和端口上
- socketWatch.Listen(16);//设置侦听队列的长度,开始侦听
- threadWatch = new Thread(WatchConnecting);//创建负责侦听的线程
- threadWatch.IsBackground = true;//设置为后台线程
- threadWatch.Start();//启动线程
- return true;
- }
- catch (Exception e)
- {
- MessageBox.Show("异常:" + e.Message, "服务器侦听", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
- return false;
- }
- }
- /// <summary>
- /// 侦听客户端请求
- /// </summary>
- private void WatchConnecting()
- {
- while (true) //持续监听客户端的连接请求
- {
- // 开始监听客户端连接请求,Accept方法会阻断当前的线程
- Socket sokConnection = socketWatch.Accept(); //一旦监听到一个客户端的请求,就返回一个与该客户端通信的套接字
- string ip = sokConnection.RemoteEndPoint.ToString().Split(':')[0];
- if (!dictSocket.ContainsKey(ip)) dictSocket.Add(ip, sokConnection);//将客户端的IP对象添加到集合中
- else dictSocket[ip] = sokConnection;
- Thread thr = new Thread(ReceiveMsg);//创建处理客户端连接线程
- thr.IsBackground = true;//设置为后台线程
- thr.Start(sokConnection);//启动线程
- if (!dictThread.ContainsKey(ip)) dictThread.Add(ip, thr); //将新建的线程添加到线程的集合中
- else dictThread[ip] = thr;
- if (TcpConnectEvent != null) TcpConnectEvent(ip, true);//发布客户端连接成功消息
- }
- }
- /// <summary>
- /// 接收数据处理
- /// </summary>
- /// <param name="sokConnectionparn">客户端套接字</param>
- private void ReceiveMsg(object sokConnectionparn)
- {
- Socket sokClient = sokConnectionparn as Socket;//客户端套接字
- string ip = sokClient.RemoteEndPoint.ToString().Split(':')[0];
- try
- {
- while (true)
- {
- byte[] arrMsgRec = new byte[2048 * 1];//定义一个1k字节的接收缓存区
- int length = sokClient.Receive(arrMsgRec);//接收数据将数据存入arrMsgRec,返回数据的长度,并阻挡当前线程
- if (length > 0)//判断接收到的数据长度,如果大于0则表示数据正常,如果小于或等于0则表示客户端断开连接
- {
- byte[] rec = new byte[length];
- Array.Copy(arrMsgRec, rec, length);
- if (TcpReceiveEvent != null) TcpReceiveEvent(ip, rec);//发布接收客户端消息
- }
- else dictThread[ip].Abort();//释放线程
- }
- }
- catch (Exception)
- {
- if (dictSocket.ContainsKey(ip)) dictSocket.Remove(ip);//从通信套接字集合中删除被中断连接的通信套接字
- if (dictThread.ContainsKey(ip)) dictThread.Remove(ip);//从通信线程集合中删除被中断连接的通信线程对象
- if (TcpConnectEvent != null) TcpConnectEvent(ip, false);//发布客户端连接断开消息
- }
- }
- public void CloseTcpConnect(string ip)
- {
- if (dictSocket.ContainsKey(ip))
- {
- dictThread[ip].Abort();
- dictSocket[ip].Close();
- }
- }
- public void CloseTcpListen()
- {
- //socketWatch.Close();
- //socketWatch.Dispose();
- //threadWatch.Abort();
- }
- /// <summary>
- /// 发送消息
- /// </summary>
- /// <param name="IP">客户端IP地址</param>
- /// <param name="SendData">数据</param>
- public bool SendServerMsg(string IP, string SendData)
- {
- try
- {
- byte[] sendMsg = Encoding.ASCII.GetBytes(SendData);
- if (dictSocket.ContainsKey(IP)) dictSocket[IP].Send(sendMsg);//发送数据
- return true;
- }
- catch { return false; }
- }
- /// <summary>
- /// 发送消息
- /// </summary>
- /// <param name="IP">客户端IP地址</param>
- /// <param name="SendData">数据</param>
- public bool SendServerMsg(string IP, byte[] SendData)
- {
- try
- {
- if (dictSocket.ContainsKey(IP)) dictSocket[IP].Send(SendData);//发送数据
- return true;
- }
- catch { return false; }
- }
- }
- /// <summary>
- /// TCP客户端类
- /// </summary>
- class Tcp_Client
- {
- /// <summary>
- /// 接收消息事件
- /// </summary>
- public event Action<string> TcpReceiveEvent;
- /// <summary>
- /// 连接状态事件
- /// </summary>
- public event Action<bool> TcpConnectEvent;
- /// <summary>
- /// TCP客户端
- /// </summary>
- private Socket tcpClient;
- /// <summary>
- /// 接收消息线程
- /// </summary>
- private Thread receiveThread;
- private string _ip = "127.0.0.1";
- private int _port = 8500;
- /// <summary>
- /// 获取或设置远程服务端IP地址
- /// </summary>
- public string IP
- {
- get { return _ip; }
- set { _ip = value; }
- }
- /// <summary>
- /// 获取或设置远程服务端端口号
- /// </summary>
- public int Port
- {
- get { return _port; }
- set { _port = value; }
- }
- /// <summary>
- /// 打开连接
- /// </summary>
- /// <param name="ip"></param>
- /// <param name="port"></param>
- public bool OpenTcpConnect()
- {
- IPEndPoint IpEnd = new IPEndPoint(IPAddress.Parse(_ip), _port);
- tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- try
- {
- tcpClient.Connect(IpEnd);//发起TCP连接
- receiveThread = new Thread(ReceiveMsg);//实例化并启动接受消息线程
- receiveThread.IsBackground = true;//设置为后台线程
- receiveThread.Start();//启动线程
- if (TcpConnectEvent != null) TcpConnectEvent(true);//发布连接成功消息
- return true;
- }
- catch (Exception e)
- {
- if (TcpConnectEvent != null) TcpConnectEvent(false);//发布连接失败消息
- return false;
- }
- }
- /// <summary>
- /// 关闭连接
- /// </summary>
- public void CloseTcpConnect()
- {
- tcpClient.Close();//断开TCP连接
- receiveThread.Abort();//销毁接受消息的线程
- }
- /// <summary>
- /// 接收服务端发送的消息
- /// </summary>
- public void ReceiveMsg()
- {
- try
- {
- while (true)
- {
- byte[] getData = new byte[2048];//创建接受数据的字节流
- int length = tcpClient.Receive(getData, getData.Length, 0);
- if (length > 0)
- {
- byte[] rec = new byte[length];
- Array.Copy(getData, rec, length);
- string getMsg = Encoding.ASCII.GetString(rec);//将字节数组转换成文本形式
- if (TcpReceiveEvent != null) TcpReceiveEvent(getMsg);
- }
- else receiveThread.Abort();//释放线程
- }
- }
- catch (Exception e)//检测释放线程异常
- {
- if (TcpConnectEvent != null) TcpConnectEvent(false);//发布连接断开消息
- CloseTcpConnect();
- }
- }
- /// <summary>
- /// 发送消息给服务端
- /// </summary>
- /// <param name="msg">数据</param>
- public void SendMsg(string msg)
- {
- byte[] sendData = Encoding.ASCII.GetBytes(msg);//将要发送的文本转换为字符数组形式
- tcpClient.Send(sendData, sendData.Length, 0);
- }
- /// <summary>
- /// 发送消息给服务端
- /// </summary>
- /// <param name="msg">数据</param>
- public void SendMsg(byte[] msg)
- {
- tcpClient.Send(msg);
- }
- }
- }
|