using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Net.Sockets; using System.Net; // IP,IPAddress, IPEndPoint,端口等; using System.Threading; using System.IO; namespace ConsoleApp1 { class Program { string ip_val = ""; static string tcp_port = "1520"; static Thread threadWatch = null; // 负责监听客户端连接请求的 线程; static Socket socketWatch = null; private bool Client_connect = false; static Dictionary dict = new Dictionary();////例如使用socket,创建字典代码
  Dictionary dic = new Dictionary();
static Dictionary dictThread = new Dictionary(); static void start_init() { // 创建负责监听的套接字,注意其中的参数; socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 获得文本框中的IP对象; IPAddress address = IPAddress.Parse(GetLocalIPv4Address().ToString());//127.0.0.1 Console.WriteLine("服务器IP:"+GetLocalIPv4Address().ToString()+" 端口:"+tcp_port); // 创建包含ip和端口号的网络节点对象; IPEndPoint endPoint = new IPEndPoint(address, int.Parse(tcp_port)); //8098 //IPEndPoint endPoint = new IPEndPoint(address, 8098); //8098 try { // 将负责监听的套接字绑定到唯一的ip和端口上; socketWatch.Bind(endPoint); } catch (SocketException se) { Console.WriteLine("异常:" + se.Message); return; } // 设置监听队列的长度; socketWatch.Listen(20); // 创建负责监听的线程; threadWatch = new Thread(WatchConnecting); threadWatch.IsBackground = true; threadWatch.Start(); Console.WriteLine("TCP透传服务器启动成功!"); } /// <字节数组转16进制字符串> /// /// String 16进制显示形式 public static string byteToHexStr(byte[] bytes) { string returnStr = ""; try { if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString("X2"); returnStr += " ";//两个16进制用空格隔开,方便看数据 } } return returnStr; } catch (Exception) { return returnStr; } } /// <字符串转16进制格式,不够自动前面补零> /// /// /// /// private static byte[] strToToHexByte(String hexString) { int i; // hexString = hexString.Replace(" ", "");//清除空格 if ((hexString.Length % 2) != 0)//奇数个 { byte[] returnBytes = new byte[(hexString.Length + 1) / 2]; try { for (i = 0; i < (hexString.Length - 1) / 2; i++) { returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); } returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16); } catch { return null; } return returnBytes; } else { byte[] returnBytes = new byte[(hexString.Length) / 2]; try { for (i = 0; i < returnBytes.Length; i++) { returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); } } catch { return null; } return returnBytes; } } /// /// 监听客户端请求的方法; /// static void WatchConnecting() { Socket sokConnection = null; while (true) // 持续不断的监听客户端的连接请求; { // 开始监听客户端连接请求,Accept方法会阻断当前的线程; try { sokConnection = socketWatch.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字; // Socket sokConnection = socketWatch.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字; } catch (Exception ex) { //提示套接字监听异常 Console.WriteLine(ex.Message); ShowMsg("客户端异常" + ex.Message); break; } // 想列表控件中添加客户端的IP信息; // lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString()); // 将与客户端连接的 套接字 对象添加到集合中; dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);//// 字典集合添加元素 ShowMsg("客户端连接成功!"); Thread thr = new Thread(RecMsg); thr.IsBackground = true; thr.Start(sokConnection); dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr); // 将新建的线程 添加 到线程的集合中去。 } } static bool IsSocketConnected(Socket s) { return !((s.Poll(10, SelectMode.SelectRead) && (s.Available == 0)) || !s.Connected); } static void RecMsg(object sokConnectionparn) { Socket sokClient = sokConnectionparn as Socket; while (true) { // 定义一个5M的缓存区; byte[] arrMsgRec = new byte[1024 * 1024 * 5]; // 将接受到的数据存入到输入 arrMsgRec中; int length = -1; if (sokClient.Poll(-1, SelectMode.SelectRead))//第一个参数为等待时间 us -1 为一直等待 阻塞在这里等待 当有数据 /*SelectRead: 如果已调用 Listen(Int32) 并且有挂起的连接,则为 true。 - 或 - 如果有数据可供读取,则为 true。 - 或 - 如果连接已关闭 重置或终止则返回 true; - 否则,返回 false。*/ { try { length = sokClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度; // 当客户端断开时 会发送一个长度为0 的空数据 此处一定要加判断 等于0 说明断开了 要做出处理 否则线程死循环一直接收0字节数据bug if (length == 0) //长度等于0 客户端断开连接了 会发送个0字节数据上来的 { dict.Remove(sokClient.RemoteEndPoint.ToString()); // 从通信线程集合中删除被中断连接的通信线程对象; dictThread.Remove(sokClient.RemoteEndPoint.ToString()); // 从列表中移除被中断的连接IP //lbOnline.Items.Remove(sokClient.RemoteEndPoint.ToString()); Console.WriteLine("客户端:"+ sokClient.RemoteEndPoint.ToString()+"断开连接"); break; //客户端断开了 终止当前的通讯线程 不然会一直触发接收 有bug } else //接收正常数据了 { string strMsg = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length);// 将接受到的字节数据转化成字符串; 接收文件另外处理 看下面 这里不能接收文件 byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg); // 将要发送的字符串转换成Utf-8字节数组; string ShowstrMsg = "客户端:" + sokClient.RemoteEndPoint + " 时间:" + GetCurrentTime() + "\r\n源数据 String:" + strMsg + " hex:"+ byteToHexStr(arrMsg) +"\r\n"; ShowMsg(ShowstrMsg); // SendMsgdata(strMsg);//源数据下发 给所有客户端 foreach (Socket s in dict.Values) //开始群发信息 遍历字典里面的连接好的socket客户端 { if (s != sokClient)//判断是否是当前发送数据上来的客户端 是的话就不发送 { s.Send(arrMsg); } // s.Send(arrMsg); } //ShowMsg("发送消息为:" + strMsg); } } catch (SocketException se) { ShowMsg("异常了:" + se.Message); // 从 通信套接字 集合中删除被中断连接的通信套接字; dict.Remove(sokClient.RemoteEndPoint.ToString()); // 从通信线程集合中删除被中断连接的通信线程对象; dictThread.Remove(sokClient.RemoteEndPoint.ToString()); Console.WriteLine("客户端:" + sokClient.RemoteEndPoint.ToString() + "断开连接"); // 从列表中移除被中断的连接IP // lbOnline.Items.Remove(sokClient.RemoteEndPoint.ToString()); break; } catch (Exception e) { ShowMsg("异常了:" + e.Message); // 从 通信套接字 集合中删除被中断连接的通信套接字; dict.Remove(sokClient.RemoteEndPoint.ToString()); // 从通信线程集合中删除被中断连接的通信线程对象; dictThread.Remove(sokClient.RemoteEndPoint.ToString()); Console.WriteLine("客户端:" + sokClient.RemoteEndPoint.ToString() + "断开连接"); // sokClient.Close(); // 从列表中移除被中断的连接IP // lbOnline.Items.Remove(sokClient.RemoteEndPoint.ToString()); break; } } } } static void SendMsgdata(string dataStr) { // string strMsg = "服务器" + "\r\n" + " -->" + dataStr + "\r\n"; string strMsg = dataStr; byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(dataStr); // 将要发送的字符串转换成Utf-8字节数组; byte[] arrSendMsg = new byte[arrMsg.Length]; // byte[] arrSendMsg = new byte[arrMsg.Length + 1]; // 用来标识发送是数据而不是文件,如果没有这一段的客户端就接收不到消息了~~~ // arrSendMsg[0] = 0; // 表示发送的是消息数据 //  Buffer.BlockCopy(arrMsg, 0, arrSendMsg, 1, arrMsg.Length); foreach (Socket s in dict.Values) { s.Send(arrMsg); } ShowMsg("发送消息为:" + strMsg); } static int cnt_info = 0; static void ShowMsg(string str) { Console.WriteLine(str); Write_SaveTxtFile(str + "\r\n"); if(++cnt_info>5000) { cnt_info = 0; Console.Clear(); } // txtMsg.Items.Add(str + "\r\n"); } static public void Write_SaveTxtFile(string txtStr) //保存文本文件 到软件运行目录下 { string str = Environment.CurrentDirectory;//获取软件的运行目录 取得或设置当前工作目录的完整限定路径 File.AppendAllText(@str + "\\" + "Log.txt", txtStr); //在软件运行目录下保存log信息 } /// /// 获取当前系统时间的方法 /// 当前时间 static DateTime GetCurrentTime() { DateTime currentTime = new DateTime(); currentTime = DateTime.Now; return currentTime; } /// /// 获取本地IPv4地址 /// /// static public IPAddress GetLocalIPv4Address() { IPAddress localIpv4 = null; //获取本机所有的IP地址列表 IPAddress[] IpList = Dns.GetHostAddresses(Dns.GetHostName()); //循环遍历所有IP地址 foreach (IPAddress IP in IpList) { //判断是否是IPv4地址 if (IP.AddressFamily == AddressFamily.InterNetwork) { localIpv4 = IP; } else { continue; } } return localIpv4; } static string acceptmultiLine() { ConsoleKeyInfo cki; // Console.TreatControlCAsInput = true;//防止Ctrl+C复制 Console.WriteLine("Press the F10 key to quit app \n"); string result = string.Empty; do { cki = Console.ReadKey(); result += cki.KeyChar; if (cki.Key == ConsoleKey.Enter) { if(result!="") { result += System.Environment.NewLine;//如果输入回车,则加入换行标志 SendMsgdata(result); } result = string.Empty; } } while (cki.Key != ConsoleKey.F10);//按F10退出 Environment.Exit(0); return result; } static void Main(string[] args) { // Console.WriteLine("hello"); start_init(); string s = acceptmultiLine(); Console.WriteLine(s); while (true) ; } } }