用c#写的一个局域网聊天客户端 类似小飞鸽

最后在公司实习,新人不给活干,就自己随便看看,了解一些DevExpress控件啊,编码规范啊之类的,自己就寻思着写一点点小东西练习练习

出于自己对c# socket这块不熟,就选择了这块,顺便可以进一步了解委托 代理。

闲话不说,先说下这次做的东西:一个局域网聊天的小软件  主要基于udp的通信,如果读者还不知道udp or tcp  那请度娘一下。。。

基本思路(这也都是网上查的,还查了飞鸽传书的 基本原理,在此感谢网上的各位高手哈):

1:软件开启的时候先新开一个线程,该线程充当服务器端,一直死循环监听

2:开了新线程了,调用广播的方法

3:此时如果局域网内已经有有其它主机打开了这个软件,将会监听到这个广播,收到这个广播后将返回自己的主机,并且将监听到的主机添加自己的在线列表中,当然,发起广播的软件也能收到其它软件的回信,收到他们的主机后也加入自己的在线列表,这样各自的列表就都能建立起来,并且将当前的列表加入一个静态的泛型列表中(用于以后和其它用户的通信,维护他们的状态)

4:通信 发送消息:双击一个主机列表后  得到该主机host 传到交谈窗体 并查询出他主机的endpoint,这样就可以进行本机和向该endpoint点发送消息了

5:下线 下线之前软件会发一个下线的广播,其它的软件接到该广播的时候将会将该主机从自己的在线列表中移除

 

整体思路就这样,下面可以结合代码具体看一下

View Code
#region Field/// <summary>/// 在非主线程是对控件操作/// </summary>/// <param name="host"></param>private delegate void MyInvoke(string host);/// <summary>/// 充当服务器 进行监听接收/// </summary>private SocketUdpServer udpServer;/// <summary>/// 充当客户端/// </summary>private SocketUdpClient udpClient;#endregion#region Contructor/// <summary>/// 构造函数/// </summary>public FrmUser(){InitializeComponent();init();}#endregion#region Method/// <summary>/// 初始化数据/// </summary>private void init(){LanList.CurrentLanList = new List<LanInfo>();this.Text = "当前局域网内在线用户";this.udpServer = SocketUdpServer.Instance;this.udpServer.OnLineComplete += new SocketUdpServer.OnCompleteHander(this.OnLine_Event);this.udpServer.DownLineComplete += new SocketUdpServer.OnCompleteHander(this.DownLine_Event);this.udpServer.ErrorAppear += new SocketUdpServer.OnCompleteHander(this.Error_Event);this.udpServer.Listen();this.udpClient = new SocketUdpClient();this.udpClient.Broadcast(DatagramType.OnLine);}/// <summary>/// 上线增加用户/// </summary>/// <param name="host">用户主机</param>private void AddUser(string host){this.ilbUserList.Items.Add(host, 0);}/// <summary>/// 下线减少用户/// </summary>/// <param name="host">用户主机在列表的序号 懒了以下 应该将回调的委托参数定义为int的,这里用了string 到程序需要转化为Int</param>private void RemoveUser(string hostIndex){this.ilbUserList.Items.RemoveAt(Convert.ToInt32(hostIndex));}#endregion#region Event/// <summary>/// 上线事件/// </summary>/// <param name="socket"></param>/// <param name="e"></param>private void OnLine_Event(SocketUdpServer socket, EventArgs e){string host = socket.Message;//如果该上线的用户在局域网列表中不存在if (!LanList.CurrentLanList.Exists(x => x.Host == host)){while (!this.IsHandleCreated) ;this.ilbUserList.Invoke(new MyInvoke(this.AddUser), host);//将上线用户添加进静态的局域网列表LanList.CurrentLanList.Add(new LanInfo(){Host = host,State = TalkState.Waiting,RemoteEndPoint = socket.RemoteEndPoint});}}/// <summary>/// 下线事件/// </summary>/// <param name="socket"></param>/// <param name="e"></param>private void DownLine_Event(SocketUdpServer socket, EventArgs e){string host = socket.Message;if (LanList.CurrentLanList.Exists(x => x.Host == host)){///判断是否是自己的主机下线 如果是自己的 则不需要操作if (string.Compare(Dns.GetHostName(), host) != 0){this.ilbUserList.Invoke(new MyInvoke(this.RemoveUser), LanList.CurrentLanList.FindIndex(x => x.Host == host).ToString());//将该用户从局域网列表中移除LanList.CurrentLanList.RemoveAll(x => x.Host == host);}}}/// <summary>/// 出现错误的事件/// </summary>/// <param name="socket"></param>/// <param name="e"></param>private void Error_Event(SocketUdpServer socket, EventArgs e){XtraMessageBox.Show(socket.Message);}private void ilbUserList_DoubleClick(object sender, EventArgs e){//XtraMessageBox.Show(ilbUserList.SelectedItem.ToString());string host = ilbUserList.SelectedItem.ToString();///打开窗口 设置为正在交谈LanList.SetTalkState(host, TalkState.Talking);(new FrmTalk(host)).Show();}/// <summary>/// 窗体关闭事 进行下线广播/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void FrmUser_FormClosed(object sender, FormClosedEventArgs e){this.udpClient.Broadcast(DatagramType.DownLine);this.udpServer.Stop();Application.Exit();}/// <summary>/// 刷新按钮/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnRefresh_Click(object sender, EventArgs e){//刷新  情况列表中的数据  重新上线广播this.ilbUserList.Items.Clear();LanList.CurrentLanList.Clear();this.udpClient.Broadcast(DatagramType.OnLine);}#endregion

 

  该页面主要是在线用户列表页面,同时监听其它软件发来的上线,下线,获取主机信息等数据报,维护当前在线的用户 和聊天状态

View Code
#region Field/// <summary>/// 自己的socket 充当服务器  接收消息/// </summary>private SocketUdpServer selfSocket = null;/// <summary>/// 对话的socket/// </summary>private SocketUdpClient tallSocket = null;/// <summary>/// 谈话对方的局域网信息/// </summary>private LanInfo talkLan = null;/// <summary>/// 当前用户主机/// </summary>private string currentUserHost = "";/// <summary>/// 对控件操作 在非主线程下需要调用此代理/// </summary>private delegate void MyInvoke(string user,string message);#endregion#region Constructor/// <summary>/// 通过远端主机名打开窗体/// </summary>/// <param name="host"></param>public FrmTalk(string host){InitializeComponent();if (this.talkLan == null){ this.talkLan = LanList.CurrentLanList.Find(x => x.Host == host);}this.currentUserHost = Dns.GetHostName();this.Text = "正在和" + host + "聊天中";this.Initializion();}/// <summary>/// 通过远端 端点打开窗体/// </summary>/// <param name="remotePoint"></param>public FrmTalk(EndPoint remotePoint){this.talkLan = LanList.CurrentLanList.Find(x => string.Compare(x.RemoteEndPoint.ToString(), remotePoint.ToString()) == 0);(new FrmTalk(talkLan.Host)).Show();}#endregion#region Method/// <summary>/// 初始化方法/// </summary>private void Initializion(){this.selfSocket = SocketUdpServer.Instance;///绑定收到信息事件this.selfSocket.OnChatComplete += new SocketUdpServer.OnCompleteHander(this.ReceiveEvent);//给谈话的socket初始化endpointthis.tallSocket = new SocketUdpClient(this.talkLan.RemoteEndPoint);}/// <summary>/// 加载未读的信息/// </summary>private void LoadUnReadMessage(){Queue<MessageInfo> queque = QueueMessage.GetAndRemove(talkLan.Host);MessageInfo messageInfo=null;if (queque != null){while (queque.Count > 0){//出队列messageInfo = queque.Dequeue();this.lbxMessage.Items.Add(talkLan.Host + ":" + messageInfo.ReceiveTime.ToString("yyyy-MM-dd HH:mm:ss"));this.lbxMessage.Items.Add(messageInfo.Message);}}}/// <summary>/// 添加一行 在listboxcontrol中/// </summary>/// <param name="name">显示的用户</param>/// <param name="message">消息</param>private void AddLine(string name,string message){this.lbxMessage.Items.Add(name+ ":" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));this.lbxMessage.Items.Add(message);}/// <summary>/// 发送信息 由键盘回车和发送按钮调用/// </summary>private void SendMessage(){try{string message = this.memInput.Text;if (string.IsNullOrEmpty(message)){XtraMessageBox.Show("发送信息不能为空");}else{this.tallSocket.Send(message);this.AddLine("我", message);this.memInput.Text = "";}}catch (Exception ex){XtraMessageBox.Show(ex.Message);}}#endregion#region Event/// <summary>/// 表单加载/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void FrmTalk_Load(object sender, EventArgs e){this.LoadUnReadMessage();}/// <summary>/// 接收信息回调事件/// </summary>/// <param name="socket"></param>/// <param name="e"></param>private void ReceiveEvent(SocketUdpServer socket, EventArgs e){//判断 远端的网络端点是否是当前的 打开的窗体if (string.Compare(this.talkLan.RemoteEndPoint.ToString(), socket.RemoteEndPoint.ToString()) == 0){this.lbxMessage.Invoke(new MyInvoke(this.AddLine), this.talkLan.Host, socket.Message);}}/// <summary>/// 信息发送按钮/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnSend_Click(object sender, EventArgs e){this.SendMessage();}private void FrmTalk_FormClosed(object sender, FormClosedEventArgs e){//将其设置为非交谈状态LanList.SetTalkState(talkLan.Host, TalkState.Waiting);}private void memInput_KeyDown(object sender, KeyEventArgs e){///按下回车事件if (e.KeyCode == Keys.Enter){this.SendMessage();}}#endregion

 

  该页面就是聊天页面,主要是对相应的host进行通信聊天,发送和接收聊天信息,根据聊天窗口设置状态啊之类的

 

View Code
#region Method#region 停止当前监听和断开线程/// <summary>/// 停止当前服务器的监听和断开线程/// </summary>public void Stop(){this.listenThread.Abort();this.listenSocket.Close();}#endregion#region 监听/// <summary>/// 开始监听/// </summary>public void Listen(){ThreadStart method = new ThreadStart(this.ListenMethod);this.listenThread = new Thread(method);this.listenThread.Start();}/// <summary>/// 监听的方法/// </summary>private void ListenMethod(){try{this.listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);IPEndPoint ipep = new IPEndPoint(IPAddress.Any, this.port);this.listenSocket.Bind(ipep);//定义一个网络端点IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);//定义要发送的计算机的地址EndPoint remote = (EndPoint)(sender);//远程///持续监听while (true){byte[] data = new byte[1024];//准备接收int recv = this.listenSocket.ReceiveFrom(data, ref remote);string stringData = Encoding.UTF8.GetString(data, 0, recv);//将接收到的信息转化为自定义的数据报类Datagram recvicedataGram = Datagram.Convert(stringData);this.message = recvicedataGram.Message;string remotePoint = remote.ToString();string remoteip = remotePoint.Substring(0, remotePoint.IndexOf(":"));remote = new IPEndPoint(IPAddress.Parse(remoteip), this.port);this.remoteEndPoint = remote;this.Action(recvicedataGram.Type);}}catch (Exception ex){this.message = ex.Message;this.ErrorAppear(this, new EventArgs());}}/// <summary>/// 收到数据报后的动作/// </summary>/// <param name="type">数据报的类型</param>private void Action(DatagramType type){switch (type){case DatagramType.OnLine:Datagram sendDataGram = new Datagram{Type = DatagramType.GiveInfo,FromAddress = "",ToAddress = "",Message = Dns.GetHostName()};//告诉对方自己的信息this.listenSocket.SendTo(Encoding.UTF8.GetBytes(sendDataGram.ToString()), this.remoteEndPoint);this.OnLineComplete(this, new EventArgs());break;case DatagramType.GiveInfo:///执行添加上线用户事件this.OnLineComplete(this, new EventArgs());break;case DatagramType.DownLine:///执行用户下线事件///如果是自己下线if (string.Compare(Dns.GetHostName(), message) == 0){System.Windows.Forms.Application.Exit();}else{this.DownLineComplete(this, new EventArgs());}break;case DatagramType.Chat://得到当前要交谈的用户LanInfo lanInfo = LanList.CurrentLanList.Find(x => string.Compare(this.remoteEndPoint.ToString(), x.RemoteEndPoint.ToString()) == 0);//如果有查询到该用户在自己这边登记过if (lanInfo != null){if (lanInfo.State == TalkState.Talking){//正在交谈 直接打开这次窗口this.OnChatComplete(this, new EventArgs());}else { //没有交谈 将窗口加入信息的队列MessageInfo messageInfo = new MessageInfo(){Message = this.message,ReceiveTime = DateTime.Now,RemoteEndPoint = this.remoteEndPoint};QueueMessage.Add(lanInfo.Host, messageInfo);}}break;}}#endregion#endregion

 

  充当服务器的 socket的监听,定义一些监听事件,在form里面使用该事件就可以了

View Code
#region Delegate Event/// <summary>/// 完成一个socket的代理/// </summary>/// <param name="sender"></param>/// <param name="e"></param>public delegate void OnCompleteHander(SocketUdpServer sender, EventArgs e);/// <summary>/// 完成收到一个主机信息 即上线事件/// </summary>public event OnCompleteHander OnLineComplete;/// <summary>/// 完成下线事件/// </summary>public event OnCompleteHander DownLineComplete;/// <summary>/// 完成一次谈话  就一条信息/// </summary>public event OnCompleteHander OnChatComplete;/// <summary>/// 有错误出现/// </summary>public event OnCompleteHander ErrorAppear;#endregion

 

  用户上线事件,下线事件,或者主机事件,chat聊天事件,再服务器接收到信息后 感觉信息分类执行不同的事件

     在CHAT类型的数据报重要注意的是,当有数据过来接收到  但是该主机窗口并未打开时,要将要收到信息加入一个未读的信息队列中,当再次开发对该用户的聊天窗口时先要加载相应的未读信息队列,这样可以简单的实现离线信息的发送

接下来看下信息数据报的格式

View Code
/****************************************************************** 定义广播的数据格式* Type=OnLine,FromAdress=xxx,ToAdress=zzz,Message=mmm* 类型为上线广播  从xxx主机到zzz主机  信息是mmm       * CHAT这个就是我的信息我的信息 可能有各种=,的字符串* 这种就直接将CHAT去掉后 后面的都为mmm*****************************************************************//// <summary>/// 定义数据报里面的几个字段/// </summary>public class Datagram{#region Property/// <summary>/// 数据报的类型 ,/// </summary>public DatagramType Type{get;set;}/// <summary>/// 发送者的网络地址/// </summary>public string FromAddress{get;set;}/// <summary>/// 接收者网络地址/// </summary>public string ToAddress{get;set;}/// <summary>/// 数据报的信息/// </summary>public string Message{get;set;}/// <summary>/// 信息 Message的长度/// </summary>public int Length{get {return this.Message.Length;}}#endregion#region Method/// <summary>/// 重写下ToString/// </summary>/// <returns></returns>public override string ToString(){StringBuilder sb = new StringBuilder();sb.AppendFormat("Type={0},", this.Type.ToString());sb.AppendFormat("FromAddress={0},", this.FromAddress.ToString());sb.AppendFormat("ToAddress={0},", this.ToAddress.ToString());sb.AppendFormat("Message={0}", this.Message.ToString());return sb.ToString();}/// <summary>/// 将有效字符串转化成数据报/// </summary>/// <param name="str"></param>/// <returns></returns>public static Datagram Convert(string str){Datagram data = new Datagram();//前面不是CHAT主要是建立连接 取消连接等信号传送if (!str.StartsWith("CHAT")){IDictionary<string, string> idict = new Dictionary<string, string>();string[] strlist = str.Split(',');for (int i = 0; i < strlist.Length; i++){//数据报字符串的各个键值对放进字典类string[] info = strlist[i].Split('=');idict.Add(info[0], info[1]);}data.Type = (DatagramType)Enum.Parse(typeof(DatagramType), idict["Type"]);data.FromAddress = idict["FromAddress"];data.ToAddress=idict["ToAddress"];data.Message = idict["Message"];}else {data.Type = (DatagramType)Enum.Parse(typeof(DatagramType), "Chat");data.Message = str.Substring(4);}return data;}#endregion}#region Enum/// <summary>/// 数据报的类型/// </summary>public enum DatagramType{ /// <summary>/// 上线  一应一答/// </summary>OnLine=1,/// <summary>/// 下线 一应/// </summary>DownLine,/// <summary>/// 确认收到 一应/// </summary>/// <summary>/// 正常聊天 一应一答/// </summary>Chat,/// <summary>/// 给予个人的信息/// </summary>GiveInfo}#endregion

简单的定义一下发送的数据报的格式  可能发送的几种类型:

上线:主要用于软件刚刚开启时向局域网内发送上线广播

下线:软件在关闭之前再向局域网内发送一次下线广播

给出主机信息:用于收到上线广播后  再返回一个自己主机信息给对方,让让对方知道局域网中这台主机是上线的

聊天:就是平常的通信  这里特别注意的是,为考虑到聊天中也会出来,=  这两个协定的字符串,所以 开头加CHAT  表示纯粹聊天的数据报

View Code
/// <summary>/// udp的客户端  主要用户发送数据/// </summary>public class SocketUdpClient{#region Feild/// <summary>/// 广播的socket/// </summary>private Socket broadcastSocket;/// <summary>/// 服务器的端口/// </summary>private int port;/// <summary>/// 远端的端点/// </summary>private EndPoint remoteEndPoint = null;/// <summary>/// 当前客户端/// </summary>private Socket client = null;#endregion#region Constructor/// <summary>/// 构造函数/// </summary>public SocketUdpClient(EndPoint point){this.client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);this.remoteEndPoint = point;}/// <summary>/// 无参构造函数/// </summary>public SocketUdpClient(){this.port = 9050;}#endregion#region 进行广播/// <summary>/// 进行广播 上线或者下线/// </summary>/// <param name="msg">广播中发送的信息</param>public void Broadcast(DatagramType type){this.broadcastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);IPEndPoint iep = new IPEndPoint(IPAddress.Broadcast, this.port);this.broadcastSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);Datagram dataGram = new Datagram{Type = type,FromAddress = "",ToAddress = "",Message = Dns.GetHostName()};//将要发送的信息改为字节流byte[] data = Encoding.ASCII.GetBytes(dataGram.ToString());this.broadcastSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);this.broadcastSocket.SendTo(data, iep);//this.broadcastSocket.Close();
        }#endregion#region Method/// <summary>/// 发送数据/// </summary>/// <param name="message">当前的数据</param>public void Send(string message){byte[] data = Encoding.UTF8.GetBytes("CHAT" + message);int i = client.SendTo(data, this.remoteEndPoint);}#endregion}

socket的client代码  实现广播 发送信息  

 

以上简单的逻辑设计+代码就基本完成了这个简单的客户端聊天软件

说了那么多,接下来看下效果图:

本机这边的效果

局域网中另一端的效果

 可以实现简单的  通讯

下面是源码下载:猛击我去下载它

大家在下载包中可以发现  有两个项目  一个是ITalk,他是我最初在写的时候使用的,窗体时继承dev的,效果稍微好一点

为考虑到各大读者可能没有安装dev,所以又一模一样的改了一个ITalkTradition,传统的winform

还有源码里面有可能socket的tcp  这块,这个主要是因为我刚刚开始的想法是使用tcp,但是后来发现请求在线用户,聊天之类都比较麻烦,就改用了udp,不过  本人有精力的话  还是要去试着写写tcp传输文件 这块

 

这篇文章大致就这样啦,如果大家有什么疑问或者建议赶快留言吧,还有本源码和软件仅供交流学习,用于商业或者实际应用了出了问题概不负责哈

 

 

 

 

 

 

转载于:https://www.cnblogs.com/yyl8781697/archive/2012/12/07/csharp-socket-udp.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461519.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++远征之多态篇——异常处理

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 1、关于异常的一些概念 异常&#xff1a;程序运行期出现的错误。 数组下标越界&#xff1b;除数为0&#xff1b;内存不足&#xff1b;…… 异常处理&#xff1a;对有可能发生异常的地方做出预见性的…

图像传感器之CMOS(2)

转&#xff1a;http://www.elecfans.com/application/Military_avionics/2013/0531/319531.html 提高宇航级图像传感器生产能力 日前&#xff0c;在能量效率方面不断创新的安森美半导体公司已同斯坦福国际研究院&#xff08;SRI&#xff09;和波尔航天科技公司合作&#xff0c;…

c++远征之模板篇——友元函数、友元类

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 一、友元函数 1、分类 全局函数——》友元全局函数 成员函数——》友元成员函数 2、关键字friend 友元全局函数 如下&#xff0c;利用friend修饰的函数&#xff0c;其参数应该是本类的引用或者指…

PHP通过session判断防止表单重复提交实例

PHP通过session判断防止表单重复提交实例 PHP通过session判断防止表单重复提交实例&#xff0c;当用户提交表单后&#xff0c;为防止重复操作&#xff0c;通过session来判断是否为初次提交&#xff0c;否则让他返回到之前表单页面。 当前表单页面is_submit设为0 1 SESSION_STAR…

c++远征之模板篇——静态数据成员,静态成员函数

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 1、静态数据成员 &#xff08;1&#xff09;不同于普通的数据成员&#xff0c;静态数据成员在没有实例化时&#xff0c;它也是存在的&#xff08;即它是和类共存的&#xff09;&#xff1b; &…

c++远征之模板篇——运算符重载

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 一、运算符重载的概念 给原有的运算符赋予新的功能。比如下面的截图&#xff0c;本来加号并不具备坐标的相加的功能&#xff0c;但是通过运算符重载可以实现该功能。 二、运算符重载的本质 本质是…

frp对http协议应用

前言 frp是一个开源的项目, 可用于内网穿透的高性能的反向代理应用&#xff0c;支持 tcp, udp 协议&#xff0c;为 http 和 https 应用协议提供了额外的能力&#xff0c;且尝试性支持了点对点穿透。 github地址&#xff1a;https://github.com/fatedier/frp 此处对http的应用做…

树形列(无限级联下拉列的曲线版本)

先上效果图&#xff1a; 1、列表 - 列表设置 - 创建栏&#xff0c;“类型”选择“托管元数据”&#xff0c;如下图&#xff1a; 2、选中“托管元数据”后&#xff0c;可以到下面编辑需要的树形啦&#xff1a; 3、编辑好&#xff0c;确定&#xff0c;搞定&#xff1b;可以到列表…

c++远征之模板篇——函数模板、类模板

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 函数模板&#xff08;vs模板函数&#xff09; 1、为什么需要模板&#xff1f; 函数体相同&#xff0c;只是类型不一样而已。那么能否把数据的类型当做参数传递呢&#xff1f;肯定是可以的&#xff0…

c++远征之模板篇——标准模板库(STL)

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 常见的设计模板 1、vector&#xff0c;向量 &#xff08;1&#xff09;本质是对数组的封装&#xff1b; &#xff08;2&#xff09;能够在常数时间内完成读取&#xff1b; &#xff08;3&#xf…

数据结构探险——队列篇

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 1、什么是队列&#xff1f; &#xff08;1&#xff09;先入先出的模型&#xff08;FIFO&#xff09;。 &#xff08;2&#xff09;队头&#xff0c;队尾。 &#xff08;3&#xff09;细分为普通队…

数据结构与算法之冒泡排序

转载于:https://www.cnblogs.com/yakun/p/3634457.html

数据结构探险——栈篇

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 1、栈要素 栈底&#xff08;不变&#xff09;、栈顶&#xff08;随着入栈和出栈而改变&#xff09; 2、栈机制的实现 &#xff08;1&#xff09;栈的相关机制 判断栈的空满&#xff1b;入栈、出栈…

windows下修改tomcat的startup.bat脚本文件后台运行

1、修改startup.bat文件 rem Get remaining unshifted command line arguments and save them in the set CMD_LINE_ARGS :setArgs if ""%1"""""" goto doneSetArgs set CMD_LINE_ARGS%CMD_LINE_ARGS% %1 shift goto setArgs :doneSet…

开源框架:CocoaPods 安装学习教程

转载 开源框架:CocoaPods 引言: CocoaPods是一个可以帮你集中管理第三方库的开源项目,运行在Ruby的环境下,基于GitHub托管优势,你可以很方便的查阅目前依赖于CocoaPods的资源. 并且,CocoaPods是可靠,稳定,安全的.可以为你在使用第三方库资源时节省大部分的配置和部署时间.更专心…

SESSION 回收机制

session.gc_maxlifetime session.gc_probability session.gc_divisor session.gc_divisor 与 session.gc_probability 合起来定义了在每个会话初始化时启动 gc&#xff08;garbage collection 垃圾回收&#xff09;进程的概率。此概率用 gc_probability/gc_divisor 计算得来…

数据结构探险——线性表篇

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 1、线性表 概念 机制的实现 2、顺序表 构造函数、析构函数 清空线性表&#xff0c;判空 求当前线性表长度&#xff0c;获取某个序号的元素 定位某个元素的位置 找前驱&#xff08;找后驱类似的&…

Mysql优化之执行计划查看

我们经常说到mysql优化&#xff0c;优化中一种常见的方式就是对于经常查询的字段创建索引。那么mysql中有哪些索引类型呢&#xff1f; 一、索引分类1、普通索引&#xff1a;即一个索引只包含单个列&#xff0c;一个表可以有多个单列索引 2、唯一索引&#xff1a;索引列的值必须…

jmeter+Fiddler:通过Fiddler抓包生成jmeter脚本

Fiddler是目前最常用的抓包工具之一&#xff0c;它作为客户端和服务器端之间的代理&#xff0c;记录客户端和服务器之间的所有请求(http/https)&#xff0c;可以针对特定的请求过滤&#xff0c;分析请求和响应的数据、设置断点、调试、修改请求的数据&#xff0c;甚至可以修改服…

数据结构探险——树篇

以下内容源于慕课网的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 树存在概念中&#xff0c;是对数组或者链表的一种操作方式的概念。 一、与树有关的一些基础概念 &#xff08;1&#xff09;树 有限节点的集合&#xff1b; &#xff08;2&#xff09;度 某个节点的…