基于C#Winform的简易聊天程序客户端(3)

来源:互联网 发布:模拟人生4帅哥捏脸数据 编辑:程序博客网 时间:2024/06/05 05:21

基于C#Winform的简易聊天程序客户端程序
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.IO;
namespace ChatClient
{
    public partial class FClient : Form

    {
        public FClient()
        {
            InitializeComponent();
            //关闭对文本框的非法线程操作检查
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }
        //创建 1个客户端套接字 和1个负责监听服务端请求的线程  
        Socket socketClient = null;
        Thread threadClient = null;
        private void btnBeginListen_Click(object sender, EventArgs e)
        {
            //定义一个套字节监听  包含3个参数(IP4寻址协议,流式连接,TCP协议)
            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //获取文本框中的IP地址
            IPAddress ipaddress = IPAddress.Parse(txtIP.Text);
            //将获取的ip地址和端口号绑定到网络节点endpoint上
            IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(txtPort.Text));
            //向指定的ip和端口号的服务端发送连接请求 用的方法是Connect 不是Bind
            socketClient.Connect(endpoint);
            //创建一个新线程 用于监听服务端发来的信息
            threadClient = new Thread(RecMsg);
            //将窗体线程设置为与后台同步
            threadClient.IsBackground = true;
            //启动线程
            threadClient.Start();
            txtMsg.AppendText("已与服务端建立连接,可以开始通信...\r\n");
        }

        /// <summary>
        /// 接受服务端发来信息的方法
        /// </summary>
        private void RecMsg()
        {
            while (true) //持续监听服务端发来的消息
            {
                string strRecMsg = null;
                int length = 0;
                //定义一个10M的内存缓冲区 用于临时性存储接收到的信息
                byte[] arrRecMsg = new byte[10 * 1024 * 1024];
                try
                {
                    //将客户端套接字接收到的字节数组存入内存缓冲区, 并获取其长度
                    length = socketClient.Receive(arrRecMsg);
                }
                catch (Exception ex)
                {
                    txtMsg.AppendText("系统异常消息:" + ex.Message);
                    break;
                }
                //将套接字获取到的字节数组转换为人可以看懂的字符串
                strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                ////将套接字获取到的字节数组转换为人可以看懂的字符串
                //string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                //将文本框输入的信息附加到txtMsg中  并显示 谁,什么时间,换行,发送了什么信息 再换行
                txtMsg.AppendText("天之涯:" + GetCurrentTime() + "\r\n" + strRecMsg + "\r\n");
            }
        }

        /// <summary>
        /// 发送字符串信息到服务端的方法
        /// </summary>
        /// <param name="sendMsg">发送的字符串信息</param>
        private void ClientSendMsg(string sendMsg)
        {
            //将输入的字符串信息转换为机器可以识别的字节数组
            byte[] arrClientMsg = Encoding.UTF8.GetBytes(sendMsg);
            //实际发送的字节数组比实际输入的长度多1 用于存取标识符
            byte[] arrClientSendMsg = new byte[arrClientMsg.Length + 1];
            arrClientSendMsg[0] = 0;  //在索引为0的位置上添加一个标识符
            Buffer.BlockCopy(arrClientMsg, 0, arrClientSendMsg, 1, arrClientMsg.Length);
            //调用客户端套接字发送字节数组
            socketClient.Send(arrClientSendMsg);
            txtMsg.AppendText("SoFlash:" + GetCurrentTime() + "\r\n" + sendMsg + "\r\n");
        }

        //向服务端发送信息
        private void btnSend_Click(object sender, EventArgs e)
        {
            ClientSendMsg(txtCMsg.Text);
        }

        //快捷键 Enter 发送信息
        private void txtCMsg_KeyDown(object sender, KeyEventArgs e)
        {   //当光标位于输入文本框上的情况下 发送信息的热键为回车键Enter 
            if (e.KeyCode == Keys.Enter)
            {
                //则调用客户端向服务端发送信息的方法
                ClientSendMsg(txtCMsg.Text);
            }
        }

        string filePath = null;   //文件的全路径
        string fileName = null;   //文件名称(不包含路径) 
        //选择要发送的文件
        private void btnSelectFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofDialog = new OpenFileDialog();
            if (ofDialog.ShowDialog(this) == DialogResult.OK)
            {
                fileName = ofDialog.SafeFileName; //获取选取文件的文件名
                txtFileName.Text = fileName;      //将文件名显示在文本框上 
                filePath = ofDialog.FileName;     //获取包含文件名的全路径
            }
        }

        /// <summary>
        /// 发送文件的方法
        /// </summary>
        /// <param name="fileFullPath">文件全路径(包含文件名称)</param>
        private void SendFile(string fileFullPath)
        {
            if (fileFullPath == null)
            {
                MessageBox.Show("请选择需要发送的文件!");
                return;
            }
            else if (fileFullPath != null)
            {
                //创建文件流 
                FileStream fs = new FileStream(fileFullPath, FileMode.Open);
                //创建一个内存缓冲区 用于临时存储读取到的文件字节数组
                byte[] arrClientFile = new byte[10 * 1024 * 1024];
                //从文件流中读取文件的字节数组 并将其存入到缓冲区arrClientFile中 
                int realLength = fs.Read(arrClientFile, 0, arrClientFile.Length);  //realLength 为文件的真实长度
                byte[] arrClientSendedFile = new byte[realLength + 1];
                //给新增标识符(实际要发送的)字节数组的索引为0的位置上增加一个标识符1
                arrClientSendedFile[0] = 1;  //告诉机器该发送的字节数组为文件
                //将真实的文件字节数组完全拷贝到需要发送的文件字节数组中,从索引为1的位置开始存放,存放的字节长度为realLength.
                //实际发送的文件字节数组 arrSendedFile包含了2部分 索引为0位置上的标识符1 以及 后面的真实文件字节数组
                Buffer.BlockCopy(arrClientFile, 0, arrClientSendedFile, 1, realLength);
                //调用发送信息的方法 将文件名发送出去
                ClientSendMsg(fileName);
                socketClient.Send(arrClientSendedFile);
                txtMsg.AppendText("SoFlash:" + GetCurrentTime() + "\r\n您发送了文件:" + fileName + "\r\n");
            }

        }

        //点击文件发送按钮 发送文件
        private void btnSendFile_Click(object sender, EventArgs e)
        {
            //发送文件 
            SendFile(filePath);
        }

        /// <summary>
        /// 获取当前系统时间
        /// </summary>
        /// <returns>当前系统时间</returns>
        public DateTime GetCurrentTime()
        {
            DateTime currentTime = new DateTime();
            currentTime = DateTime.Now;
            return currentTime;
        }
    }
}
原创粉丝点击