tcp wcf

                                                                           Wcf tcp

 

我们利用wcf和tcp做一个qq实时在线聊天

 

步骤:1:上线和我们的下线功能

                   2:指定的聊天

                   3:发送文件和字体颜色

 

Wcf和tcp的转换:

         改配置文件:

 

 

我们用控制器启动我们的wcf服务。

         `        创建一个主机  绑定我们的服务ServiceHost  用typeof 绑定我们的服务

                   我们还要写一个事件  就是当通信对象转换到打开的时候我们发生的事件  是为了我们方便知道是否打开了我们的服务器

                   Opened

                   然后打开我们的主机   open();

 

例子

         staticvoid Main(string[] args)

       {

           using (ServiceHost sh = new ServiceHost(typeof(Service1)))          

                   //这里我们要注意using{}这个方法会销毁我们的程序

                   //实列化一个服务器     绑定一个接口typeof(接口)

           {

                sh.Opened += sh_Opened;

                //打开

                sh.Open();

               //暂停不让服务销毁

                Console.ReadLine();

           }

       }

       static void sh_Opened(object sender, EventArgs e)

       {

           Console.WriteLine("服务已经启动;");

       }

 

 

让一个服务器有回调方法:

后台:在接口中设置回调协定的类型     CallbackContract =typeof(回调类)

        回调类中需要返回答复消息 就要设置IsOneWay=true

前台:用服务点出我们的服务主机 ,如果我们的主机有回调我们要服务实例化我们的回调类    InstanceContext

回调类:我们要实现我们服务的回调   如果我们要传值的话我们重构传值

 

 

 

 

 

 

例子:

后台:

接口

  [ServiceContract(CallbackContract=typeof(IQQlogin_callback))]

         回调接口

       [OperationContract(IsOneWay = true)]

        void onlines(users user);

 

前台:

                            //这里我们把本页面给传入过去

            InstanceContext ic = new InstanceContext(new callback_QQ(this));

            // QQ_Service是我们的服务名称

            QQ_Service.QQloginServiceClient lsqq = new QQ_Service.QQloginServiceClient(ic);

 

 

回调类:

 

 

 

    public class callback_QQ : QQ_ .IQQloginServiceCallback

    {

       

        public QQ _qq;

        public callback_QQ(QQ qq)

        {

            this._qq = qq;

        }

        public void onlines(QQ_Service.users user)

        {

        }

        public void offlines(string QQ_numer)

        {

        }

        public void sendmess_callback(QQ_Service.DTO_xiaoxi xiaoxi)

        {

        }

 

    }

 

 

 

1上线和下线

         思路:用户登录访问数据库,登录成功就记录我们用户和用户通道,

                   在用我们的回调函数告诉前面登录的人,我们上线了

 

         我们用DTO来存储数  :一个登陆返回信息 ,一个记录我们信息和通道的,用一个键值对来取出我们对应的通道,一个上线的对象

 

登陆返回的DTO:

         public class DTO_QQ_reuslt<T>

    {

        public int number { get; set; }

 

        public string message { get; set; }

       

        //这个泛型用来记录我们在线的人信息

        public T value { get; set; }

    }

 

 

 

 

具体思路就是:我们一个用户一登录  我们就记录他的信息和回调通道   和上线信息

                                     然后在调用我们的上线的回调通道

 

注意我们这里:就是传值的问题

            InstanceContext ic = new InstanceContext(new callback_QQ(this));

        这里我们传入了一个本页到我们的回调类  

        所以以后的传值问题我们都传到我们,这页  然后再传入到我们 的回调类

 

例子:服务:

public DTO.DTO_QQ_reuslt<DTO_uers> getlogin(string name, string password)

        {

            dbEntities db = new dbEntities();

 

            //得到当前的回调函数

            IQQlogin_callback callback = OperationContext.Current.GetCallbackChannel<IQQlogin_callback>();

 

            //获取当前线程正在关闭的事件

            OperationContext.Current.Channel.Closing += Channel_Closing;

 

           //返回的信息

            DTO.DTO_QQ_reuslt<DTO_uers> result = new DTO.DTO_QQ_reuslt<DTO_uers>();

 

 

            if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(password))

            {

                result.number = 501;

                result.message = "账号或者密码为空";

            }

 

            users user = db.users.Where(a => a.user_name == name && a.user_password == password).FirstOrDefault();

            if (user != null)

            {

                _number = name;

 

                //得到我们在线人信息

                DTO_uers dto = new DTO_uers();

                dto.user = user;

                dto.online = DTO.DTO_chuanshu.dpdic.Values.Select(a => a.qqusers).ToList();

 

                //记录通道

                DTO_QQreacd qqreacd = new DTO_QQreacd();

                qqreacd.qqusers = user;

                qqreacd.qqcallback = callback;

 

 

                result.number = 200;

                result.message = "登陆成功";

                result.value = dto;

 

                //告诉前面的用户我已经登录了

                foreach (var item in DTO.DTO_chuanshu.dpdic.Values)

                {

                    item.qqcallback.onlines(user);

                }

 

                //记录用户信息和用户的通道

                DTO.DTO_chuanshu.dpdic.Add(name, qqreacd);

 

 

            }

            else

            {

                result.number = 201;

                result.message = "账号或者密码错误";

            }

 

            //IQQlogin_callback iqqcallback =OperationContext.Current.GetCallbackChannel<IQQlogin_callback>();

            iqqcallback.login(DTO.DTO_chuanshu.qquers);

 

            return result;

 

        }

 

 

        void Channel_Closing(object sender, EventArgs e)

        {

            //先移除自己的qq帐号

            DTO_chuanshu.dpdic.Remove(_number);

            //传递一个下线的qq帐号

            foreach (var item in DTO.DTO_chuanshu.dpdic.Values)

            {

                item.qqcallback.offlines(_number);

            }

 

 

        }

 

 

 

 

 

发送信息  就和我们的登陆差不多,调用我们的回调通道

 

 

我们发送文件和我们的颜色:

 

发送文件我们用二进制读取,颜色的话我们用ToArgb()把颜色转换成我们的int 类型  然后我们在回调类中用FromArgb()把它弄回来

 

 

例子:客户端

        public async void send_File()

        {

            OpenFileDialog ofd = new OpenFileDialog();

            ofd.ShowDialog();

 

            // MessageBox.Show(ofd.FileName);

            if (string.IsNullOrEmpty(ofd.FileName))

            {

                MessageBox.Show("请选择文件");

                return;

            }

            FileStream fs = new FileStream(ofd.FileName, FileMode.Open);

 

            long alllength = fs.Length;

 

            var offset = 0;  //记录位置

 

            byte[] filebyte = null;

 

            this.progressBar1.Maximum = (int)(fs.Length / 1000);

 

            while (offset != fs.Length)

            {

 

                ///这里我们做一个限速传入

                if (fs.Length - offset <= 1024 * 100)

                {

                    filebyte = new byte[fs.Length - offset];

                }

                else

                {

                    filebyte = new byte[1024 * 100];

                }

 

                //filebyte = new byte[alllength - offset];

                fs.Read(filebyte, 0, filebyte.Length);

 

                sfns = new Send_FileName_Service.Send_FilenameClient();

 

                await sfns.sendfilenameAsync(ofd.SafeFileName, filebyte);

 

                if (jingcheng==0)

                {

                    offset = offset + filebyte.Length;

                }

                if (jingcheng==-1)

                {

                    offset = 0;

                }

           

                this.progressBar1.Value = (offset / 1000);

 

            }

            MessageBox.Show(ofd.FileName + "文件传输完成......");

 

 

        }

 

 

服务:

 

   public void sendfilename(string filename,byte[] bytes)

        {

            string path = "e:/" + filename;

            fs = new FileStream(path, FileMode.Append);

            fs.Write(bytes,0,bytes.Length);

 

            fs.Close();

        }

 

 

 

 

 

 

小技巧如何让一个对象中装入另外一个对象  我们用泛型

                     键值对中也可以用上我们的linp语句

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值