zoukankan      html  css  js  c++  java
  • 网络聊天软件项目

     

    简单的网络聊天项目,实现了聊天 发文件 功能

    本想打算把代码打包上传的,没找着添加附件的地方  哈哈哈.

    代码如下:

    ------------客户端代码---------------

    ------------客户端代码---------------

    using System;
    using System.Windows.Forms;

    using System.Net.Sockets;
    using System.Net;
    using System.Threading;
    using System.IO;

    namespace MyChatRoomClient
    {
        public partial class FChatClient : Form
        {
            public FChatClient()
            {
                InitializeComponent();
                TextBox.CheckForIllegalCrossThreadCalls = false;
            }
            Thread threadClient = null; //客户端负责接受服务端发来的数据消息线程
            Socket socketClient = null;

            #region 01客户端发送连接请求到服务器+void btnConnect_Click(object sender, EventArgs e)
            //客户端发送连接请求到服务器
            private void btnConnect_Click(object sender, EventArgs e)
            {
                IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
                IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));
                socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //向指定的端口发送连接请求
                socketClient.Connect(endpoint);
                //创建线程 监听服务端发来的消息
                threadClient = new Thread(RecMsg);
                threadClient.IsBackground = true;
                threadClient.Start();

            }
            #endregion

            #region 02监听服务端 发来的消息+void RecMsg()
            /// <summary>
            /// 监听服务端 发来的消息
            /// </summary>
            void RecMsg()
            {
                while (true)
                {
                   
                    //定义一个 接受用的缓存区(2M字节数组)
                    byte[] arrMsgRec = new byte[1024 * 1024 * 2];
                    //将接受到的数据 存入arrMsgRec数组 并返回真正接收到的数据的长度
                    int length = socketClient.Receive(arrMsgRec);
                    //此时是将 数组 所有的元素 都转成字符串, 而真正接受到的 只有服务端发来的几个字符
                    string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length);
                    ShowMsg(strMsgRec);
                }
            }
            #endregion

            #region 03显示消息+void ShowMsg(string msg)
            void ShowMsg(string msg)
            {
                txtMsg.AppendText(msg + " ");
            }
           
            #endregion

            #region 04发送消息到服务器+private void btnSend_Click(object sender, EventArgs e)
            //发送消息到服务器
            private void btnSend_Click(object sender, EventArgs e)
            {
                string strMsg = txtMsgSend.Text.Trim();
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                byte[] arrMsgSend = new byte[arrMsg.Length + 1];
                arrMsgSend[0] = 0; //设置标示符 0 表示文字 文本数据.
                Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length);

                socketClient.Send(arrMsgSend);
                ShowMsg("我说:" + strMsg);
            }
            #endregion


            #region 05选择要发送的文件+void btnChooseFile_Click
            //选择要发送的文件
            private void btnChooseFile_Click(object sender, EventArgs e)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    txtFilePath.Text = ofd.FileName;
                }
            }
             #endregion

            //06向服务端发送文件
            private void btnSendFile_Click(object sender, EventArgs e)
            {
                //用文件流打开 用户选择的文件
                using (FileStream fs = new FileStream(txtFilePath.Text,FileMode.Open))
                {
                    //定义一个2M的数组,缓存区
                    byte[] arrFile = new byte[1024 * 1024 * 2];
                    //将文件数据读到arrFile数组中, 并获得读取的真实数据长度length
                    int length =  fs.Read(arrFile, 0, arrFile.Length);

                    byte[] arrFileSend = new byte[length+1];
                    arrFileSend[0] = 1;//代表发送的文件数据
                    //for (int i = 0; i < length; i++)
                    //{
                    //    arrFileSend[i + 1] = arrFile[i];
                    //}
                    //将arrFile数组里的元素从第0个开始拷贝,拷贝到arrFileSend数组里,从第1个位置开始存放,以供拷贝length个数据
                    Buffer.BlockCopy(arrFile, 0, arrFileSend, 1,length);
                    //发送包含了标识位 的新数据数组 到服务端
                    socketClient.Send(arrFileSend);
                   // arrFile.CopyTo(arrFileSend, length);

                }
            }

        }
    }

    -------------------服务端代码------------------------------

    -------------------服务端代码------------------------------

    using System;
    using System.Windows.Forms;


    using System.Net; //IPAdress,IPEndPoint(ip和端口)类
    using System.Net.Sockets;
    using System.Threading;
    using System.Collections.Generic;
    using System.IO;


    namespace MyChatRoomServer
    {
        public partial class FChatServer : Form
        {
            public FChatServer()
            {
                InitializeComponent();
                TextBox.CheckForIllegalCrossThreadCalls = false;
            }

            Thread threadWatch = null;//负责监听 客户端 连接请求的线程
            Socket socketWatch = null; // 负责监听的套接字

            #region 01服务器启动监听的方法+void btnBeginLisen_Click(object sender, EventArgs e)
            private void btnBeginLisen_Click(object sender, EventArgs e)
            {
               
                //创建 服务端 负责监听的套接字,参数(使用IP4寻址协议,使用流式连接,使用TCP协议传输数据)
                socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //获得文本框中ip地址对象
                IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
                //创建 包含IP 和 端口的 网络节点对象
                IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));

                //将负责监听的套接字绑定到唯一的IP 和端口上
                socketWatch.Bind(endpoint);
                //设置监听队列的长度
                socketWatch.Listen(10);
                //创建负责监听的线程,并传入监听方法
                threadWatch = new Thread(WatchConnection);
                threadWatch.IsBackground = true;
               
                threadWatch.Start();
                ShowMsg("服务器启动监听成功");
              
            }
            #endregion
            //保存了服务器段 所有负责和客户端通信的套接字
            Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
            //保存了服务器端, 所有负责调用 通信套接字.receive方法的线程
            Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();


            #region 02监听客户端请求的方法+void WatchConnection()
            /// <summary>
            /// 监听客户端请求的方法
            /// </summary>
            void WatchConnection()
            {
                while (true) // 持续不断的监听新的客户端的连接请求
                {
                    //开始监听 客户端 连接请求 注意:Accept方法,会阻断当前的线程
                    Socket sokConnection = socketWatch.Accept();// 一旦监听到客户端的请求,就返回一个负责和该客户端通信的套接字
                    //向列表控件中 添加一个客户端的IP端口字符串 作为客户端的唯一标识
                    lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString());
                    //将与客户端通信的 套接字对象sokConnection 添加到键值对集合中 并以客户端IP端口作为键
                    dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);
                  
                    //创建通信线程
                    Thread thr = new Thread(RecMsg);
                    thr.SetApartmentState(ApartmentState.STA);
                    thr.IsBackground = true;
                    //启动先换成 并为线程要调用的方法RecMsg 传入参数sokConnection
                    thr.Start(sokConnection);
                    //将线程 保存在 字典里,方便大家以后做"踢人"功能
                    dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr);

                    ShowMsg("客户端连接成功!" + sokConnection.RemoteEndPoint.ToString());
                }
            }
            #endregion

            #region 03服务端 负责监听 客户端 发来的数据的方法+void RecMsg(object socketClientPara)
            /// <summary>
            /// 服务端 负责监听 客户端 发来的数据的方法
            /// </summary>
            void RecMsg(object socketClientPara)
            {
                Socket socketClient = socketClientPara as Socket;
               
                while (true)
                {
                    byte[] arrMsgRec = new byte[1024 * 1024 * 2];
                    int length = -1;
                    try
                    {
                        length = socketClient.Receive(arrMsgRec);
                    }
                    catch (SocketException ex)
                    {
                        ShowMsg("异常:" + ex.Message);
                        //从 通信套接字集合中删除被中断连接的 通信套接字对象
                        dict.Remove(socketClient.RemoteEndPoint.ToString());
                        //从 通信线程 集合中删除被终端连接的通信线程独享
                        dictThread.Remove(socketClient.RemoteEndPoint.ToString());
                        //从列表中移除 被中断的连接 ip :port
                        lbOnline.Items.Remove(socketClient.RemoteEndPoint.ToString());
                        break;
                    }
                    catch (Exception ex)
                    {
                        ShowMsg("异常:" + ex.Message);
                        break;
                    }
                    if (arrMsgRec[0]==0)//判断发送过来的数据的第一个元素 是0 代表文本文字数据
                    {
                        string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length-1);
                        ShowMsg(strMsgRec);
                    }
                    else if (arrMsgRec[0]==1)//如果是1 代表发送过来的是 文件数据(图片/视频/等等..)
                    {
                        //保存文件选择框对象
                        SaveFileDialog sfd = new SaveFileDialog();
                        if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)//用户选择文件路径后
                        {
                            string fileSavePath = sfd.FileName; //获得要保存的文件路径
                            //创建文件流,然后让文件流根据路径创建一个文件
                            using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
                            {
                                fs.Write(arrMsgRec, 1, length - 1);
                                ShowMsg("文件保存成功"+ fileSavePath);
                            }
                          
                        }

                    }
                   
                }
            }
            #endregion

            #region 04显示消息+ void ShowMsg(string msg)
            void ShowMsg(string msg)
            {
                txtMessage.AppendText(msg + " ");
            }
            #endregion

            #region 05发送消息到客户端+void btnSend_Click(object sender, EventArgs e)
            //发送消息到客户端
            private void btnSend_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(lbOnline.Text))
                {
                    MessageBox.Show("请选择发送的好友!");
                }
                else
                {
                    string strMsg = txtMsgSend.Text.Trim();
                    //将要发送的字符串 转成utf8对应的字节数组
                    byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                    //获得列表中选中的key
                    string strClientKey = lbOnline.Text;
                    //通过key,找到字典集合 中对应的和某个客户端通信的套接字的 send方法,发送数据给对方
                    try
                    {
                        dict[strClientKey].Send(arrMsg);
                        //sokConnection.Send(arrMsg);
                        ShowMsg("发送了数据: " + strMsg);
                        txtMsgSend.Text = string.Empty;
                    }
                    catch (SocketException ex)
                    {
                        ShowMsg("发送时异常:" + ex.Message);
                      
                    }
                    catch (Exception ex)
                    {
                        ShowMsg("发送时异常:" + ex.Message);
                    }
                  
                }
            }
            #endregion

            #region 06服务端群发消息+void btnSendToAll_Click(object sender, EventArgs e)
            //服务端群发消息
            private void btnSendToAll_Click(object sender, EventArgs e)
            {
                string strMsg = txtMsgSend.Text.Trim();
                //将要发送的字符串 转成utf8对应的字节数组
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                foreach (Socket s in dict.Values)
                {
                    s.Send(arrMsg);
                }
                ShowMsg("群发完毕 : )");

            }
            #endregion

           
        }
    }


     

  • 相关阅读:
    I
    poj 3414 pots (bfs+路径记录)
    hdoj 1495 非常可乐(bfs)
    hdoj 1241 Oil Deposits (dfs)
    hdoj 2612 find a way (两次bfs)
    poj 3984 迷宫问题
    poj 3087 Shuffle'm Up (bfs)
    poj 3126 Prime Path (bfs)
    poj 3279 Fliptile
    hdu_3068 最长回文(Manacher算法)
  • 原文地址:https://www.cnblogs.com/chenanzixue/p/3465260.html
Copyright © 2011-2022 走看看