基于C#Winform的简易聊天程序(1)

39 篇文章 1 订阅
1.首先,我们需要写一个选择发送文件的方法,这里使用了最常见OpenFileDialog方法,用于选取需要发送的文件.
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;     //获取包含文件名的全路径  
    }  
}  
2.选取文件之后,通过FileStream来读取文件字节数组,然后在读到的文件字节数组的索引为0的位置上增加了一个文件标识符1,目的是告知计算机该字节数组为文件字节数组.这里在向服务端发送文件的同时也发送了一个文件名(字符串信息),目的是在服务端成功接收文件后,自动将原文件名附加上去.
/// <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("天之涯:" + GetCurrentTime() + "\r\n您发送了文件:" + fileName + "\r\n");  
    }  
}  
由于新增了一个类型标识符,这里便将之前服务端接收信息的方法稍微改了下. 当服务端接收到含有标识符为0的字节数组,则直接将字节数组转换成字符串,并附加到聊天信息文本框上.若接收到的字节数组含有标识符1(即文件),则调用保存文件的方法SaveFile()将其保存为原文件.
string strSRecMsg = null;  
/// <summary>  
/// 接收客户端发来的信息  
/// </summary>  
/// <param name="socketClientPara">客户端套接字的委托对象</param>  
private void ServerRecMsg(object socketClientPara)  
{  
    Socket socketServer = socketClientPara as Socket;  
    while (true)  
    {  
        //创建一个接收用的内存缓冲区 大小为10M字节数组  
        byte[] arrServerRecMsg = new byte[10 * 1024 * 1024];  
        //获取接收的数据,并存入内存缓冲区  返回一个字节数组的长度  
        int length = socketServer.Receive(arrServerRecMsg);  
        //判断发送过来的数据是文件还是普通文字信息  
        if (arrServerRecMsg[0] == 0) //0为文字信息  
        {  
            //将字节数组 转换为人可以读懂的字符串  
            strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 1, length - 1);//真实有用的文本信息要比接收到的少1(标识符)  
            //将接收到的信息附加到文本框txtMsg上    
            txtMsg.AppendText("天之涯:" + GetCurrentTime() + "\r\n" + strSRecMsg + "\r\n");  
        }  
        //如果发送过来的数据是文件  
        if (arrServerRecMsg[0] == 1)  
        {  
            SaveFile(arrServerRecMsg, length - 1);//同样实际文件长度需要-1(减去标识符)  
        }  
    }  
}  
SaveFile()方法里包含了FileStream的Write()方法,用于将接收到的文件字节数组保存为实际文件,这里Write()方法传入了3个参数,文件的字节数组,需要拷贝文件字节数组的初始位置以及拷贝的字节数组的长度.在获取到文件的同时,这里也获取了文件名(字符串信息),用于附加到另存为对话框的文件名上;同时截取了文件名的后缀,作为需要保存的文件类型.最后,在文件成功保存到服务端所在的计算机的同时,在聊天内容文本框中附加了成功接收的文件名和文件的保存路径.
/// <summary>  
/// 保存接收文件的方法 包含一个字节数组参数 和 文件的长度  
/// </summary>  
/// <param name="arrFile">字节数组参数</param>  
/// <param name="fileLength">文件的长度</param>  
private void SaveFile(byte[] arrFile, int fileLength)  
{  
    //创建一个用于保存文件的对话框  
    SaveFileDialog sfDialog = new SaveFileDialog();  
    //获取文件名的后缀 比如文本文件后缀 .txt  
    string fileNameSuffix = strSRecMsg.Substring(strSRecMsg.LastIndexOf("."));  
    sfDialog.Filter = "(*" + fileNameSuffix + ")|*" + fileNameSuffix + ""; //文件类型  
    sfDialog.FileName = strSRecMsg;  //文件名  
    //如果点击了对话框中的保存文件按钮   
    if (sfDialog.ShowDialog(this) == DialogResult.OK)  
    {  
        string savePath = sfDialog.FileName; //获取文件的全路径  
        //保存文件  
        FileStream fs = new FileStream(savePath, FileMode.Create);  
        fs.Write(arrFile, 1, fileLength);  
        string fName = savePath.Substring(savePath.LastIndexOf("\\") + 1); //文件名 不带路径  
        string fPath = savePath.Substring(0, savePath.LastIndexOf("\\")); //文件路径 不带文件名  
        txtMsg.AppendText("SoFlash:" + GetCurrentTime() + "\r\n您成功接收了文件" + fName + "\r\n保存路径为:" + fPath + "\r\n");  
    }  
}  
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值