[c#源码分享]微风IM V3.1 支持TCP通信发送图片

Sunny5816 2015-03-01 05:24:12
加精
微风IM 采用开源的networkcomms2.3.1c#通信框架
源码 数据库 (数据库和以前一样 没有变动)
前面有好几位朋友说希望微风IM能够支持图片的发送,于是学习了图片发送的一些相关知识,在微风IMV3.1中实现了图片的发送。

如果客户端之间P2P通道已经打通,则直接在客户端之间发送,不经过服务器。

如果P2P通道没有打通,则通过服务器转发。

效果图:


下面简单的介绍一下相关知识

在TCP 通信中,Image类本身不支持序列化。

我们想要发送的话,需要做一些变通。简单的讲,就是在序列化之前把Image类转化为二进制数据,序列化完成后,解析的时候再把二进制数据解析成Image类。

我们使用的是开源的 protobuf.net序列化器。

对IMage图片类进行包装
using System;
using System.Collections.Generic;
using System.Text;
using ProtoBuf;
using System.Drawing;
using System.IO;
using ProtoBuf;

namespace SimpleIM.Business
{
[ProtoContract]
public class ImageWrapper
{
/// <summary>
/// 把Image对象存储为私有的字节数组
/// </summary>
[ProtoMember(1)]
private byte[] _imageData;

/// <summary>
/// 图片名称
/// </summary>
[ProtoMember(2)]
public string ImageName { get; set; }

/// <summary>
/// 图片对象
/// </summary>
public Image Image { get; set; }

/// <summary>
/// 私有的无参数构造函数 反序列化时需要使用
/// </summary>
private ImageWrapper() { }

/// <summary>
/// 创建一个新的 ImageWrapper类
/// </summary>
/// <param name="imageName"></param>
/// <param name="image"></param>
public ImageWrapper(string imageName, Image image)
{
this.ImageName = imageName;
this.Image = image;
}

/// <summary>
///序列化之前,把图片转化为二进制数据
/// </summary>
[ProtoBeforeSerialization]
private void Serialize()
{
if (Image != null)
{
//We need to decide how to convert our image to its raw binary form here
using (MemoryStream inputStream = new MemoryStream())
{
//For basic image types the features are part of the .net framework
Image.Save(inputStream, Image.RawFormat);

//If we wanted to include additional data processing here
//such as compression, encryption etc we can still use the features provided by NetworkComms.Net
//e.g. see DPSManager.GetDataProcessor<LZMACompressor>()

//Store the binary image data as bytes[]
_imageData = inputStream.ToArray();
}
}
}

/// <summary>
/// 反序列化时,把二进制数据转化为图片对象
/// </summary>
[ProtoAfterDeserialization]
private void Deserialize()
{
MemoryStream ms = new MemoryStream(_imageData);

//If we added custom data processes we have the perform the reverse operations here before
//trying to recreate the image object
//e.g. DPSManager.GetDataProcessor<LZMACompressor>()

Image = Image.FromStream(ms);
_imageData = null;
}
}
}

修改一下用于传输聊天信息的契约类,使之包含相关的图片
using System;
using System.Collections.Generic;
using System.Text;
using ProtoBuf;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.ComponentModel;

namespace SimpleIM.Business
{
/// <summary>
/// 此契约类存放聊天对话消息
/// </summary>
[ProtoContract]
public class NewChatContract
{
//用户ID
[ProtoMember(1)]
public string UserID { get; set; }
//用户名
[ProtoMember(2)]
public string UserName { get; set; }
//目标用户ID
[ProtoMember(3)]
public string DestUserID { get; set; }
//目标用户名
[ProtoMember(4)]
public string DestUserName { get; set; }
//聊天的内容,主要是文本消息
[ProtoMember(5)]
public string Content { get; set; }

//发送的时间
[ProtoMember(6)]
public DateTime SendTime { get; set; }

[ProtoMember(7)]
public IList<ImageWrapper> ImageList { get; set; }

//下面这段代码主要是为了防止列表为空,如果列表为空,不加入下面这段代码,序列化会有问题
[DefaultValue(false), ProtoMember(8)]
private bool IsEmptyList
{
get { return ImageList != null && ImageList.Count == 0; }
set { if (value) { ImageList = new List<ImageWrapper>(); } }
}




public NewChatContract()
{ }

public NewChatContract(string userID, string userName, string destUserID, string destUserName, string content, IList<ImageWrapper> imageList, DateTime sendTime)
{
this.UserID = userID;
this.UserName = userName;
this.DestUserID = destUserID;
this.DestUserName = destUserName;
this.Content = content;
this.ImageList = imageList;
this.SendTime = sendTime;
}


}
}


修改ChatControl控件,添加2个按钮

并添加相关代码,具体大家可以看一下源码

需要说明的是,聊天控件使用的是RichTextBox的扩展控件,本来想是否能够提取出RichTextBox中的内容,即包含所有的文字信息和图片信息,然后以发送二进制数据的形式发送,

但是对这方面不太了解,查了好些文章,也没有完后,对这方面比较了解的朋友请指点一下。

后来使用了一个变通的方法,即把文本内容,和图片文件分开发送。

在ChatControl控件中增加了一个字典类变量
public Dictionary<string, Image> imageDict = new Dictionary<string, Image>();

当用户插入图片时,会把图片添加到此字典中。

当用户发送聊天信息时,会提取字典中的图片列表进行发送,并清空图片字典。

点击发送聊天信息时的相关代码:
/   /控件中的图片字典
public Dictionary<string, Image> imageDict = null;
//图片包装类的列表
IList<ImageWrapper> imageWrapperList = new List<ImageWrapper>();

private void chatControl1_BeginToSend(string content)
{
this.chatControl1.ShowMessage(Common.UserName, DateTime.Now, content, true);

imageDict = this.chatControl1.imageDict;

//把控件中的图片字典,添加到图片包装类列表中
foreach (KeyValuePair<string, Image> kv in imageDict)
{
ImageWrapper newWrapper = new ImageWrapper(kv.Key, kv.Value);

imageWrapperList.Add(newWrapper);

}
//清除控件中图片字典的内容
this.chatControl1.ClearImageDic();

//从客户端 Common中获取相应连接
Connection p2pConnection = Common.GetUserConn(this.friendID);

if (p2pConnection != null)
{
NewChatContract chatContract = new NewChatContract();
chatContract.UserID = Common.UserID;
chatContract.UserName = Common.UserName;
chatContract.DestUserID = this.friendID;
chatContract.DestUserName = this.friendID;
chatContract.Content = content;
chatContract.SendTime = DateTime.Now;
chatContract.ImageList = imageWrapperList;
p2pConnection.SendObject("ClientChatMessage", chatContract);
this.chatControl1.Focus();

LogInfo.LogMessage("通过p2p通道发送消息,当前用户ID为"+Common.UserID+"当前Tcp连接端口号"+p2pConnection.ConnectionInfo.LocalEndPoint.Port.ToString (), "P2PINFO");


}
else
{
NewChatContract chatContract = new NewChatContract();
chatContract.UserID = Common.UserID;
chatContract.UserName = Common.UserName;
chatContract.DestUserID = this.friendID;
chatContract.DestUserName = this.friendID;
chatContract.Content = content;
chatContract.SendTime = DateTime.Now;
chatContract.ImageList = imageWrapperList;
Common.TcpConn.SendObject("ChatMessage", chatContract);
this.chatControl1.Focus();

LogInfo.LogMessage("服务器转发消息", "P2PINFO");
}

}

图片的传送是经常用的功能,在其他的程序中也经常用到,稍微改动一下,可以实现客户端拍照片,然后传送到服务器上保存等类似功能。
...全文
5345 44 打赏 收藏 转发到动态 举报
写回复
用AI写文章
44 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_34432051 2017-01-08
  • 打赏
  • 举报
回复
谢谢楼主,,能有源码吗
zlm285998230 2015-11-18
  • 打赏
  • 举报
回复
楼主 这个支持发截图图片的源码链接不存在,可不可以在补发一个哇!
john_QQ:2335298917 2015-07-15
  • 打赏
  • 举报
回复
你的网络通信框架使用VS的哪个版本打开的,我用vs2010和vs2013都打不开啊
RayBreslin 2015-03-21
  • 打赏
  • 举报
回复
支持源码分享!!!!!
tianyiantennas 2015-03-15
  • 打赏
  • 举报
回复
支持源码分享。
Sunny5816 2015-03-12
  • 打赏
  • 举报
回复
微风IM还有很多不成熟的地方,特别是p2p那一部分,可能这种p2p不是一种成熟的方案,感谢大家关注
Sunny5816 2015-03-11
  • 打赏
  • 举报
回复
bob76012 2015-03-10
  • 打赏
  • 举报
回复
对聊天室功能感到兴趣
qnapjiujiu 2015-03-08
  • 打赏
  • 举报
回复
支持源码分享。
程序员鼓励师 2015-03-07
  • 打赏
  • 举报
回复
qq_26356535 2015-03-06
  • 打赏
  • 举报
回复
nice~~
GoodDbye 2015-03-06
  • 打赏
  • 举报
回复
目测很高端,好久没做cs
l123156 2015-03-06
  • 打赏
  • 举报
回复
qq_16386885 2015-03-06
  • 打赏
  • 举报
回复
qq_26358415 2015-03-06
  • 打赏
  • 举报
回复
看看到底怎样~
zk911 2015-03-05
  • 打赏
  • 举报
回复
谢谢分享!!!
zhangke347 2015-03-05
  • 打赏
  • 举报
回复
谢谢分享,好强大,膜拜ing。。
autucu 2015-03-05
  • 打赏
  • 举报
回复
谢谢指教,学些了
qq_26343971 2015-03-05
  • 打赏
  • 举报
回复
牛逼的感觉,虽然不知道楼主说的是什么!
freedomchen718 2015-03-05
  • 打赏
  • 举报
回复
路过了,白忙了一天
加载更多回复(19)

110,560

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧