123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- 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<string, Socket> dict = new Dictionary<string, Socket>();////例如使用socket,创建字典代码<br> Dictionary<string,Socket> dic = new Dictionary<string,Socket>();<br>
- static Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
- 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进制字符串>
- /// <param name="bytes"></param>
- /// <returns> String 16进制显示形式</returns>
- 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进制格式,不够自动前面补零>
- ///
- /// </summary>
- /// <param name="hexString"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 监听客户端请求的方法;
- /// </summary>
- 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;
- } /// <summary>
- /// 获取本地IPv4地址
- /// </summary>
- /// <returns></returns>
- 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) ;
- }
- }
- }
|